/*******************************************************************************
 * Copyright (c) 2004, 2015 Tasktop Technologies and others.
 * 
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * https://www.eclipse.org/legal/epl-2.0
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Tasktop Technologies - initial API and implementation
 *     David Green - fixes for bug 237503
 *     Frank Becker - fixes for bug 252300
 *	   Kevin Sawicki - fixes for bug 306029
 *******************************************************************************/

package org.eclipse.mylyn.tasks.ui.editors;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
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.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.util.LocalSelectionTransfer;
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.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.ui.CommonImages;
import org.eclipse.mylyn.commons.ui.CommonUiUtil;
import org.eclipse.mylyn.commons.ui.GradientCanvas;
import org.eclipse.mylyn.commons.workbench.editors.CommonTextSupport;
import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil;
import org.eclipse.mylyn.internal.tasks.core.AbstractTaskContainer;
import org.eclipse.mylyn.internal.tasks.core.ITaskListChangeListener;
import org.eclipse.mylyn.internal.tasks.core.ITaskListRunnable;
import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta;
import org.eclipse.mylyn.internal.tasks.core.data.ITaskDataManagerListener;
import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManagerEvent;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.actions.ClearOutgoingAction;
import org.eclipse.mylyn.internal.tasks.ui.actions.DeleteTaskEditorAction;
import org.eclipse.mylyn.internal.tasks.ui.actions.NewSubTaskAction;
import org.eclipse.mylyn.internal.tasks.ui.actions.OpenWithBrowserAction;
import org.eclipse.mylyn.internal.tasks.ui.actions.SynchronizeEditorAction;
import org.eclipse.mylyn.internal.tasks.ui.editors.AbstractTaskEditorSection;
import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil;
import org.eclipse.mylyn.internal.tasks.ui.editors.FocusTracker;
import org.eclipse.mylyn.internal.tasks.ui.editors.Messages;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskAttachmentDropListener;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorActionContributor;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorActionPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorAttachmentPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorAttributePart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorCommentPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorContributionExtensionReader;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorDescriptionPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorFindSupport;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorNewCommentPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorOutlineNode;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorOutlinePage;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorPeoplePart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorPlanningPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorRichTextPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorSummaryPart;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskMigrator;
import org.eclipse.mylyn.internal.tasks.ui.editors.ToolBarButtonContribution;
import org.eclipse.mylyn.internal.tasks.ui.util.AttachmentUtil;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
import org.eclipse.mylyn.tasks.core.IRepositoryElement;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITask.SynchronizationState;
import org.eclipse.mylyn.tasks.core.RepositoryStatus;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.ITaskDataWorkingCopy;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.eclipse.mylyn.tasks.core.data.TaskDataModel;
import org.eclipse.mylyn.tasks.core.data.TaskDataModelEvent;
import org.eclipse.mylyn.tasks.core.data.TaskDataModelListener;
import org.eclipse.mylyn.tasks.core.data.TaskRelation;
import org.eclipse.mylyn.tasks.core.sync.SubmitJob;
import org.eclipse.mylyn.tasks.core.sync.SubmitJobEvent;
import org.eclipse.mylyn.tasks.core.sync.SubmitJobListener;
import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi;
import org.eclipse.mylyn.tasks.ui.TasksUi;
import org.eclipse.mylyn.tasks.ui.TasksUiImages;
import org.eclipse.mylyn.tasks.ui.TasksUiUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.forms.FormColors;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.services.IDisposable;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;

/**
 * Extend to provide a task editor page.
 *
 * @author Mik Kersten
 * @author Rob Elves
 * @author Steffen Pingel
 * @since 3.0
 */
