/******************************************************************************* * Copyright (c) 2004, 2011 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 * Ken Sueda - initial prototype *******************************************************************************/ package org.eclipse.mylyn.internal.tasks.ui.editors; import java.util.Collection; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.ControlContribution; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.ui.CommonImages; import org.eclipse.mylyn.commons.ui.SelectionProviderAdapter; import org.eclipse.mylyn.commons.workbench.editors.CommonTextSupport; import org.eclipse.mylyn.internal.tasks.core.AbstractTask; import org.eclipse.mylyn.internal.tasks.core.ITaskListChangeListener; import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; import org.eclipse.mylyn.internal.tasks.core.LocalTask; import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.actions.NewSubTaskAction; import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.ITaskActivityListener; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.TaskData; import org.eclipse.mylyn.tasks.ui.ITasksUiConstants; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; import org.eclipse.mylyn.tasks.ui.editors.TaskEditorInput; import org.eclipse.mylyn.tasks.ui.editors.TaskFormPage; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.IWorkbenchPartConstants; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.IFormPart; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.handlers.IHandlerService; /** * @author Mik Kersten * @author Rob Elves * @author Shawn Minto * @author Steffen Pingel */ public class TaskPlanningEditor extends TaskFormPage { private Composite editorComposite; private TaskRepository repository; private AbstractTask task; private Button saveButton; private final IPropertyListener dirtyStateListener = new IPropertyListener() { public void propertyChanged(Object source, int propId) { if (propId == IWorkbenchPartConstants.PROP_DIRTY && saveButton != null) { saveButton.setEnabled(getEditor().isDirty()); } } }; private final ITaskListChangeListener taskListChangeListener = new TaskListChangeAdapter() { @Override public void containersChanged(Set<TaskContainerDelta> containers) { for (TaskContainerDelta taskContainerDelta : containers) { if (taskContainerDelta.getElement() instanceof ITask) { final AbstractTask updateTask = (AbstractTask) taskContainerDelta.getElement(); if (updateTask != null && task != null && updateTask.getHandleIdentifier().equals(task.getHandleIdentifier())) { if (PlatformUI.getWorkbench() != null && !PlatformUI.getWorkbench().isClosing()) { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { refresh(); } }); } break; } } } } }; private CommonTextSupport textSupport; private ITaskActivityListener timingListener; private FormToolkit toolkit; private FocusTracker focusTracker; public TaskPlanningEditor(TaskEditor editor) { super(editor, ITasksUiConstants.ID_PAGE_PLANNING, Messages.TaskPlanningEditor_Planning); TasksUiInternal.getTaskList().addChangeListener(taskListChangeListener); } private void createContributions(final Composite editorComposite) { Collection<LocalTaskEditorContributionDescriptor> localEditorContributions = TaskEditorContributionExtensionReader.getLocalEditorContributions(); for (final LocalTaskEditorContributionDescriptor descriptor : localEditorContributions) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable e) { StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Error creating task editor contribution: \"" + descriptor.getId() + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$ } public void run() throws Exception { AbstractLocalEditorPart part = descriptor.createPart(); initializePart(editorComposite, part); } }); } } @Override protected void createFormContent(IManagedForm managedForm) { super.createFormContent(managedForm); TaskEditorInput taskEditorInput = (TaskEditorInput) getEditorInput(); task = (AbstractTask) taskEditorInput.getTask(); repository = TasksUi.getRepositoryManager().getRepository(task.getConnectorKind(), task.getRepositoryUrl()); toolkit = managedForm.getToolkit(); editorComposite = managedForm.getForm().getBody(); GridLayout layout = new GridLayout(); layout.verticalSpacing = 0; editorComposite.setLayout(layout); if (task instanceof LocalTask) { SummaryPart part = new SummaryPart(); part.setTextSupport(textSupport); initializePart(editorComposite, part); initializePart(editorComposite, new AttributePart()); // currently there is only one location for extensions createContributions(editorComposite); } PlanningPart planningPart = new PlanningPart(SWT.NONE); // disable due date picker if it's a repository due date boolean needsDueDate = true; if (task != null) { try { TaskData taskData = TasksUi.getTaskDataManager().getTaskData(task); if (taskData != null) { AbstractRepositoryConnector connector = TasksUi.getRepositoryConnector(taskData.getConnectorKind()); TaskRepository taskRepository = TasksUi.getRepositoryManager().getRepository( taskData.getConnectorKind(), taskData.getRepositoryUrl()); if (connector != null && taskRepository != null && connector.hasRepositoryDueDate(taskRepository, task, taskData)) { needsDueDate = false; } } } catch (CoreException e) { // ignore } } planningPart.initialize(getManagedForm(), repository, task, needsDueDate, this, textSupport); planningPart.createControl(editorComposite, toolkit); planningPart.getSection().setLayoutData(new GridData(GridData.FILL_BOTH)); getManagedForm().addPart(planningPart); focusTracker = new FocusTracker(); focusTracker.track(editorComposite); } @Override public void dispose() { getEditor().removePropertyListener(dirtyStateListener); if (timingListener != null) { TasksUiPlugin.getTaskActivityManager().removeActivityListener(timingListener); } TasksUiInternal.getTaskList().removeChangeListener(taskListChangeListener); super.dispose(); } @Override public void doSave(IProgressMonitor monitor) { super.doSave(monitor); // update task title TasksUiInternal.getTaskList().notifyElementChanged(task); } @Override public void doSaveAs() { // don't support saving as } /** * Override for customizing the tool bar. */ @Override public void fillToolBar(IToolBarManager toolBarManager) { TaskEditorInput taskEditorInput = (TaskEditorInput) getEditorInput(); ITask task = taskEditorInput.getTask(); if (task instanceof LocalTask && task.getAttribute(ITasksCoreConstants.ATTRIBUTE_OUTGOING_NEW_CONNECTOR_KIND) == null) { NewSubTaskAction newSubTaskAction = new NewSubTaskAction(); newSubTaskAction.selectionChanged(newSubTaskAction, new StructuredSelection(task)); if (newSubTaskAction.isEnabled()) { toolBarManager.add(newSubTaskAction); } } } @Override public TaskEditor getEditor() { return (TaskEditor) super.getEditor(); } @Override public void init(IEditorSite site, IEditorInput input) { super.init(site, input); this.textSupport = new CommonTextSupport((IHandlerService) getSite().getService(IHandlerService.class)); this.textSupport.setSelectionChangedListener((TaskEditorActionContributor) getEditorSite().getActionBarContributor()); site.setSelectionProvider(new SelectionProviderAdapter(new StructuredSelection( ((TaskEditorInput) input).getTask()))); } private void initializePart(final Composite editorComposite, final AbstractLocalEditorPart part) { part.initialize(getManagedForm(), repository, task); Control control = part.createControl(editorComposite, toolkit); part.setControl(control); GridDataFactory.fillDefaults().grab(true, false).applyTo(control); getManagedForm().addPart(part); } @Override public boolean isSaveAsAllowed() { return false; } @Override public void refresh() { if (getManagedForm() == null || getManagedForm().getForm().isDisposed()) { // editor possibly closed return; } getEditor().updateHeaderToolBar(); IFormPart[] parts = getManagedForm().getParts(); // refresh will not be invoked unless parts are stale for (IFormPart part : parts) { if (part instanceof AbstractLocalEditorPart) { ((AbstractLocalEditorPart) part).refresh(false); } else { part.refresh(); } } getManagedForm().reflow(true); } public void fillLeftHeaderToolBar(IToolBarManager toolBarManager) { if (getEditorInput() instanceof TaskEditorInput && ((TaskEditorInput) getEditorInput()).getTask() instanceof LocalTask) { ControlContribution submitButtonContribution = new ControlContribution( "org.eclipse.mylyn.tasks.toolbars.save") { //$NON-NLS-1$ @Override protected Control createControl(Composite parent) { saveButton = new Button(parent, SWT.FLAT); saveButton.setText(Messages.TaskPlanningEditor_Save); saveButton.setImage(CommonImages.getImage(CommonImages.SAVE)); saveButton.setBackground(null); saveButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { doSave(new NullProgressMonitor()); } }); saveButton.setEnabled(getEditor().isDirty()); return saveButton; } }; getEditor().addPropertyListener(dirtyStateListener); toolBarManager.add(submitButtonContribution); } } @Override public void setFocus() { if (focusTracker.setFocus()) { return; } else { IFormPart[] parts = getManagedForm().getParts(); if (parts.length > 0) { parts[0].setFocus(); return; } } super.setFocus(); } }