/******************************************************************************* * Copyright (c) 2009, 2015 Tasktop Technologies 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: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.tasks.ui.actions; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.internal.tasks.core.AbstractTask; import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory; import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector; import org.eclipse.mylyn.internal.tasks.core.TaskCategory; import org.eclipse.mylyn.internal.tasks.core.UncategorizedTaskContainer; import org.eclipse.mylyn.internal.tasks.ui.IDynamicSubMenuContributor; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.actions.CopyTaskDetailsAction.Mode; import org.eclipse.mylyn.internal.tasks.ui.views.Messages; import org.eclipse.mylyn.internal.tasks.ui.views.UpdateRepositoryConfigurationAction; import org.eclipse.mylyn.tasks.core.IRepositoryElement; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.ITaskContainer; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.menus.IMenuService; import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; /** * @author Steffen Pingel */ public class RepositoryElementActionGroup { protected static final String ID_SEPARATOR_NEW = "new"; //$NON-NLS-1$ private static final String ID_SEPARATOR_OPERATIONS = "operations"; //$NON-NLS-1$ private static final String ID_SEPARATOR_TASKS = "tasks"; //$NON-NLS-1$ protected static final String ID_SEPARATOR_REPOSITORY = "repository"; //$NON-NLS-1$ private static final String ID_SEPARATOR_PROPERTIES = "properties"; //$NON-NLS-1$ protected static final String ID_SEPARATOR_NAVIGATE = "navigate"; //$NON-NLS-1$ private static final String ID_SEPARATOR_OPEN = "open"; //$NON-NLS-1$ private static final String ID_SEPARATOR_SHOW_IN = "showIn"; //$NON-NLS-1$ protected static final String ID_SEPARATOR_EDIT = "edit"; //$NON-NLS-1$ private final CopyTaskDetailsAction copyUrlAction; private final CopyTaskDetailsAction copyKeyAction; private final CopyTaskDetailsAction copyKeySummaryAction; private final CopyTaskDetailsAction copyKeySummaryURLAction; private final OpenTaskListElementAction openAction; private final OpenWithBrowserAction openWithBrowserAction; private final DeleteAction deleteAction; private final DeleteTaskEditorAction deleteTaskEditorAction; private final RemoveFromCategoryAction removeFromCategoryAction; private final ShowInSearchViewAction showInSearchViewAction; private final ShowInTaskListAction showInTaskListAction; private final TaskActivateAction activateAction; private final TaskDeactivateAction deactivateAction; private ISelectionProvider selectionProvider; private final List<ISelectionChangedListener> actions; private final AutoUpdateQueryAction autoUpdateAction; private final NewSubTaskAction newSubTaskAction; private final CloneTaskAction cloneTaskAction; public RepositoryElementActionGroup() { actions = new ArrayList<ISelectionChangedListener>(); newSubTaskAction = add(new NewSubTaskAction()); cloneTaskAction = add(new CloneTaskAction()); activateAction = add(new TaskActivateAction()); deactivateAction = new TaskDeactivateAction(); copyKeyAction = add(new CopyTaskDetailsAction(Mode.KEY)); copyUrlAction = add(new CopyTaskDetailsAction(Mode.URL)); copyKeySummaryAction = add(new CopyTaskDetailsAction(Mode.ID_SUMMARY)); copyKeySummaryURLAction = add(new CopyTaskDetailsAction(Mode.ID_SUMMARY_URL)); if (!isInEditor()) { copyKeySummaryURLAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY); } removeFromCategoryAction = add(new RemoveFromCategoryAction()); deleteAction = add(new DeleteAction()); deleteTaskEditorAction = add(new DeleteTaskEditorAction()); openAction = add(new OpenTaskListElementAction()); openWithBrowserAction = add(new OpenWithBrowserAction()); showInSearchViewAction = add(new ShowInSearchViewAction()); showInTaskListAction = add(new ShowInTaskListAction()); autoUpdateAction = add(new AutoUpdateQueryAction()); } protected <T extends ISelectionChangedListener> T add(T action) { actions.add(action); return action; } public void setSelectionProvider(ISelectionProvider selectionProvider) { if (this.selectionProvider != null) { for (ISelectionChangedListener action : actions) { this.selectionProvider.removeSelectionChangedListener(action); } } this.selectionProvider = selectionProvider; if (selectionProvider != null) { for (ISelectionChangedListener action : actions) { this.selectionProvider.addSelectionChangedListener(action); ISelection selection = selectionProvider.getSelection(); if (selection == null) { selection = StructuredSelection.EMPTY; } action.selectionChanged(new SelectionChangedEvent(selectionProvider, selection)); } } } public void fillContextMenu(final IMenuManager manager) { manager.add(new Separator(ID_SEPARATOR_NEW)); // new, schedule manager.add(new GroupMarker(ID_SEPARATOR_NAVIGATE)); // mark, go into, go up manager.add(new Separator(ID_SEPARATOR_OPEN)); // open, activate manager.add(new GroupMarker(ID_SEPARATOR_SHOW_IN)); // open, activate manager.add(new Separator(ID_SEPARATOR_EDIT)); // cut, copy paste, delete, rename manager.add(new Separator(ID_SEPARATOR_TASKS)); // move to manager.add(new GroupMarker(ID_SEPARATOR_OPERATIONS)); // repository properties, import/export, context manager.add(new Separator(ID_SEPARATOR_REPOSITORY)); // synchronize manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); manager.add(new Separator(ID_SEPARATOR_PROPERTIES)); // properties final ITaskContainer element; IStructuredSelection selection = getSelection(); final Object firstSelectedObject = selection.getFirstElement(); if (firstSelectedObject instanceof ITaskContainer) { element = (ITaskContainer) firstSelectedObject; } else { element = null; } final List<IRepositoryElement> selectedElements = getSelectedTaskContainers(selection); AbstractTask task = null; if (element instanceof ITask) { task = (AbstractTask) element; } if (!isInTaskList()) { MenuManager newSubMenu = new MenuManager(Messages.RepositoryElementActionGroup_New); if (newSubTaskAction.isEnabled()) { newSubMenu.add(newSubTaskAction); } if (cloneTaskAction.isEnabled()) { newSubMenu.add(new Separator()); newSubMenu.add(cloneTaskAction); } manager.appendToGroup(ID_SEPARATOR_NEW, newSubMenu); } if (element instanceof ITask && !isInEditor()) { addAction(ID_SEPARATOR_OPEN, openAction, manager, element); } if (openWithBrowserAction.isEnabled()) { manager.appendToGroup(ID_SEPARATOR_OPEN, openWithBrowserAction); } showInSearchViewAction.selectionChanged(selection); if (showInSearchViewAction.isEnabled()) { manager.appendToGroup(ID_SEPARATOR_OPEN, showInSearchViewAction); } showInTaskListAction.selectionChanged(selection); if (showInTaskListAction.isEnabled() && !isInTaskList()) { manager.appendToGroup(ID_SEPARATOR_OPEN, showInTaskListAction); } if (task != null) { if (task.isActive()) { manager.appendToGroup(ID_SEPARATOR_SHOW_IN, deactivateAction); } else { manager.appendToGroup(ID_SEPARATOR_SHOW_IN, activateAction); } } if (!selection.isEmpty()) { MenuManager copyDetailsSubMenu = new MenuManager( Messages.RepositoryElementActionGroup_Copy_Detail_Menu_Label, CopyTaskDetailsAction.ID); copyDetailsSubMenu.add(copyKeyAction); copyDetailsSubMenu.add(copyUrlAction); copyDetailsSubMenu.add(copyKeySummaryAction); copyDetailsSubMenu.add(copyKeySummaryURLAction); copyDetailsSubMenu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); IMenuService menuService = PlatformUI.getWorkbench().getService(IMenuService.class); menuService.populateContributionManager(copyDetailsSubMenu, "menu:" + CopyTaskDetailsAction.ID); //$NON-NLS-1$ manager.appendToGroup(ID_SEPARATOR_EDIT, copyDetailsSubMenu); } if (isInTaskList() && !selection.isEmpty()) { manager.appendToGroup(ID_SEPARATOR_EDIT, deleteAction); } if (isInEditor()) { manager.appendToGroup(ID_SEPARATOR_TASKS, deleteTaskEditorAction); } removeFromCategoryAction.selectionChanged(selection); removeFromCategoryAction.setEnabled(isRemoveFromCategoryEnabled(selectedElements)); if (removeFromCategoryAction.isEnabled()) { manager.appendToGroup(ID_SEPARATOR_EDIT, removeFromCategoryAction); } if (autoUpdateAction.isEnabled()) { manager.appendToGroup(ID_SEPARATOR_REPOSITORY, autoUpdateAction); } if (element instanceof IRepositoryQuery) { EditRepositoryPropertiesAction repositoryPropertiesAction = new EditRepositoryPropertiesAction(); repositoryPropertiesAction.selectionChanged(new StructuredSelection(element)); if (repositoryPropertiesAction.isEnabled()) { MenuManager subMenu = new MenuManager(Messages.TaskListView_Repository); manager.appendToGroup(ID_SEPARATOR_OPERATIONS, subMenu); UpdateRepositoryConfigurationAction resetRepositoryConfigurationAction = new UpdateRepositoryConfigurationAction(); resetRepositoryConfigurationAction.selectionChanged(new StructuredSelection(element)); subMenu.add(resetRepositoryConfigurationAction); subMenu.add(new Separator()); subMenu.add(repositoryPropertiesAction); } } Map<String, List<IDynamicSubMenuContributor>> dynamicMenuMap = TasksUiPlugin.getDefault().getDynamicMenuMap(); for (final String menuPath : dynamicMenuMap.keySet()) { for (final IDynamicSubMenuContributor contributor : dynamicMenuMap.get(menuPath)) { SafeRunnable.run(new ISafeRunnable() { public void handleException(Throwable e) { StatusHandler .log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Menu contributor failed")); //$NON-NLS-1$ } public void run() throws Exception { MenuManager subMenuManager = contributor.getSubMenuManager(selectedElements); if (subMenuManager != null) { addMenuManager(menuPath, subMenuManager, manager, element); } } }); } } } private boolean isInTaskList() { return (this instanceof TaskListViewActionGroup); } private IStructuredSelection getSelection() { ISelection selection = (selectionProvider != null) ? selectionProvider.getSelection() : null; if (selection instanceof IStructuredSelection) { return (IStructuredSelection) selection; } return StructuredSelection.EMPTY; } private boolean isInEditor() { return (this instanceof TaskEditorActionGroup); } private boolean isRemoveFromCategoryEnabled(final List<IRepositoryElement> selectedElements) { if (selectedElements.isEmpty()) { return false; } for (IRepositoryElement element : selectedElements) { if (element instanceof AbstractTask) { boolean hasCategory = false; for (ITaskContainer container : ((AbstractTask) element).getParentContainers()) { if (container instanceof TaskCategory) { hasCategory = true; } if (container instanceof UncategorizedTaskContainer && !LocalRepositoryConnector.CONNECTOR_KIND .equals(((AbstractTask) element).getConnectorKind())) { hasCategory = true; } } if (!hasCategory) { return false; } } else { return false; } } return true; } private void addMenuManager(String path, IMenuManager menuToAdd, IMenuManager manager, ITaskContainer element) { if (element instanceof ITask || element instanceof IRepositoryQuery) { manager.appendToGroup(path, menuToAdd); } } private void addAction(String path, Action action, IMenuManager manager, ITaskContainer element) { action.setEnabled(false); if (element != null) { updateActionEnablement(action, element); } manager.appendToGroup(path, action); } // TODO move the enablement to the action classes private void updateActionEnablement(Action action, ITaskContainer element) { if (element instanceof ITask) { if (action instanceof OpenTaskListElementAction) { action.setEnabled(true); } else if (action instanceof CopyTaskDetailsAction) { action.setEnabled(true); } else if (action instanceof RenameAction) { action.setEnabled(true); } } else if (element != null) { if (action instanceof GoIntoAction) { TaskCategory cat = (TaskCategory) element; if (cat.getChildren().size() > 0) { action.setEnabled(true); } else { action.setEnabled(false); } } else if (action instanceof OpenTaskListElementAction) { action.setEnabled(true); } else if (action instanceof CopyTaskDetailsAction) { action.setEnabled(true); } else if (action instanceof RenameAction) { if (element instanceof AbstractTaskCategory) { AbstractTaskCategory container = (AbstractTaskCategory) element; action.setEnabled(container.isUserManaged()); } else if (element instanceof IRepositoryQuery) { action.setEnabled(true); } } } else { action.setEnabled(true); } } public List<IRepositoryElement> getSelectedTaskContainers(IStructuredSelection selection) { List<IRepositoryElement> selectedElements = new ArrayList<IRepositoryElement>(); for (Iterator<?> i = selection.iterator(); i.hasNext();) { Object object = i.next(); if (object instanceof ITaskContainer) { selectedElements.add((IRepositoryElement) object); } } return selectedElements; } public OpenTaskListElementAction getOpenAction() { return openAction; } public TaskActivateAction getActivateAction() { return activateAction; } public DeleteAction getDeleteAction() { return deleteAction; } public CopyTaskDetailsAction getCopyDetailsAction() { return copyKeySummaryURLAction; } }