/*=============================================================================#
# Copyright (c) 2007-2016 Stephan Wahlbrink (WalWare.de) 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:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.docmlet.base.ui.processing.actions;
import java.util.List;
import java.util.regex.Matcher;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.bindings.TriggerSequence;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.help.IWorkbenchHelpSystem;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.menus.IWorkbenchContribution;
import org.eclipse.ui.services.IServiceLocator;
import de.walware.jcommons.collections.IdentitySet;
import de.walware.jcommons.collections.ImIdentitySet;
import de.walware.jcommons.collections.ImList;
import de.walware.ecommons.ui.actions.ListContributionItem;
import de.walware.ecommons.ui.actions.SimpleContributionItem;
import de.walware.ecommons.ui.actions.SubMenuContributionItem;
import de.walware.ecommons.ui.util.MessageUtil;
import de.walware.docmlet.base.internal.ui.processing.Messages;
import de.walware.docmlet.base.ui.processing.DocProcessingConfig;
import de.walware.docmlet.base.ui.processing.DocProcessingConfig.Format;
import de.walware.docmlet.base.ui.processing.DocProcessingManager;
import de.walware.docmlet.base.ui.processing.DocProcessingUI;
public class RunConfigsMenuContribution extends ListContributionItem
implements IWorkbenchContribution, IExecutableExtension {
private static class Data {
private final IWorkbenchWindow window;
private final IFile file;
private final DocProcessingManager manager;
private final IBindingService bindingService;
private final ILaunchConfiguration activeConfig;
private final IWorkbenchHelpSystem helpSystem;
private Matcher validExtMatcher;
public Data(final IWorkbenchWindow window, final IServiceLocator serviceLocator,
final IFile file, final DocProcessingManager manager) {
this.window= window;
this.file= file;
this.manager= manager;
this.activeConfig= manager.getActiveConfig();
this.bindingService= (serviceLocator != null) ?
(IBindingService) serviceLocator.getService(IBindingService.class) : null;
this.helpSystem= PlatformUI.getWorkbench().getHelpSystem();
}
}
protected class ConfigContribution extends SubMenuContributionItem implements SelectionListener {
private static final String ACTIVATE= "activate"; //$NON-NLS-1$
private static final String EDIT= "edit"; //$NON-NLS-1$
private final Image icon;
private final String label;
private final ILaunchConfiguration config;
private Data data;
public ConfigContribution(final Image icon, final String label,
final ILaunchConfiguration configuration) {
super();
this.icon= icon;
this.label= label;
this.config= configuration;
}
protected IWorkbenchWindow getWindow() {
return this.data.window;
}
protected IFile getFile() {
return this.data.file;
}
protected DocProcessingManager getManager() {
return this.data.manager;
}
@Override
protected Image getImage() {
return this.icon;
}
@Override
protected String getLabel() {
return this.label;
}
public ILaunchConfiguration getConfiguration() {
return this.config;
}
protected boolean isActive() {
return (this.config == this.data.activeConfig);
}
@Override
protected void fillMenu(final Menu menu) {
addLaunchItems(menu);
{ final MenuItem item= new MenuItem(menu, SWT.RADIO);
item.setText(Messages.ProcessingAction_ActivateConfig_label);
item.setData(ACTIVATE);
item.addSelectionListener(this);
item.setSelection(isActive());
if (this.data.helpSystem != null) {
this.data.helpSystem.setHelp(item, DocProcessingUI.ACTIONS_ACTIVATE_CONFIG_HELP_CONTEXT_ID);
}
}
{ final MenuItem item= new MenuItem(menu, SWT.PUSH);
item.setText(Messages.ProcessingAction_EditConfig_label);
item.setData(EDIT);
item.addSelectionListener(this);
if (this.data.helpSystem != null) {
this.data.helpSystem.setHelp(item, DocProcessingUI.ACTIONS_EDIT_CONFIG_HELP_CONTEXT_ID);
}
}
}
protected void addLaunchItems(final Menu menu) {
}
protected void addLaunchItem(final Menu menu,
final ImIdentitySet<String> launchFlags,
final String actionDetailInfo, final boolean enabled,
String commandId, final String helpContextId) {
if (getMode() != ActionUtil.ACTIVE_EDITOR_MODE) {
commandId= null;
}
final StringBuilder label= getStringBuilder();
label.append(this.data.manager.getActionLabel(launchFlags));
if (actionDetailInfo != null) {
label.append(actionDetailInfo);
}
if (isActive() && commandId != null && this.data.bindingService != null) {
final TriggerSequence binding= this.data.bindingService.getBestActiveBindingFor(commandId);
if (binding != null) {
label.append('\t');
label.append(binding.format());
}
}
final MenuItem item= new MenuItem(menu, SWT.PUSH);
item.setText(label.toString());
item.setImage(this.data.manager.getActionImage(launchFlags));
item.setData(launchFlags);
item.addSelectionListener(this);
item.setEnabled(enabled);
if (this.data.helpSystem != null && helpContextId != null) {
this.data.helpSystem.setHelp(item, helpContextId);
}
}
@Override
public void widgetDefaultSelected(final SelectionEvent e) {
}
@Override
public void widgetSelected(final SelectionEvent e) {
final DocProcessingManager manager= getManager();
final Object data= e.widget.getData();
if (data instanceof ImIdentitySet) {
manager.launch(this.config, getFile(), (ImIdentitySet<String>) data);
return;
}
if (data == ACTIVATE) {
manager.setActiveConfig(this.config);
return;
}
if (data == EDIT) {
final IWorkbenchWindow window= getWindow();
if (getMode() == ActionUtil.ACTIVE_EDITOR_MODE) {
ActionUtil.activateActiveEditor(window);
}
manager.openConfigurationDialog(window.getShell(),
new StructuredSelection(this.config) );
return;
}
}
private Matcher getValidExtMatcher(final String ext) {
if (this.data.validExtMatcher == null) {
this.data.validExtMatcher= DocProcessingConfig.VALID_EXT_PATTERN.matcher(ext);
}
else {
this.data.validExtMatcher.reset(ext);
}
return this.data.validExtMatcher;
}
protected String resolveFormatExt(final Format format, String inputExt) {
if (format == null) {
return null;
}
if (inputExt != null && (inputExt.isEmpty() || !getValidExtMatcher(inputExt).matches())) {
inputExt= null;
}
return format.getExt(inputExt);
}
protected String createDetail(final String inputExt, final String outputExt) {
if (inputExt == null || outputExt == null) {
return null;
}
final StringBuilder sb= getStringBuilder();
sb.append("\u2002["); //$NON-NLS-1$
sb.append(inputExt);
sb.append("\u2002\u2192\u2002"); //$NON-NLS-1$
sb.append(outputExt);
sb.append("]"); //$NON-NLS-1$
return sb.toString();
}
}
private class ConfigureContribution extends SimpleContributionItem {
private final Data data;
public ConfigureContribution(final Data data) {
super(Messages.ProcessingAction_CreateEditConfigs_label, null);
this.data= data;
}
protected IWorkbenchWindow getWindow() {
return this.data.window;
}
protected DocProcessingManager getManager() {
return this.data.manager;
}
@Override
protected void execute(final Event event) throws ExecutionException {
final IWorkbenchWindow window= getWindow();
if (getMode() == ActionUtil.ACTIVE_EDITOR_MODE) {
ActionUtil.activateActiveEditor(window);
}
getManager().openConfigurationDialog(window.getShell(), null);
}
}
private class ShortcutContribution extends SimpleContributionItem {
private Data data;
private final IdentitySet<String> launchFlags;
public ShortcutContribution(final ImageDescriptor icon, final String label,
final IdentitySet<String> launchFlags) {
super(icon, null, label, null);
this.launchFlags= launchFlags;
}
protected DocProcessingManager getManager() {
return this.data.manager;
}
protected IFile getFile() {
return this.data.file;
}
@Override
protected void execute(final Event event) throws ExecutionException {
getManager().launch(this.data.activeConfig, getFile(), this.launchFlags);
}
}
private final ActionUtil util= new ActionUtil(ActionUtil.ACTIVE_MENU_SELECTION_MODE);
private final StringBuilder sBuilder= new StringBuilder(32);
public RunConfigsMenuContribution(final IContentType contentType) {
this.util.setContentType(contentType);
}
/** For instantiation via plugin.xml */
public RunConfigsMenuContribution() {
}
@Override
public void setInitializationData(final IConfigurationElement config, final String propertyName,
final Object data) throws CoreException {
if (data instanceof String) {
switch ((String) data) {
case "activeEditor":
setMode(ActionUtil.ACTIVE_EDITOR_MODE);
break;
case "activeMenuSelection":
setMode(ActionUtil.ACTIVE_MENU_SELECTION_MODE);
break;
default:
break;
}
}
}
protected void setMode(final byte mode) {
this.util.setMode(mode);;
}
protected byte getMode() {
return this.util.getMode();
}
@Override
public void initialize(final IServiceLocator serviceLocator) {
this.util.setServiceLocator(serviceLocator);
}
private StringBuilder getStringBuilder() {
this.sBuilder.setLength(0);
return this.sBuilder;
}
@Override
protected void createContributionItems(final List<IContributionItem> items) {
final IWorkbenchWindow window= this.util.getWindow();
final IFile file= this.util.getFile(window);
final DocProcessingManager manager= this.util.getManager(this.util.getContentType(window, file));
if (manager == null) {
return;
}
final ImList<ILaunchConfiguration> configs= manager.getAvailableConfigs();
final Data data= new Data(window, this.util.getServiceLocator(), file, manager);
if (getMode() != ActionUtil.ACTIVE_EDITOR_MODE && data.activeConfig != null) {
items.add(createContextShortcut(data, DocProcessingUI.CommonFlags.PROCESS_AND_PREVIEW));
items.add(createContextShortcut(data, DocProcessingUI.CommonFlags.PROCESS));
items.add(new Separator());
}
int i= 0;
for (int num= 1; i < configs.size(); i++, num++) {
final ILaunchConfiguration configuration= configs.get(i);
final Image image= manager.getImage(configuration);
String mnemonic= null;
final StringBuilder label= getStringBuilder();
if (num > 0 && num <= 10) {
mnemonic= Integer.toString((num % 10));
label.append('&');
label.append(mnemonic);
label.append(' ');
}
label.append(MessageUtil.escapeForMenu(configuration.getName()));
final ConfigContribution item= createConfigContribution(image, label, configuration);
item.data= data;
items.add(item);
}
if (getMode() == ActionUtil.ACTIVE_EDITOR_MODE || configs.isEmpty()) {
items.add(new ConfigureContribution(data));
}
}
protected ConfigContribution createConfigContribution(
final Image icon, final StringBuilder label,
final ILaunchConfiguration configuration) {
return new ConfigContribution(icon, label.toString(), configuration);
}
private ShortcutContribution createContextShortcut(final Data data,
final IdentitySet<String> launchFlags) {
final Image icon= data.manager.getActionImage(launchFlags);
final String label= data.manager.getLabel(data.activeConfig, launchFlags, false);
return new ShortcutContribution(
(icon != null) ? ImageDescriptor.createFromImage(icon) : null, label,
launchFlags );
}
}