| /******************************************************************************* |
| * Copyright (c) 2012 Rushan R. Gilmullin and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Rushan R. Gilmullin - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.osbp.vaaclipse.contributions; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| |
| import javax.inject.Inject; |
| |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.core.contexts.RunAndTrack; |
| import org.eclipse.e4.core.di.annotations.Execute; |
| import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer; |
| import org.eclipse.e4.ui.model.application.MApplication; |
| import org.eclipse.e4.ui.model.application.ui.MContext; |
| import org.eclipse.e4.ui.model.application.ui.MUIElement; |
| import org.eclipse.e4.ui.model.application.ui.menu.MMenu; |
| import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution; |
| import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; |
| import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator; |
| import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu; |
| import org.eclipse.e4.ui.workbench.modeling.EModelService; |
| import org.eclipse.osbp.vaaclipse.api.MenuContributionService; |
| |
| /** |
| * @author rushan |
| * |
| */ |
| public class MenuContributionProcessor implements MenuContributionService { |
| @Inject |
| MApplication application; |
| @Inject |
| EModelService modelService; |
| |
| private Map<MMenuElement, ArrayList<ContributionRecord>> sharedElementToRecord = new HashMap<MMenuElement, ArrayList<ContributionRecord>>(); |
| |
| @Execute |
| public void start(IEclipseContext context) { |
| context.set(MenuContributionService.class, this); |
| } |
| |
| @Override |
| public void addContributions(MMenu menu) { |
| processContributions(menu, menu instanceof MPopupMenu); |
| } |
| |
| /** |
| * @param menuModel |
| * @param isMenuBar |
| * @param isPopup |
| */ |
| private void processContributions(MMenu menuModel, boolean isPopup) { |
| if (menuModel.getElementId() == null) { |
| return; |
| } |
| final ArrayList<MMenuContribution> toContribute = new ArrayList<MMenuContribution>(); |
| ContributionsAnalyzer.XXXgatherMenuContributions(menuModel, |
| application.getMenuContributions(), menuModel.getElementId(), |
| toContribute, null, isPopup); |
| generateContributions(menuModel, toContribute); |
| // for (MMenuElement element : menuModel.getChildren()) { |
| // if (element instanceof MMenu) { |
| // processContributions((MMenu) element, isPopup); |
| // } |
| // } |
| } |
| |
| /** |
| * @param menuModel |
| * @param toContribute |
| */ |
| private void generateContributions(MMenu menuModel, |
| ArrayList<MMenuContribution> toContribute) { |
| HashSet<String> existingMenuIds = new HashSet<String>(); |
| HashSet<String> existingSeparatorNames = new HashSet<String>(); |
| for (MMenuElement child : menuModel.getChildren()) { |
| String elementId = child.getElementId(); |
| if (child instanceof MMenu && elementId != null) { |
| existingMenuIds.add(elementId); |
| } else if (child instanceof MMenuSeparator && elementId != null) { |
| existingSeparatorNames.add(elementId); |
| } |
| } |
| |
| boolean done = toContribute.size() == 0; |
| while (!done) { |
| ArrayList<MMenuContribution> curList = new ArrayList<MMenuContribution>( |
| toContribute); |
| int retryCount = toContribute.size(); |
| toContribute.clear(); |
| |
| for (MMenuContribution menuContribution : curList) { |
| if (!processAddition(menuModel, menuContribution, |
| existingMenuIds, existingSeparatorNames)) { |
| toContribute.add(menuContribution); |
| } |
| } |
| |
| // We're done if the retryList is now empty (everything done) or |
| // if the list hasn't changed at all (no hope) |
| done = (toContribute.size() == 0) |
| || (toContribute.size() == retryCount); |
| } |
| } |
| |
| /** |
| * @param menuModel |
| * @param manager |
| * @param menuContribution |
| * @return true if the menuContribution was processed |
| */ |
| private boolean processAddition(MMenu menuModel, |
| MMenuContribution menuContribution, |
| final HashSet<String> existingMenuIds, |
| HashSet<String> existingSeparatorNames) { |
| final ContributionRecord record = new ContributionRecord(menuModel, |
| menuContribution, this); |
| if (!record.mergeIntoModel()) { |
| return false; |
| } |
| |
| final IEclipseContext parentContext = modelService |
| .getContainingContext(menuModel); |
| parentContext.runAndTrack(new RunAndTrack() { |
| @Override |
| public boolean changed(IEclipseContext context) { |
| record.updateVisibility(parentContext.getActiveLeaf()); |
| return true; |
| } |
| }); |
| |
| return true; |
| } |
| |
| ArrayList<ContributionRecord> getList(MMenuElement item) { |
| ArrayList<ContributionRecord> tmp = sharedElementToRecord.get(item); |
| if (tmp == null) { |
| tmp = new ArrayList<ContributionRecord>(); |
| sharedElementToRecord.put(item, tmp); |
| } |
| return tmp; |
| } |
| |
| public void removeContributions(MMenu menu) { |
| |
| } |
| |
| IEclipseContext getContext(MUIElement element) { |
| if (element instanceof MContext) { |
| return ((MContext) element).getContext(); |
| } |
| return modelService.getContainingContext(element); |
| } |
| } |