/*******************************************************************************
* Copyright (c) 2010, 2015 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
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 472654
******************************************************************************/
package org.eclipse.e4.ui.internal.workbench.addons;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.core.commands.Category;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.CommandManager;
import org.eclipse.core.commands.CommandManagerEvent;
import org.eclipse.core.commands.ICommandManagerListener;
import org.eclipse.core.commands.IParameter;
import org.eclipse.core.commands.ParameterType;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.e4.core.commands.ECommandService;
import org.eclipse.e4.core.commands.internal.HandlerServiceImpl;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.internal.workbench.Activator;
import org.eclipse.e4.ui.internal.workbench.Parameter;
import org.eclipse.e4.ui.internal.workbench.Policy;
import org.eclipse.e4.ui.model.LocalizationHelper;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.commands.MCategory;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.e4.ui.model.application.commands.MCommandParameter;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
/**
* Process commands in the model, feeding them into the command service.
*/
public class CommandProcessingAddon {
@Inject
private ECommandService commandService;
@Inject
private CommandManager commandManager;
@Inject
private MApplication application;
@Inject
private IEventBroker broker;
@Inject
private EModelService modelService;
private Category undefinedCategory;
private EventHandler additionHandler;
private ICommandManagerListener cmListener;
/**
* @param cmd
* @param modelService
* @param categoryModel
* @return a command model element
* @throws NotDefinedException
*/
public static MCommand createCommand(Command cmd, EModelService modelService,
final MCategory categoryModel) throws NotDefinedException {
MCommand command = modelService.createModelElement(MCommand.class);
command.setElementId(cmd.getId());
command.setCategory(categoryModel);
command.setCommandName(cmd.getName());
command.setDescription(cmd.getDescription());
// deal with parameters
// command.getParameters().addAll(parameters);
IParameter[] cmdParms = cmd.getParameters();
if (cmdParms != null) {
for (IParameter cmdParm : cmdParms) {
MCommandParameter parmModel = modelService
.createModelElement(MCommandParameter.class);
parmModel.setElementId(cmdParm.getId());
parmModel.setName(cmdParm.getName());
parmModel.setOptional(cmdParm.isOptional());
ParameterType parmType = cmd.getParameterType(cmdParm.getId());
if (parmType != null) {
parmModel.setTypeId(parmType.getId());
}
command.getParameters().add(parmModel);
}
}
return command;
}
@PostConstruct
public void init() {
if (Policy.DEBUG_CMDS) {
Activator.trace(Policy.DEBUG_CMDS_FLAG, "Initialize commands from model", null); //$NON-NLS-1$
}
undefinedCategory = commandService.defineCategory(MApplication.class.getName(),
"Application Category", null); //$NON-NLS-1$
createCategories();
createCommands();
registerModelListeners();
registerCommandListener();
}
@PreDestroy
public void dispose() {
unregisterCommandListener();
unregsiterModelListeners();
}
private void registerModelListeners() {
additionHandler = new EventHandler() {
@Override
public void handleEvent(Event event) {
if (application == event.getProperty(UIEvents.EventTags.ELEMENT)) {
if (UIEvents.isADD(event)) {
for (Object obj : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) {
if (obj instanceof MCommand) {
createCommand((MCommand) obj);
} else if (obj instanceof MCategory) {
createCategory((MCategory) obj);
}
}
}
}
}
};
broker.subscribe(UIEvents.Application.TOPIC_COMMANDS, additionHandler);
broker.subscribe(UIEvents.Application.TOPIC_CATEGORIES, additionHandler);
}
private void unregsiterModelListeners() {
broker.unsubscribe(additionHandler);
broker.unsubscribe(additionHandler);
}
private void registerCommandListener() {
cmListener = new ICommandManagerListener() {
@SuppressWarnings("restriction")
@Override
public void commandManagerChanged(CommandManagerEvent commandManagerEvent) {
if (commandManagerEvent.isCommandChanged()) {
if (commandManagerEvent.isCommandDefined()) {
final String commandId = commandManagerEvent.getCommandId();
if (findCommand(commandId) != null) {
return;
}
final Command command = commandManagerEvent.getCommandManager().getCommand(
commandId);
if (command.getHandler() == null) {
command.setHandler(HandlerServiceImpl.getHandler(commandId));
}
try {
MCategory categoryModel = findCategory(command.getCategory().getId());
final MCommand createdCommand = createCommand(command, modelService,
categoryModel);
application.getCommands().add(createdCommand);
} catch (NotDefinedException e) {
Activator.getDefault().getLogService()
.log(0, "Failed to create command " + commandId, e); //$NON-NLS-1$
}
}
}
}
};
commandManager.addCommandManagerListener(cmListener);
}
private void unregisterCommandListener() {
commandManager.removeCommandManagerListener(cmListener);
}
protected MCommand findCommand(String commandId) {
for (MCommand cmd : application.getCommands()) {
if (commandId.equals(cmd.getElementId())) {
return cmd;
}
}
return null;
}
protected MCategory findCategory(String id) {
final List<MCategory> categories = application.getCategories();
for (MCategory cat : categories) {
if (id.equals(cat.getElementId())) {
return cat;
}
}
return null;
}
private void createCommands() {
for (MCommand cmdModel : application.getCommands()) {
createCommand(cmdModel);
}
}
private void createCommand(MCommand cmdModel) {
IParameter[] parms = null;
String id = cmdModel.getElementId();
String name = localize(cmdModel.getCommandName(), cmdModel);
String desc = localize(cmdModel.getDescription(), cmdModel);
List<MCommandParameter> modelParms = cmdModel.getParameters();
if (modelParms != null && !modelParms.isEmpty()) {
ArrayList<Parameter> parmList = new ArrayList<>();
for (MCommandParameter cmdParm : modelParms) {
ParameterType parameterType = null;
if (cmdParm.getTypeId() != null && cmdParm.getTypeId().length() > 0) {
parameterType = commandManager.getParameterType(cmdParm.getTypeId());
}
parmList.add(new Parameter(cmdParm.getElementId(), cmdParm.getName(), null,
parameterType, cmdParm.isOptional()));
}
parms = parmList.toArray(new Parameter[parmList.size()]);
}
Category cat = undefinedCategory;
if (cmdModel.getCategory() != null) {
cat = commandService.getCategory(cmdModel.getCategory().getElementId());
}
commandService.defineCommand(id, name, desc, cat, parms,
cmdModel.getPersistedState().get("HelpContextId")); //$NON-NLS-1$
}
private void createCategories() {
for (MCategory catModel : application.getCategories()) {
createCategory(catModel);
}
}
private void createCategory(MCategory catModel) {
Category category = commandService.getCategory(catModel.getElementId());
if (!category.isDefined()) {
category.define(localize(catModel.getName(), catModel),
localize(catModel.getDescription(), catModel));
}
}
/**
* Attempt to localize the provided key. Return the localized variant if found or the key itself
* otherwise.
*
* @param key
* the possible key reference
* @param modelElement
* the defining model element
* @return the localized variant if found, or the key
*/
private String localize(String key, MApplicationElement modelElement) {
if (key == null) {
return null;
}
String localized = LocalizationHelper.getLocalized(key, modelElement);
return localized == null ? key : localized;
}
}