From d65cd5c4c02419177a58614fc76a12e2e7e1ff4b Mon Sep 17 00:00:00 2001 From: Steffen Pingel Date: Thu, 27 Oct 2011 00:10:31 +0200 Subject: NEW - bug 362009: provide an abstract attribute editor part https://bugs.eclipse.org/bugs/show_bug.cgi?id=362009 --- .../AbstractTaskEditorAttributeSection.java | 366 +++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/AbstractTaskEditorAttributeSection.java diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/AbstractTaskEditorAttributeSection.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/AbstractTaskEditorAttributeSection.java new file mode 100644 index 000000000..260b70f84 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/AbstractTaskEditorAttributeSection.java @@ -0,0 +1,366 @@ +/******************************************************************************* + * Copyright (c) 2004, 2010 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 + * Perforce - fixes for bug 318396 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.editors; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.mylyn.internal.provisional.commons.ui.CommonFormUtil; +import org.eclipse.mylyn.internal.provisional.commons.ui.WorkbenchUtil; +import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskDiffUtil; +import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; +import org.eclipse.mylyn.internal.tasks.ui.views.UpdateRepositoryConfigurationAction; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.sync.TaskJob; +import org.eclipse.mylyn.tasks.ui.TasksUiImages; +import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor; +import org.eclipse.mylyn.tasks.ui.editors.LayoutHint; +import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.ColumnSpan; +import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.RowSpan; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.widgets.FormToolkit; + +/** + * Editor part that shows {@link TaskAttribute}s in a two column layout. + * + * @author Steffen Pingel + * @author Kevin Sawicki + */ +public abstract class AbstractTaskEditorAttributeSection extends AbstractTaskEditorSection { + + private static final int LABEL_WIDTH = 110; + + private static final int COLUMN_WIDTH = 140; + + private static final int COLUMN_GAP = 20; + + private static final int MULTI_COLUMN_WIDTH = COLUMN_WIDTH + 5 + COLUMN_GAP + LABEL_WIDTH + 5 + COLUMN_WIDTH; + + private static final int MULTI_ROW_HEIGHT = 55; + + private List attributeEditors; + + private boolean hasIncoming; + + private Composite attributesComposite; + + private boolean needsRefresh; + + public AbstractTaskEditorAttributeSection() { + } + + @Override + public void createControl(Composite parent, final FormToolkit toolkit) { + initialize(); + super.createControl(parent, toolkit); + } + + public boolean hasIncoming() { + return hasIncoming; + } + + public void selectReveal(TaskAttribute attribute) { + if (attribute == null) { + return; + } + if (!getSection().isExpanded()) { + CommonFormUtil.setExpanded(getSection(), true); + } + EditorUtil.reveal(getTaskEditorPage().getManagedForm().getForm(), attribute.getId()); + } + + @Override + public boolean setFormInput(Object input) { + if (input instanceof String) { + String text = (String) input; + Collection attributes = getAttributes(); + for (TaskAttribute attribute : attributes) { + if (text.equals(attribute.getId())) { + selectReveal(attribute); + } + } + } + return super.setFormInput(input); + } + + private void createAttributeControls(Composite attributesComposite, FormToolkit toolkit, int columnCount) { + int currentColumn = 1; + int currentPriority = 0; + for (AbstractAttributeEditor attributeEditor : attributeEditors) { + int priority = (attributeEditor.getLayoutHint() != null) + ? attributeEditor.getLayoutHint().getPriority() + : LayoutHint.DEFAULT_PRIORITY; + if (priority != currentPriority) { + currentPriority = priority; + if (currentColumn > 1) { + while (currentColumn <= columnCount) { + getManagedForm().getToolkit().createLabel(attributesComposite, ""); //$NON-NLS-1$ + currentColumn++; + } + currentColumn = 1; + } + } + + if (attributeEditor.hasLabel()) { + attributeEditor.createLabelControl(attributesComposite, toolkit); + Label label = attributeEditor.getLabelControl(); + String text = label.getText(); + String shortenText = TaskDiffUtil.shortenText(label, text, LABEL_WIDTH); + label.setText(shortenText); + if (!text.equals(shortenText)) { + label.setToolTipText(text); + } + GridData gd = GridDataFactory.fillDefaults() + .align(SWT.RIGHT, SWT.CENTER) + .hint(LABEL_WIDTH, SWT.DEFAULT) + .create(); + if (currentColumn > 1) { + gd.horizontalIndent = COLUMN_GAP; + gd.widthHint = LABEL_WIDTH + COLUMN_GAP; + } + label.setLayoutData(gd); + currentColumn++; + } + + attributeEditor.createControl(attributesComposite, toolkit); + LayoutHint layoutHint = attributeEditor.getLayoutHint(); + GridData gd = new GridData(SWT.FILL, SWT.CENTER, false, false); + RowSpan rowSpan = (layoutHint != null && layoutHint.rowSpan != null) ? layoutHint.rowSpan : RowSpan.SINGLE; + ColumnSpan columnSpan = (layoutHint != null && layoutHint.columnSpan != null) + ? layoutHint.columnSpan + : ColumnSpan.SINGLE; + if (rowSpan == RowSpan.SINGLE && columnSpan == ColumnSpan.SINGLE) { + gd.widthHint = COLUMN_WIDTH; + gd.horizontalSpan = 1; + } else { + if (rowSpan == RowSpan.MULTIPLE) { + gd.heightHint = MULTI_ROW_HEIGHT; + } + if (columnSpan == ColumnSpan.SINGLE) { + gd.widthHint = COLUMN_WIDTH; + gd.horizontalSpan = 1; + } else { + gd.widthHint = MULTI_COLUMN_WIDTH; + gd.horizontalSpan = columnCount - currentColumn + 1; + } + } + attributeEditor.getControl().setLayoutData(gd); + + getTaskEditorPage().getAttributeEditorToolkit().adapt(attributeEditor); + + currentColumn += gd.horizontalSpan; + currentColumn %= columnCount; + } + } + + private void initialize() { + attributeEditors = new ArrayList(); + hasIncoming = false; + + Collection attributes = getAttributes(); + for (TaskAttribute attribute : attributes) { + AbstractAttributeEditor attributeEditor = createAttributeEditor(attribute); + if (attributeEditor != null) { + attributeEditors.add(attributeEditor); + if (getModel().hasIncomingChanges(attribute)) { + hasIncoming = true; + } + } + } + + Comparator attributeSorter = createAttributeEditorSorter(); + if (attributeSorter != null) { + Collections.sort(attributeEditors, attributeSorter); + } + } + + /** + * Create a comparator by which attribute editors will be sorted. By default attribute editors are sorted by layout + * hint priority. Subclasses may override this method to sort attribute editors in a custom way. + * + * @return comparator for {@link AbstractAttributeEditor} objects + */ + protected Comparator createAttributeEditorSorter() { + return new Comparator() { + public int compare(AbstractAttributeEditor o1, AbstractAttributeEditor o2) { + int p1 = (o1.getLayoutHint() != null) ? o1.getLayoutHint().getPriority() : LayoutHint.DEFAULT_PRIORITY; + int p2 = (o2.getLayoutHint() != null) ? o2.getLayoutHint().getPriority() : LayoutHint.DEFAULT_PRIORITY; + return p1 - p2; + } + }; + } + + @Override + protected Control createContent(FormToolkit toolkit, Composite parent) { + attributesComposite = toolkit.createComposite(parent); + attributesComposite.addListener(SWT.MouseDown, new Listener() { + public void handleEvent(Event event) { + Control focus = event.display.getFocusControl(); + if (focus instanceof Text && ((Text) focus).getEditable() == false) { + getManagedForm().getForm().setFocus(); + } + } + }); + + GridLayout attributesLayout = EditorUtil.createSectionClientLayout(); + attributesLayout.numColumns = 4; + attributesLayout.horizontalSpacing = 9; + attributesLayout.verticalSpacing = 6; + attributesComposite.setLayout(attributesLayout); + + GridData attributesData = new GridData(GridData.FILL_BOTH); + attributesData.horizontalSpan = 1; + attributesData.grabExcessVerticalSpace = false; + attributesComposite.setLayoutData(attributesData); + + createAttributeControls(attributesComposite, toolkit, attributesLayout.numColumns); + toolkit.paintBordersFor(attributesComposite); + + return attributesComposite; + } + + protected IAction doCreateRefreshAction() { + UpdateRepositoryConfigurationAction repositoryConfigRefresh = new UpdateRepositoryConfigurationAction() { + @Override + public void run() { + getTaskEditorPage().showEditorBusy(true); + final TaskJob job = TasksUiInternal.getJobFactory().createUpdateRepositoryConfigurationJob( + getTaskEditorPage().getConnector(), getTaskEditorPage().getTaskRepository(), + getTaskEditorPage().getTask()); + job.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + getTaskEditorPage().showEditorBusy(false); + if (job.getStatus() != null) { + getTaskEditorPage().getTaskEditor() + .setStatus( + Messages.TaskEditorAttributePart_Updating_of_repository_configuration_failed, + Messages.TaskEditorAttributePart_Update_Failed, job.getStatus()); + } else { + getTaskEditorPage().refresh(); + } + } + }); + } + }); + job.setUser(true); + // show the progress in the system task bar if this is a user job (i.e. forced) + job.setProperty(WorkbenchUtil.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE); + job.setPriority(Job.INTERACTIVE); + job.schedule(); + }; + +// @Override +// public void performUpdate(TaskRepository repository, AbstractRepositoryConnector connector, +// IProgressMonitor monitor) { +// PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { +// public void run() { +// getTaskEditorPage().showEditorBusy(true); +// } +// }); +// try { +// super.performUpdate(repository, connector, monitor); +// AbstractTask task = getTaskEditorPage().getTask(); +// Job job = TasksUi.synchronizeTask(connector, task, true, null); +// job.join(); +// } catch (InterruptedException e) { +// // ignore +// } finally { +// PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { +// public void run() { +// getTaskEditorPage().refreshFormContent(); +// } +// }); +// } +// } + }; + repositoryConfigRefresh.setImageDescriptor(TasksUiImages.REPOSITORY_SYNCHRONIZE_SMALL); + repositoryConfigRefresh.selectionChanged(new StructuredSelection(getTaskEditorPage().getTaskRepository())); + repositoryConfigRefresh.setToolTipText(Messages.TaskEditorAttributePart_Refresh_Attributes); + return repositoryConfigRefresh; + } + + @Override + protected void fillToolBar(ToolBarManager toolBar) { + if (needsRefresh()) { + IAction repositoryConfigRefresh = doCreateRefreshAction(); + toolBar.add(repositoryConfigRefresh); + } + } + + /** + * Returns the list of attributes that are show in the section. + */ + protected abstract Collection getAttributes(); + + @Override + protected String getInfoOverlayText() { + StringBuilder sb = new StringBuilder(); + List overlayAttributes = getOverlayAttributes(); + for (TaskAttribute attribute : overlayAttributes) { + String label = getModel().getTaskData().getAttributeMapper().getValueLabel(attribute); + if (label != null) { + if (sb.length() > 0) { + sb.append(" / "); + } + } + sb.append(label); + } + return (sb.length() > 0) ? sb.toString() : null; + } + + /** + * Returns the attributes that are shown in the overlay text. + * + * @see #getInfoOverlayText() + */ + protected abstract List getOverlayAttributes(); + + protected boolean needsRefresh() { + return needsRefresh; + } + + protected void setNeedsRefresh(boolean needsRefresh) { + this.needsRefresh = needsRefresh; + } + + /** + * Integrator requested the ability to control whether the attributes section is expanded on creation. + */ + @Override + protected boolean shouldExpandOnCreate() { + return getTaskData().isNew() || hasIncoming; + } + +} -- cgit v1.2.3