public abstract class AbstractTaskEditorPage extends TaskFormPage
		implements ISelectionProvider, ISelectionChangedListener {

	/**
	 * Causes the form page to reflow on resize.
	 */
	private final class ParentResizeHandler implements Listener {
		private int generation;

		public void handleEvent(Event event) {
			++generation;

			Display.getCurrent().timerExec(300, new Runnable() {
				int scheduledGeneration = generation;

				public void run() {
					if (getManagedForm().getForm().isDisposed()) {
						return;
					}

					// only reflow if this is the latest generation to prevent
					// unnecessary reflows while the form is being resized
					if (scheduledGeneration == generation) {
						getManagedForm().reflow(true);
					}
				}
			});
		}
	}

	private class SubmitTaskJobListener extends SubmitJobListener {

		private final boolean attachContext;

		private final boolean expandLastComment;

		public SubmitTaskJobListener(boolean attachContext, boolean expandLastComment) {
			this.attachContext = attachContext;
			this.expandLastComment = expandLastComment;
		}

		@Override
		public void done(SubmitJobEvent event) {
			final SubmitJob job = event.getJob();
			PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {

				private void addTask(ITask newTask) {
					AbstractTaskContainer parent = null;
					AbstractTaskEditorPart actionPart = getPart(ID_PART_ACTIONS);
					if (actionPart instanceof TaskEditorActionPart) {
						parent = ((TaskEditorActionPart) actionPart).getCategory();
					}
					TasksUiInternal.getTaskList().addTask(newTask, parent);
				}

				public void run() {
					try {
						if (job.getStatus() == null) {
							TasksUiInternal.synchronizeRepositoryInBackground(getTaskRepository());
							if (job.getTask().equals(getTask())) {
								refresh();
							} else {
								ITask oldTask = getTask();
								ITask newTask = job.getTask();
								addTask(newTask);

								TaskMigrator migrator = new TaskMigrator(oldTask);
								migrator.setDelete(true);
								migrator.setEditor(getTaskEditor());
								migrator.setMigrateDueDate(
										!connector.hasRepositoryDueDate(getTaskRepository(), newTask, taskData));
								migrator.execute(newTask);
							}
							if (expandLastComment) {
								expandLastComment();
							}
						}
						handleTaskSubmitted(new SubmitJobEvent(job));
					} finally {
						showEditorBusy(false);
					}
				}
			});
		}

		@Override
		public void taskSubmitted(SubmitJobEvent event, IProgressMonitor monitor) throws CoreException {
			if (!getModel().getTaskData().isNew() && attachContext) {
				TaskData taskData = getModel().getTaskData();
				TaskAttribute taskAttribute = null;
				if (taskData != null) {
					taskAttribute = taskData.getRoot().createMappedAttribute(TaskAttribute.NEW_ATTACHMENT);
				}
				AttachmentUtil.postContext(connector, getModel().getTaskRepository(), task, "", taskAttribute, monitor); //$NON-NLS-1$
			}
		}

		@Override
		public void taskSynchronized(SubmitJobEvent event, IProgressMonitor monitor) {
		}

	}

	private final ITaskDataManagerListener TASK_DATA_LISTENER = new ITaskDataManagerListener() {

		public void taskDataUpdated(final TaskDataManagerEvent event) {
			ITask task = event.getTask();
			if (task.equals(AbstractTaskEditorPage.this.getTask()) && event.getTaskDataUpdated()) {
				refresh(task);
			}
		}

		private void refresh(final ITask task) {
			PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
				public void run() {
					if (refreshDisabled || busy) {
						return;
					}

					if (!isDirty() && task.getSynchronizationState() == SynchronizationState.SYNCHRONIZED) {
						// automatically refresh if the user has not made any changes and there is no chance of missing incomings
						AbstractTaskEditorPage.this.refresh();
					} else {
						getTaskEditor().setMessage(Messages.AbstractTaskEditorPage_Task_has_incoming_changes,
								IMessageProvider.WARNING, new HyperlinkAdapter() {
									@Override
									public void linkActivated(HyperlinkEvent e) {
										AbstractTaskEditorPage.this.refresh();
									}
								});
						setSubmitEnabled(false);
					}
				}
			});
		}

		public void editsDiscarded(TaskDataManagerEvent event) {
			if (event.getTask().equals(AbstractTaskEditorPage.this.getTask())) {
				refresh(event.getTask());
			}
		}
	};

	private class NotInTaskListListener extends HyperlinkAdapter implements ITaskListChangeListener, IDisposable {

		public NotInTaskListListener() {
			TasksUiPlugin.getTaskList().addChangeListener(this);
		}

		@Override
		public void linkActivated(HyperlinkEvent e) {
			TasksUiPlugin.getTaskList().addTaskIfAbsent(task);
			getTaskEditor().setMessage(null, IMessageProvider.NONE);
		}

		public void containersChanged(Set<TaskContainerDelta> containers) {
			// clears message if task is added to Task List.
			for (TaskContainerDelta taskContainerDelta : containers) {
				if (task.equals(taskContainerDelta.getElement())) {
					if (taskContainerDelta.getKind().equals(TaskContainerDelta.Kind.ADDED)) {
						PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
							public void run() {
								getTaskEditor().setMessage(null, IMessageProvider.NONE);
							}
						});
					}
				}
			}
		}

		public void dispose() {
			TasksUiPlugin.getTaskList().removeChangeListener(this);
		}

	};

	private class MenuCreator implements IMenuCreator {

		private MenuManager menuManager;

		private Menu menu;

		public MenuCreator() {
		}

		public void dispose() {
			if (menu != null) {
				menu.dispose();
				menu = null;
			}
			if (menuManager != null) {
				menuManager.dispose();
				menuManager = null;
			}
		}

		public Menu getMenu(Control parent) {
			if (menuManager == null) {
				menuManager = new MenuManager();
				initialize(menuManager);
			}
			return menuManager.createContextMenu(parent);
		}

		public Menu getMenu(Menu parent) {
			return null;
		}

		protected void initialize(MenuManager menuManager) {
		}

	}

	private static final String ERROR_NOCONNECTIVITY = Messages.AbstractTaskEditorPage_Unable_to_submit_at_this_time;

	public static final String ID_PART_ACTIONS = "org.eclipse.mylyn.tasks.ui.editors.parts.actions"; //$NON-NLS-1$

	public static final String ID_PART_ATTACHMENTS = "org.eclipse.mylyn.tasks.ui.editors.parts.attachments"; //$NON-NLS-1$

	public static final String ID_PART_ATTRIBUTES = "org.eclipse.mylyn.tasks.ui.editors.parts.attributes"; //$NON-NLS-1$

	public static final String ID_PART_COMMENTS = "org.eclipse.mylyn.tasks.ui.editors.parts.comments"; //$NON-NLS-1$

	public static final String ID_PART_DESCRIPTION = "org.eclipse.mylyn.tasks.ui.editors.parts.descriptions"; //$NON-NLS-1$

	public static final String ID_PART_NEW_COMMENT = "org.eclipse.mylyn.tasks.ui.editors.parts.newComment"; //$NON-NLS-1$

	public static final String ID_PART_PEOPLE = "org.eclipse.mylyn.tasks.ui.editors.parts.people"; //$NON-NLS-1$

	public static final String ID_PART_PLANNING = "org.eclipse.mylyn.tasks.ui.editors.parts.planning"; //$NON-NLS-1$

	public static final String ID_PART_SUMMARY = "org.eclipse.mylyn.tasks.ui.editors.parts.summary"; //$NON-NLS-1$

	public static final String PATH_ACTIONS = "actions"; //$NON-NLS-1$

	/**
	 * @since 3.7
	 */
	public static final String PATH_ASSOCIATIONS = "associations"; //$NON-NLS-1$

	public static final String PATH_ATTACHMENTS = "attachments"; //$NON-NLS-1$

	public static final String PATH_ATTRIBUTES = "attributes"; //$NON-NLS-1$

	public static final String PATH_COMMENTS = "comments"; //$NON-NLS-1$

	public static final String PATH_HEADER = "header"; //$NON-NLS-1$

	public static final String PATH_PEOPLE = "people"; //$NON-NLS-1$

	public static final String PATH_PLANNING = "planning"; //$NON-NLS-1$

	private AttributeEditorFactory attributeEditorFactory;

	private AttributeEditorToolkit attributeEditorToolkit;

	private AbstractRepositoryConnector connector;

	private final String connectorKind;

	private StructuredSelection defaultSelection;

	private Composite editorComposite;

	private ScrolledForm form;

	private boolean busy;

	private ISelection lastSelection;

	private TaskDataModel model;

	private boolean needsAddToCategory;

	private boolean reflow;

	private volatile boolean refreshDisabled;

	private final ListenerList selectionChangedListeners;

	private SynchronizeEditorAction synchronizeEditorAction;

	private ITask task;

	private TaskData taskData;

	private FormToolkit toolkit;

	private TaskEditorOutlinePage outlinePage;

	private TaskAttachmentDropListener defaultDropListener;

	private CommonTextSupport textSupport;

	private Composite partControl;

	private GradientCanvas footerComposite;

	private boolean needsFooter;

	private Button submitButton;

	private boolean submitEnabled;

	private boolean needsSubmit;

	private boolean needsSubmitButton;

	private boolean needsPrivateSection;

	private FocusTracker focusTracker;

	private TaskEditorFindSupport findSupport;

	/**
	 * @since 3.1
	 */
	public AbstractTaskEditorPage(TaskEditor editor, String id, String label, String connectorKind) {
		super(editor, id, label);
		Assert.isNotNull(connectorKind);
		this.connectorKind = connectorKind;
		this.reflow = true;
		this.selectionChangedListeners = new ListenerList();
		this.submitEnabled = true;
		this.needsSubmit = true;
	}

	public AbstractTaskEditorPage(TaskEditor editor, String connectorKind) {
		this(editor, "id", "label", connectorKind); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * @since 3.1
	 * @see FormPage#getEditor()
	 */
	@Override
	public TaskEditor getEditor() {
		return (TaskEditor) super.getEditor();
	}

	public void addSelectionChangedListener(ISelectionChangedListener listener) {
		selectionChangedListeners.add(listener);
	}

	public void appendTextToNewComment(String text) {
		AbstractTaskEditorPart newCommentPart = getPart(ID_PART_NEW_COMMENT);
		if (newCommentPart instanceof TaskEditorRichTextPart) {
			((TaskEditorRichTextPart) newCommentPart).appendText(text);
			newCommentPart.setFocus();
		}
	}

	public boolean canPerformAction(String actionId) {
		if (findSupport != null && actionId.equals(ActionFactory.FIND.getId())) {
			return true;
		}
		return CommonTextSupport.canPerformAction(actionId, EditorUtil.getFocusControl(this));
	}

	public void close() {
		if (Display.getCurrent() != null) {
			getSite().getPage().closeEditor(getTaskEditor(), false);
		} else {
			// TODO consider removing asyncExec()
			Display activeDisplay = getSite().getShell().getDisplay();
			activeDisplay.asyncExec(new Runnable() {
				public void run() {
					if (getSite() != null && getSite().getPage() != null && !getManagedForm().getForm().isDisposed()) {
						if (getTaskEditor() != null) {
							getSite().getPage().closeEditor(getTaskEditor(), false);
						} else {
							getSite().getPage().closeEditor(AbstractTaskEditorPage.this, false);
						}
					}
				}
			});
		}
	}

	protected AttributeEditorFactory createAttributeEditorFactory() {
		return new AttributeEditorFactory(getModel(), getTaskRepository(), getEditorSite());
	}

	AttributeEditorToolkit createAttributeEditorToolkit() {
		return new AttributeEditorToolkit(textSupport);
	}

	@Override
	public void createPartControl(Composite parent) {
		parent.addListener(SWT.Resize, new ParentResizeHandler());

		if (needsFooter()) {
			partControl = getEditor().getToolkit().createComposite(parent);
			GridLayout partControlLayout = new GridLayout(1, false);
			partControlLayout.marginWidth = 0;
			partControlLayout.marginHeight = 0;
			partControlLayout.verticalSpacing = 0;
			partControl.setLayout(partControlLayout);

			super.createPartControl(partControl);
			getManagedForm().getForm().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

			footerComposite = new GradientCanvas(partControl, SWT.NONE);
			footerComposite.setSeparatorVisible(true);
			footerComposite.setSeparatorAlignment(SWT.TOP);
			GridLayout headLayout = new GridLayout();
			headLayout.marginHeight = 0;
			headLayout.marginWidth = 0;
			headLayout.horizontalSpacing = 0;
			headLayout.verticalSpacing = 0;
			headLayout.numColumns = 1;
			footerComposite.setLayout(headLayout);
			footerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

			FormColors colors = getEditor().getToolkit().getColors();
			Color top = colors.getColor(IFormColors.H_GRADIENT_END);
			Color bottom = colors.getColor(IFormColors.H_GRADIENT_START);
			footerComposite.setBackgroundGradient(new Color[] { bottom, top }, new int[] { 100 }, true);

			footerComposite.putColor(IFormColors.H_BOTTOM_KEYLINE1, colors.getColor(IFormColors.H_BOTTOM_KEYLINE1));
			footerComposite.putColor(IFormColors.H_BOTTOM_KEYLINE2, colors.getColor(IFormColors.H_BOTTOM_KEYLINE2));
			footerComposite.putColor(IFormColors.H_HOVER_LIGHT, colors.getColor(IFormColors.H_HOVER_LIGHT));
			footerComposite.putColor(IFormColors.H_HOVER_FULL, colors.getColor(IFormColors.H_HOVER_FULL));
			footerComposite.putColor(IFormColors.TB_TOGGLE, colors.getColor(IFormColors.TB_TOGGLE));
			footerComposite.putColor(IFormColors.TB_TOGGLE_HOVER, colors.getColor(IFormColors.TB_TOGGLE_HOVER));
			footerComposite.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));

			createFooterContent(footerComposite);
		} else {
			super.createPartControl(parent);
		}
	}

	@Override
	protected void createFormContent(final IManagedForm managedForm) {
		super.createFormContent(managedForm);
		form = managedForm.getForm();

		toolkit = managedForm.getToolkit();
		registerDefaultDropListener(form);
		CommonFormUtil.disableScrollingOnFocus(form);

		try {
			setReflow(false);

			editorComposite = form.getBody();
			// TODO consider using TableWrapLayout, it makes resizing much faster
			GridLayout editorLayout = new GridLayout();
			editorLayout.verticalSpacing = 0;
			editorComposite.setLayout(editorLayout);
			editorComposite.setMenu(getTaskEditor().getMenu());

			AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(getConnectorKind());
			if (connectorUi == null) {
				PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
					public void run() {
						getTaskEditor().setMessage(
								Messages.AbstractTaskEditorPage_Synchronize_to_update_editor_contents,
								IMessageProvider.INFORMATION, new HyperlinkAdapter() {
									@Override
									public void linkActivated(HyperlinkEvent e) {
										AbstractTaskEditorPage.this.refresh();
									}
								});
					}
				});
			}

			if (taskData != null) {
				createFormContentInternal();
			}

			updateHeaderMessage();
		} finally {
			setReflow(true);

			// if the editor is restored as part of workbench startup then we must reflow() asynchronously
			// otherwise the editor layout is incorrect
			boolean reflowRequired = calculateReflowRequired(form);

			if (reflowRequired) {
				Display.getCurrent().asyncExec(new Runnable() {
					public void run() {
						// this fixes a problem with layout that occurs when an editor
						// is restored before the workbench is fully initialized
						reflow();
					}
				});
			}
		}
	}

	private boolean calculateReflowRequired(ScrolledForm form) {
		Composite stopComposite = getEditor().getEditorParent().getParent().getParent();
		Composite composite = form.getParent();
		while (composite != null) {
			Rectangle clientArea = composite.getClientArea();
			if (clientArea.width > 1) {
				return false;
			}
			if (composite == stopComposite) {
				return true;
			}
			composite = composite.getParent();
		}
		return true;
	}

	private void createFormContentInternal() {
		// end life-cycle of previous editor controls
		if (attributeEditorToolkit != null) {
			attributeEditorToolkit.dispose();
		}

		// start life-cycle of previous editor controls
		if (attributeEditorFactory == null) {
			attributeEditorFactory = createAttributeEditorFactory();
			Assert.isNotNull(attributeEditorFactory);
		}
		attributeEditorToolkit = createAttributeEditorToolkit();
		Assert.isNotNull(attributeEditorToolkit);
		attributeEditorToolkit.setMenu(editorComposite.getMenu());
		attributeEditorFactory.setEditorToolkit(attributeEditorToolkit);

		createParts();

		focusTracker = new FocusTracker();
		focusTracker.track(editorComposite);
	}

	protected TaskDataModel createModel(TaskEditorInput input) throws CoreException {
		ITaskDataWorkingCopy taskDataState;
		try {
			taskDataState = TasksUi.getTaskDataManager().getWorkingCopy(task);
		} catch (OperationCanceledException e) {
			// XXX retry once to work around bug 235479
			taskDataState = TasksUi.getTaskDataManager().getWorkingCopy(task);
		}
		TaskRepository taskRepository = TasksUi.getRepositoryManager().getRepository(taskDataState.getConnectorKind(),
				taskDataState.getRepositoryUrl());

		return new TaskDataModel(taskRepository, input.getTask(), taskDataState);
	}

	/**
	 * To suppress a section, just remove its descriptor from the list. To add your own section in a specific order on
	 * the page, use the path value for where you want it to appear (your descriptor will appear after previously added
	 * descriptors with the same path), and add it to the descriptors list in your override of this method.
	 */
	protected Set<TaskEditorPartDescriptor> createPartDescriptors() {
		Set<TaskEditorPartDescriptor> descriptors = new LinkedHashSet<TaskEditorPartDescriptor>();
		descriptors.add(new TaskEditorPartDescriptor(ID_PART_SUMMARY) {
			@Override
			public AbstractTaskEditorPart createPart() {
				return new TaskEditorSummaryPart();
			}
		}.setPath(PATH_HEADER));
		descriptors.add(new TaskEditorPartDescriptor(ID_PART_ATTRIBUTES) {
			@Override
			public AbstractTaskEditorPart createPart() {
				return new TaskEditorAttributePart();
			}
		}.setPath(PATH_ATTRIBUTES));
		if (!taskData.isNew() && connector.getTaskAttachmentHandler() != null
				&& (AttachmentUtil.canDownloadAttachment(task) || AttachmentUtil.canUploadAttachment(task))) {
			descriptors.add(new TaskEditorPartDescriptor(ID_PART_ATTACHMENTS) {
				@Override
				public AbstractTaskEditorPart createPart() {
					return new TaskEditorAttachmentPart();
				}
			}.setPath(PATH_ATTACHMENTS));
		}
		if (needsPrivateSection() || taskData.isNew()) {
			descriptors.add(new TaskEditorPartDescriptor(ID_PART_PLANNING) {
				@Override
				public AbstractTaskEditorPart createPart() {
					return new TaskEditorPlanningPart();
				}
			}.setPath(PATH_PLANNING));
		}
		descriptors.add(new TaskEditorPartDescriptor(ID_PART_DESCRIPTION) {
			@Override
			public AbstractTaskEditorPart createPart() {
				TaskEditorDescriptionPart part = new TaskEditorDescriptionPart();
				if (getModel().getTaskData().isNew()) {
					part.setExpandVertically(true);
					part.setSectionStyle(ExpandableComposite.TITLE_BAR | ExpandableComposite.EXPANDED);
				}
				return part;
			}
		}.setPath(PATH_COMMENTS));
		if (!taskData.isNew()) {
			descriptors.add(new TaskEditorPartDescriptor(ID_PART_COMMENTS) {
				@Override
				public AbstractTaskEditorPart createPart() {
					return new TaskEditorCommentPart();
				}
			}.setPath(PATH_COMMENTS));
		}
		descriptors.add(new TaskEditorPartDescriptor(ID_PART_NEW_COMMENT) {
			@Override
			public AbstractTaskEditorPart createPart() {
				return new TaskEditorNewCommentPart();
			}
		}.setPath(PATH_COMMENTS));
		descriptors.add(new TaskEditorPartDescriptor(ID_PART_ACTIONS) {
			@Override
			public AbstractTaskEditorPart createPart() {
				return new TaskEditorActionPart();
			}
		}.setPath(PATH_ACTIONS));
		descriptors.add(new TaskEditorPartDescriptor(ID_PART_PEOPLE) {
			@Override
			public AbstractTaskEditorPart createPart() {
				return new TaskEditorPeoplePart();
			}
		}.setPath(PATH_PEOPLE));

		descriptors.addAll(getContributionPartDescriptors());
		return descriptors;
	}

	private Collection<TaskEditorPartDescriptor> getContributionPartDescriptors() {
		return TaskEditorContributionExtensionReader.getRepositoryEditorContributions();
	}

	protected void createParts() {
		List<TaskEditorPartDescriptor> descriptors = new LinkedList<TaskEditorPartDescriptor>(createPartDescriptors());
		// single column
		createParts(PATH_HEADER, editorComposite, descriptors);
		createParts(PATH_ASSOCIATIONS, editorComposite, descriptors);
		createParts(PATH_ATTRIBUTES, editorComposite, descriptors);
		createParts(PATH_ATTACHMENTS, editorComposite, descriptors);
		createParts(PATH_PLANNING, editorComposite, descriptors);
		createParts(PATH_COMMENTS, editorComposite, descriptors);
		// two column
		Composite bottomComposite = toolkit.createComposite(editorComposite);
		bottomComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).create());
		GridDataFactory.fillDefaults().grab(true, false).applyTo(bottomComposite);
		createParts(PATH_ACTIONS, bottomComposite, descriptors);
		createParts(PATH_PEOPLE, bottomComposite, descriptors);
		bottomComposite.pack(true);

	}

	private void createParts(String path, final Composite parent,
			final Collection<TaskEditorPartDescriptor> descriptors) {
		for (Iterator<TaskEditorPartDescriptor> it = descriptors.iterator(); it.hasNext();) {
			final TaskEditorPartDescriptor descriptor = it.next();
			if (path == null || path.equals(descriptor.getPath())) {
				SafeRunner.run(new ISafeRunnable() {
					public void handleException(Throwable e) {
						StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
								"Error creating task editor part: \"" + descriptor.getId() + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$
					}

					public void run() throws Exception {
						AbstractTaskEditorPart part = descriptor.createPart();
						part.setPartId(descriptor.getId());
						initializePart(parent, part, descriptors);
					}
				});
				it.remove();
			}
		}
	}

	private void createSubParts(final AbstractTaskEditorSection parentPart,
			final Collection<TaskEditorPartDescriptor> descriptors) {
		for (final TaskEditorPartDescriptor descriptor : descriptors) {
			int i;
			String path = descriptor.getPath();
			if (path != null && (i = path.indexOf("/")) != -1) { //$NON-NLS-1$
				String parentId = path.substring(0, i);
				final String subPath = path.substring(i + 1);
				if (parentId.equals(parentPart.getPartId())) {
					SafeRunner.run(new ISafeRunnable() {
						public void handleException(Throwable e) {
							StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
									"Error creating task editor part: \"" + descriptor.getId() + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$
						}

						public void run() throws Exception {
							AbstractTaskEditorPart part = descriptor.createPart();
							part.setPartId(descriptor.getId());
							getManagedForm().addPart(part);
							part.initialize(AbstractTaskEditorPage.this);
							parentPart.addSubPart(subPath, part);
						}
					});
				}
			}
		}
	}

	@Override
	public void dispose() {
		if (textSupport != null) {
			textSupport.dispose();
		}
		if (attributeEditorToolkit != null) {
			attributeEditorToolkit.dispose();
		}
		TasksUiPlugin.getTaskDataManager().removeListener(TASK_DATA_LISTENER);
		super.dispose();
	}

	public void doAction(String actionId) {
		if (findSupport != null && actionId.equals(ActionFactory.FIND.getId())) {
			findSupport.toggleFind();
		}
		CommonTextSupport.doAction(actionId, EditorUtil.getFocusControl(this));
	}

	@Override
	public void doSave(IProgressMonitor monitor) {
		if (!isDirty()) {
			return;
		}

		getManagedForm().commit(true);

		if (model.isDirty()) {
			try {
				model.save(monitor);
			} catch (final CoreException e) {
				StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Error saving task", e)); //$NON-NLS-1$
				getTaskEditor().setMessage(Messages.AbstractTaskEditorPage_Could_not_save_task, IMessageProvider.ERROR,
						new HyperlinkAdapter() {
							@Override
							public void linkActivated(HyperlinkEvent event) {
								TasksUiInternal.displayStatus(Messages.AbstractTaskEditorPage_Save_failed,
										e.getStatus());
							}
						});
			}
		}
		// update the summary of unsubmitted repository tasks
		if (getTask().getSynchronizationState() == SynchronizationState.OUTGOING_NEW) {
			String summary = connector.getTaskMapping(model.getTaskData()).getSummary();
			try {
				TasksUiPlugin.getTaskList().run(new ITaskListRunnable() {
					public void execute(IProgressMonitor monitor) throws CoreException {
						task.setSummary(summary);
					}
				});
				TasksUiPlugin.getTaskList().notifyElementChanged(task);
			} catch (CoreException e) {
				StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
						"Failed to set summary for task \"" + task + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}

		TasksUiPlugin.getTaskList().addTaskIfAbsent(task);

		updateHeaderMessage();
		getManagedForm().dirtyStateChanged();
		getTaskEditor().updateHeaderToolBar();
	}

	@Override
	public void doSaveAs() {
		throw new UnsupportedOperationException();
	}

	public void doSubmit() {
		if (!submitEnabled || !needsSubmit()) {
			return;
		}

		try {
			showEditorBusy(true);

			doSave(new NullProgressMonitor());

			TaskAttribute newCommentAttribute = getModel().getTaskData()
					.getRoot()
					.getMappedAttribute(TaskAttribute.COMMENT_NEW);
			boolean expandLastComment = newCommentAttribute != null
					&& getModel().getChangedAttributes().contains(newCommentAttribute);

			SubmitJob submitJob = TasksUiInternal.getJobFactory().createSubmitTaskJob(connector,
					getModel().getTaskRepository(), task, getModel().getTaskData(),
					getModel().getChangedOldAttributes());
			submitJob.addSubmitJobListener(new SubmitTaskJobListener(getAttachContext(), expandLastComment));
			submitJob.schedule();
		} catch (RuntimeException e) {
			showEditorBusy(false);
			throw e;
		}

		TasksUiPlugin.getTaskList().addTaskIfAbsent(task);
	}

	/**
	 * Override for customizing the tool bar.
	 */
	@Override
	public void fillToolBar(IToolBarManager toolBarManager) {
		final TaskRepository taskRepository = (model != null) ? getModel().getTaskRepository() : null;

		if (taskData == null) {
			synchronizeEditorAction = new SynchronizeEditorAction();
			synchronizeEditorAction.selectionChanged(new StructuredSelection(getTaskEditor()));
			toolBarManager.appendToGroup("repository", synchronizeEditorAction); //$NON-NLS-1$
		} else {
			if (taskData.isNew()) {
				DeleteTaskEditorAction deleteAction = new DeleteTaskEditorAction(getTask());
				deleteAction.setImageDescriptor(CommonImages.CLEAR);
				toolBarManager.appendToGroup("new", deleteAction); //$NON-NLS-1$
			} else if (taskRepository != null) {
				ClearOutgoingAction clearOutgoingAction = new ClearOutgoingAction(
						Collections.singletonList((IRepositoryElement) task));
				(clearOutgoingAction).setTaskEditorPage(this);
				if (clearOutgoingAction.isEnabled()) {
					toolBarManager.appendToGroup("new", clearOutgoingAction); //$NON-NLS-1$
				}

				if (task.getSynchronizationState() != SynchronizationState.OUTGOING_NEW) {
					synchronizeEditorAction = new SynchronizeEditorAction();
					synchronizeEditorAction.selectionChanged(new StructuredSelection(getTaskEditor()));
					toolBarManager.appendToGroup("repository", synchronizeEditorAction); //$NON-NLS-1$
				}

				NewSubTaskAction newSubTaskAction = new NewSubTaskAction();
				newSubTaskAction.selectionChanged(newSubTaskAction, new StructuredSelection(task));
				if (newSubTaskAction.isEnabled()) {
					toolBarManager.appendToGroup("new", newSubTaskAction); //$NON-NLS-1$
				}

				AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(taskData.getConnectorKind());
				if (connectorUi != null) {
					final String historyUrl = connectorUi.getTaskHistoryUrl(taskRepository, task);
					if (historyUrl != null) {
						final Action historyAction = new Action() {
							@Override
							public void run() {
								TasksUiUtil.openUrl(historyUrl);
							}
						};

						historyAction.setText(Messages.AbstractTaskEditorPage_History);
						historyAction.setImageDescriptor(TasksUiImages.TASK_REPOSITORY_HISTORY);
						historyAction.setToolTipText(Messages.AbstractTaskEditorPage_History);
						if (getEditor().openWithBrowserAction != null) {
							getEditor().openWithBrowserAction.setMenuCreator(new MenuCreator() {
								@Override
								protected void initialize(MenuManager menuManager) {
									OpenWithBrowserAction openWithBrowserAction = new OpenWithBrowserAction();
									openWithBrowserAction.selectionChanged(new StructuredSelection(task));
									menuManager.add(openWithBrowserAction);
									menuManager.add(new Separator());
									menuManager.add(historyAction);
								};
							});
						} else {
							toolBarManager.prependToGroup("open", historyAction); //$NON-NLS-1$
						}
					}
				}
			}
			if (needsSubmitButton()) {
				ToolBarButtonContribution submitButtonContribution = new ToolBarButtonContribution(
						"org.eclipse.mylyn.tasks.toolbars.submit") { //$NON-NLS-1$
					@Override
					protected Control createButton(Composite composite) {
						submitButton = new Button(composite, SWT.FLAT);
						submitButton.setText(Messages.TaskEditorActionPart_Submit + " "); //$NON-NLS-1$
						submitButton.setImage(CommonImages.getImage(TasksUiImages.REPOSITORY_SUBMIT));
						submitButton.setBackground(null);
						submitButton.addListener(SWT.Selection, new Listener() {
							public void handleEvent(Event e) {
								doSubmit();
							}
						});
						return submitButton;
					}
				};
				submitButtonContribution.marginLeft = 10;
				toolBarManager.add(submitButtonContribution);
			}
			if (findSupport != null) {
				findSupport.addFindAction(toolBarManager);
			}
		}
	}

	protected void fireSelectionChanged(ISelection selection) {
		// create an event
		final SelectionChangedEvent event = new SelectionChangedEvent(this, selection);

		// fire the event
		Object[] listeners = selectionChangedListeners.getListeners();
		for (Object listener : listeners) {
			final ISelectionChangedListener l = (ISelectionChangedListener) listener;
			SafeRunner.run(new SafeRunnable() {
				public void run() {
					l.selectionChanged(event);
				}
			});
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public Object getAdapter(Class adapter) {
		if (adapter == IContentOutlinePage.class) {
			updateOutlinePage();
			return outlinePage;
		}
		// TODO 3.5 replace by getTextSupport() method
		if (adapter == CommonTextSupport.class) {
			return textSupport;
		}
		return super.getAdapter(adapter);
	}

	private void updateOutlinePage() {
		if (outlinePage == null) {
			outlinePage = new TaskEditorOutlinePage();
			outlinePage.addSelectionChangedListener(new ISelectionChangedListener() {
				public void selectionChanged(SelectionChangedEvent event) {
					ISelection selection = event.getSelection();
					if (selection instanceof StructuredSelection) {
						Object select = ((StructuredSelection) selection).getFirstElement();
						selectReveal(select);
						getEditor().setActivePage(getId());
					}
				}
			});
		}
		if (getModel() != null) {
			TaskEditorOutlineNode node = TaskEditorOutlineNode.parse(getModel().getTaskData(), false);
			outlinePage.setInput(getTaskRepository(), node);
		} else {
			outlinePage.setInput(null, null);
		}
	}

	private boolean getAttachContext() {
		AbstractTaskEditorPart actionPart = getPart(ID_PART_ACTIONS);
		if (actionPart instanceof TaskEditorActionPart) {
			return ((TaskEditorActionPart) actionPart).getAttachContext();
		}
		return false;
	}

	public AttributeEditorFactory getAttributeEditorFactory() {
		return attributeEditorFactory;
	}

	public AttributeEditorToolkit getAttributeEditorToolkit() {
		return attributeEditorToolkit;
	}

	public AbstractRepositoryConnector getConnector() {
		return connector;
	}

	public String getConnectorKind() {
		return connectorKind;
	}

	/**
	 * @return The composite for the whole editor.
	 */
	public Composite getEditorComposite() {
		return editorComposite;
	}

	public TaskDataModel getModel() {
		return model;
	}

	public AbstractTaskEditorPart getPart(String partId) {
		Assert.isNotNull(partId);
		if (getManagedForm() != null) {
			for (IFormPart part : getManagedForm().getParts()) {
				if (part instanceof AbstractTaskEditorPart) {
					AbstractTaskEditorPart taskEditorPart = (AbstractTaskEditorPart) part;
					if (partId.equals(taskEditorPart.getPartId())) {
						return taskEditorPart;
					}
				}
			}
		}
		return null;
	}

	public ISelection getSelection() {
		return lastSelection;
	}

	public ITask getTask() {
		return task;
	}

	public TaskEditor getTaskEditor() {
		return getEditor();
	}

	public TaskRepository getTaskRepository() {
		// FIXME model can be null
		return getModel().getTaskRepository();
	}

	/**
	 * Invoked after task submission has completed. This method is invoked on the UI thread in all cases whether
	 * submission was successful, canceled or failed. The value returned by <code>event.getJob().getStatus()</code>
	 * indicates the result of the submit job. Sub-classes may override but are encouraged to invoke the super method.
	 *
	 * @since 3.2
	 * @see SubmitJob
	 */
	protected void handleTaskSubmitted(SubmitJobEvent event) {
		IStatus status = event.getJob().getStatus();
		if (status != null && status.getSeverity() != IStatus.CANCEL) {
			handleSubmitError(event.getJob());
		}
	}

	private void handleSubmitError(SubmitJob job) {
		if (form != null && !form.isDisposed()) {
			final IStatus status = job.getStatus();
			String message = null;
			if (status.getCode() == RepositoryStatus.REPOSITORY_COMMENT_REQUIRED) {
				TasksUiInternal.displayStatus(Messages.AbstractTaskEditorPage_Comment_required, status);
				AbstractTaskEditorPart newCommentPart = getPart(ID_PART_NEW_COMMENT);
				if (newCommentPart != null) {
					newCommentPart.setFocus();
				}
				return;
			} else if (status.getCode() == RepositoryStatus.ERROR_REPOSITORY_LOGIN) {
				if (TasksUiUtil.openEditRepositoryWizard(getTaskRepository()) == Window.OK) {
					submitEnabled = true;
					doSubmit();
					return;
				} else {
					message = getMessageFromStatus(status);
				}
			} else if (status.getCode() == RepositoryStatus.ERROR_IO) {
				message = ERROR_NOCONNECTIVITY;
			} else {
				message = getMessageFromStatus(status);
			}
			getTaskEditor().setMessage(message, IMessageProvider.ERROR, new HyperlinkAdapter() {
				@Override
				public void linkActivated(HyperlinkEvent e) {
					TasksUiInternal.displayStatus(Messages.AbstractTaskEditorPage_Submit_failed, status);
				}
			});
		}
	}

	private String getMessageFromStatus(final IStatus status) {
		String message;
		if (status.getMessage().length() > 0) {
			if (status.getMessage().length() < 256) {
				message = Messages.AbstractTaskEditorPage_Submit_failed_ + status.getMessage();
			} else {
				message = Messages.AbstractTaskEditorPage_Submit_failed_ + status.getMessage().substring(0, 256)
						+ "..."; //$NON-NLS-1$
			}
		} else {
			message = Messages.AbstractTaskEditorPage_Submit_failed;
		}
		return message.replaceAll("\n", " ").replaceAll("\r", " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
	}

	@Override
	public void init(IEditorSite site, IEditorInput input) {
		super.init(site, input);

		TaskEditorInput taskEditorInput = (TaskEditorInput) input;
		this.task = taskEditorInput.getTask();
		this.defaultSelection = new StructuredSelection(task);
		this.lastSelection = defaultSelection;
		IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
		this.textSupport = new CommonTextSupport(handlerService);
		this.textSupport.setSelectionChangedListener(this);
		createFindSupport();

		initModel(taskEditorInput);

		TasksUiPlugin.getTaskDataManager().addListener(TASK_DATA_LISTENER);
	}

	private void initModel(TaskEditorInput input) {
		Assert.isTrue(model == null);
		try {
			this.model = createModel(input);
			this.connector = TasksUi.getRepositoryManager().getRepositoryConnector(getConnectorKind());
			setTaskData(model.getTaskData());
			model.addModelListener(new TaskDataModelListener() {
				@Override
				public void attributeChanged(TaskDataModelEvent event) {
					IManagedForm form = getManagedForm();
					if (form != null && !form.isDirty()) {
						form.dirtyStateChanged();
					}
				}
			});
			setNeedsAddToCategory(model.getTaskData().isNew());
		} catch (final CoreException e) {
			StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Error opening task", e)); //$NON-NLS-1$
			getTaskEditor().setStatus(Messages.AbstractTaskEditorPage_Error_opening_task,
					Messages.AbstractTaskEditorPage_Open_failed, e.getStatus());
		}
	}

	private void initializePart(Composite parent, AbstractTaskEditorPart part,
			Collection<TaskEditorPartDescriptor> descriptors) {
		getManagedForm().addPart(part);
		part.initialize(this);
		if (part instanceof AbstractTaskEditorSection) {
			createSubParts((AbstractTaskEditorSection) part, descriptors);
		}
		if (parent != null) {
			part.createControl(parent, toolkit);
			if (part.getControl() != null) {
				if (ID_PART_ACTIONS.equals(part.getPartId())) {
					// do not expand horizontally
					GridDataFactory.fillDefaults()
							.align(SWT.FILL, SWT.FILL)
							.grab(false, false)
							.applyTo(part.getControl());
				} else {
					if (part.getExpandVertically()) {
						GridDataFactory.fillDefaults()
								.align(SWT.FILL, SWT.FILL)
								.grab(true, true)
								.applyTo(part.getControl());
					} else {
						GridDataFactory.fillDefaults()
								.align(SWT.FILL, SWT.TOP)
								.grab(true, false)
								.applyTo(part.getControl());
					}
				}
				// for outline
				if (ID_PART_COMMENTS.equals(part.getPartId())) {
					EditorUtil.setMarker(part.getControl(), TaskEditorOutlineNode.LABEL_COMMENTS);
				} else if (ID_PART_ATTACHMENTS.equals(part.getPartId())) {
					EditorUtil.setMarker(part.getControl(), TaskEditorOutlineNode.LABEL_ATTACHMENTS);
				}
			}
		}
	}

	/**
	 * Subclasses may override to disable the task editor find functionality.
	 *
	 * @since 3.11
	 */
	protected void createFindSupport() {
		this.findSupport = new TaskEditorFindSupport(this);
	}

	@Override
	public boolean isDirty() {
		return isModelDirty() || isFormDirty();
	}

	private boolean isFormDirty() {
		IManagedForm form = getManagedForm();
		return form != null && form.isDirty();
	}

	private boolean isModelDirty() {
		TaskDataModel model = getModel();
		return model != null && model.isDirty();
	}

	@Override
	public boolean isSaveAsAllowed() {
		return false;
	}

	public boolean needsAddToCategory() {
		return needsAddToCategory;
	}

	/**
	 * Force a re-layout of entire form.
	 */
	public void reflow() {
		if (reflow) {
			try {
				form.setRedraw(false);
				// help the layout managers: ensure that the form width always matches
				// the parent client area width.
				Rectangle parentClientArea = form.getParent().getClientArea();
				Point formSize = form.getSize();
				if (formSize.x != parentClientArea.width) {
					ScrollBar verticalBar = form.getVerticalBar();
					int verticalBarWidth = verticalBar != null ? verticalBar.getSize().x : 15;
					form.setSize(parentClientArea.width - verticalBarWidth, formSize.y);
				}

				form.layout(true, false);
				form.reflow(true);
			} finally {
				form.setRedraw(true);
			}
		}
	}

	/**
	 * Updates the editor contents in place.
	 *
	 * @deprecated Use {@link #refresh()} instead
	 */
	@Deprecated
	public void refreshFormContent() {
		refresh();
	}

	/**
	 * Updates the editor contents in place.
	 */
	@Override
	public void refresh() {
		if (getManagedForm() == null || getManagedForm().getForm().isDisposed()) {
			// editor possibly closed or page has not been initialized
			return;
		}

		try {
			showEditorBusy(true);

			boolean hasIncoming = false;

			if (getTask() != null) {
				hasIncoming = getTask().getSynchronizationState().isIncoming();
			}
			if (model != null) {
				doSave(new NullProgressMonitor());
				refreshInput();
			} else {
				initModel(getTaskEditor().getTaskEditorInput());
			}

			if (taskData != null) {
				try {
					setReflow(false);
					// prevent menu from being disposed when disposing control on the form during refresh
					Menu menu = editorComposite.getMenu();
					CommonUiUtil.setMenu(editorComposite, null);

					// clear old controls and parts
					for (Control control : editorComposite.getChildren()) {
						control.dispose();
					}
					if (focusTracker != null) {
						focusTracker.reset();
					}
					lastSelection = null;
					for (IFormPart part : getManagedForm().getParts()) {
						part.dispose();
						getManagedForm().removePart(part);
					}

					// restore menu
					editorComposite.setMenu(menu);

					createFormContentInternal();

					getTaskEditor().setMessage(null, 0);
					if (hasIncoming) {
						getTaskEditor().setActivePage(getId());
					}

					setSubmitEnabled(true);
				} finally {
					setReflow(true);
				}
			}

			updateOutlinePage();
			updateHeaderMessage();
			getManagedForm().dirtyStateChanged();
			getTaskEditor().updateHeaderToolBar();
		} finally {
			showEditorBusy(false);
		}
		reflow();
	}

	private void refreshInput() {
		try {
			refreshDisabled = true;
			model.refresh(null);
		} catch (CoreException e) {
			getTaskEditor().setMessage(Messages.AbstractTaskEditorPage_Failed_to_read_task_data_ + e.getMessage(),
					IMessageProvider.ERROR);
			taskData = null;
			return;
		} finally {
			refreshDisabled = false;
		}

		setTaskData(model.getTaskData());
	}

	/**
	 * Registers a drop listener for <code>control</code>. The default implementation registers a listener for attaching
	 * files. Does nothing if the editor is showing a new task.
	 * <p>
	 * Clients may override.
	 * </p>
	 *
	 * @param control
	 *            the control to register the listener for
	 */
	public void registerDefaultDropListener(final Control control) {
		if (getModel() == null || getModel().getTaskData().isNew()) {
			return;
		}

		DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_DEFAULT);
		LocalSelectionTransfer localSelectionTransfer = LocalSelectionTransfer.getTransfer();
		final TextTransfer textTransfer = TextTransfer.getInstance();
		final FileTransfer fileTransfer = FileTransfer.getInstance();
		Transfer[] types = new Transfer[] { localSelectionTransfer, textTransfer, fileTransfer };
		target.setTransfer(types);
		if (defaultDropListener == null) {
			defaultDropListener = new TaskAttachmentDropListener(this);
		}
		target.addDropListener(defaultDropListener);
	}

	public void removeSelectionChangedListener(ISelectionChangedListener listener) {
		selectionChangedListeners.remove(listener);
	}

	public void selectionChanged(Object element) {
		selectionChanged(new SelectionChangedEvent(this, new StructuredSelection(element)));
	}

	public void selectionChanged(SelectionChangedEvent event) {
		ISelection selection = event.getSelection();
		if (selection instanceof TextSelection) {
			// only update global actions
			((TaskEditorActionContributor) getEditorSite().getActionBarContributor())
					.updateSelectableActions(event.getSelection());
			return;
		}
		if (selection.isEmpty()) {
			// something was unselected, reset to default selection
			selection = defaultSelection;
			// XXX a styled text widget has lost focus, re-enable all edit actions
			((TaskEditorActionContributor) getEditorSite().getActionBarContributor()).forceActionsEnabled();
		}
		if (!selection.equals(lastSelection)) {
			this.lastSelection = selection;
			fireSelectionChanged(lastSelection);
			getSite().getSelectionProvider().setSelection(selection);
		}
	}

	@Override
	public void setFocus() {
		if (focusTracker != null && focusTracker.setFocus()) {
			return;
		} else {
			IFormPart[] parts = getManagedForm().getParts();
			if (parts.length > 0) {
				parts[0].setFocus();
				return;
			}
		}
		super.setFocus();
	}

	public void setNeedsAddToCategory(boolean needsAddToCategory) {
		this.needsAddToCategory = needsAddToCategory;
	}

	public void setReflow(boolean reflow) {
		this.reflow = reflow;
		form.setRedraw(reflow);
	}

	public void setSelection(ISelection selection) {
		IFormPart[] parts = getManagedForm().getParts();
		for (IFormPart formPart : parts) {
			if (formPart instanceof AbstractTaskEditorPart) {
				if (((AbstractTaskEditorPart) formPart).setSelection(selection)) {
					lastSelection = selection;
					return;
				}
			}
		}
	}

	// TODO EDITOR this needs to be tracked somewhere else
	private void setSubmitEnabled(boolean enabled) {
		AbstractTaskEditorPart actionPart = getPart(ID_PART_ACTIONS);
		if (actionPart instanceof TaskEditorActionPart) {
			((TaskEditorActionPart) actionPart).setSubmitEnabled(enabled);
		}
		if (submitButton != null && !submitButton.isDisposed()) {
			submitButton.setEnabled(enabled);
		}
		submitEnabled = enabled;
	}

	private void setTaskData(TaskData taskData) {
		this.taskData = taskData;
	}

	@Override
	public void showBusy(boolean busy) {
		if (getManagedForm() != null && !getManagedForm().getForm().isDisposed() && this.busy != busy) {
			setSubmitEnabled(!busy);
			CommonUiUtil.setEnabled(editorComposite, !busy);
			this.busy = busy;
		}
	}

	// TODO m4.0 remove
	public void showEditorBusy(boolean busy) {
		getTaskEditor().showBusy(busy);
		refreshDisabled = busy;
	}

	private void updateHeaderMessage() {
		if (taskData == null) {
			getTaskEditor().setMessage(Messages.AbstractTaskEditorPage_Synchronize_to_retrieve_task_data,
					IMessageProvider.WARNING, new HyperlinkAdapter() {
						@Override
						public void linkActivated(HyperlinkEvent e) {
							if (synchronizeEditorAction != null) {
								synchronizeEditorAction.run();
							}
						}
					});
		}
		if (getTaskEditor().getMessage() == null
				&& TasksUiPlugin.getTaskList().getTask(task.getRepositoryUrl(), task.getTaskId()) == null) {
			getTaskEditor().setMessage(Messages.AbstractTaskEditorPage_Add_task_to_tasklist,
					IMessageProvider.INFORMATION, new NotInTaskListListener());
		}
	}

	@Override
	public Control getPartControl() {
		return partControl != null ? partControl : super.getPartControl();
	}

	/**
	 * Returns true, if the page has an always visible footer.
	 *
	 * @see #setNeedsFooter(boolean)
	 */
	private boolean needsFooter() {
		return needsFooter;
	}

	/**
	 * Specifies that the page should provide an always visible footer. This flag is not set by default.
	 *
	 * @see #createFooterContent(Composite)
	 * @see #needsFooter()
	 */
	@SuppressWarnings("unused")
	private void setNeedsFooter(boolean needsFooter) {
		this.needsFooter = needsFooter;
	}

	private void createFooterContent(Composite parent) {
		parent.setLayout(new GridLayout());
	}

	/**
	 * Returns true, if the page supports a submit operation.
	 *
	 * @since 3.2
	 * @see #setNeedsSubmit(boolean)
	 */
	public boolean needsSubmit() {
		return needsSubmit;
	}

	/**
	 * Specifies that the page supports the submit operation. This flag is set to true by default.
	 *
	 * @since 3.2
	 * @see #needsSubmit()
	 * @see #doSubmit()
	 */
	public void setNeedsSubmit(boolean needsSubmit) {
		this.needsSubmit = needsSubmit;
	}

	/**
	 * Returns true, if the page provides a submit button.
	 *
	 * @since 3.2
	 * @see #setNeedsSubmitButton(boolean)
	 */
	public boolean needsSubmitButton() {
		return needsSubmitButton;
	}

	/**
	 * Specifies that the page supports submitting. This flag is set to false by default.
	 *
	 * @since 3.2
	 * @see #needsSubmitButton()
	 */
	public void setNeedsSubmitButton(boolean needsSubmitButton) {
		this.needsSubmitButton = needsSubmitButton;
	}

	/**
	 * Returns true, if the page provides a submit button.
	 *
	 * @since 3.2
	 * @see #setNeedsPrivateSection(boolean)
	 */
	public boolean needsPrivateSection() {
		return needsPrivateSection;
	}

	/**
	 * Specifies that the page should provide the private section. This flag is not set by default.
	 *
	 * @since 3.2
	 * @see #needsPrivateSection()
	 */
	public void setNeedsPrivateSection(boolean needsPrivateSection) {
		this.needsPrivateSection = needsPrivateSection;
	}

	@Override
	public boolean selectReveal(Object object) {
		if (object instanceof TaskEditorOutlineNode) {
			TaskEditorOutlineNode node = (TaskEditorOutlineNode) object;
			TaskAttribute attribute = node.getData();
			if (attribute != null) {
				super.selectReveal(attribute.getId());
			} else {
				TaskRelation taskRelation = node.getTaskRelation();
				TaskRepository taskRepository = node.getTaskRepository();
				if (taskRelation != null && taskRepository != null) {
					String taskID = taskRelation.getTaskId();
					TasksUiUtil.openTask(taskRepository, taskID);
				} else {
					EditorUtil.reveal(this.getManagedForm().getForm(), node.getLabel());
				}
				return true;
			}
		}
		return super.selectReveal(object);
	}

	void expandLastComment() {
		if (getManagedForm() == null || getManagedForm().getForm().isDisposed()) {
			// editor possibly closed or page has not been initialized
			return;
		}

		if (taskData == null) {
			return;
		}

		List<TaskAttribute> commentAttributes = taskData.getAttributeMapper().getAttributesByType(taskData,
				TaskAttribute.TYPE_COMMENT);
		if (commentAttributes.size() > 0) {
			selectReveal(commentAttributes.get(commentAttributes.size() - 1).getId());
		}
	}

}
