| /******************************************************************************* |
| * Copyright (c) 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 |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.provisional.tasks.ui.wizards; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.mylyn.commons.workbench.forms.SectionComposite; |
| import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema.Field; |
| import org.eclipse.mylyn.internal.tasks.core.TaskTask; |
| import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskDiffUtil; |
| import org.eclipse.mylyn.tasks.core.IRepositoryQuery; |
| import org.eclipse.mylyn.tasks.core.ITask; |
| 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.ui.TasksUi; |
| import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor; |
| import org.eclipse.mylyn.tasks.ui.editors.AttributeEditorFactory; |
| 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.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage2; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| |
| @SuppressWarnings("nls") |
| public class RepositoryQuerySchemaPage extends AbstractRepositoryQueryPage2 { |
| |
| 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; |
| |
| protected final AbstractQueryPageSchema schema; |
| |
| private final TaskData data; |
| |
| private final Pattern URL_PATTERN; |
| |
| private QueryPageSearch search; |
| |
| private final QueryPageDetails pageDetails; |
| |
| private AttributeEditorFactory factory; |
| |
| private SectionComposite scrolledComposite; |
| |
| private TaskData targetTaskData; |
| |
| protected final Map<String, AbstractAttributeEditor> editorMap = new HashMap<String, AbstractAttributeEditor>(); |
| |
| public RepositoryQuerySchemaPage(String pageName, TaskRepository repository, IRepositoryQuery query, |
| AbstractQueryPageSchema schema, TaskData data, QueryPageDetails pageDetails) { |
| super(pageName, repository, query); |
| this.schema = schema; |
| this.data = data; |
| this.pageDetails = pageDetails; |
| setTitle(pageDetails.getPageTitle()); |
| setDescription(pageDetails.getPageDescription()); |
| URL_PATTERN = Pattern.compile(pageDetails.getUrlPattern()); |
| if (query != null) { |
| search = new QueryPageSearch(query.getUrl()); |
| } else { |
| search = new QueryPageSearch(); |
| } |
| } |
| |
| @Override |
| protected void createPageContent(@NonNull SectionComposite parent) { |
| this.scrolledComposite = parent; |
| |
| Composite scrolledBodyComposite = scrolledComposite.getContent(); |
| GridLayout layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 10; |
| layout.horizontalSpacing = 0; |
| layout.verticalSpacing = 0; |
| scrolledBodyComposite.setLayout(layout); |
| |
| Composite attributesComposite = new Composite(scrolledBodyComposite, SWT.NONE); |
| GridDataFactory.fillDefaults() |
| .align(SWT.FILL, SWT.FILL) |
| .grab(true, true) |
| .span(2, 1) |
| .applyTo(attributesComposite); |
| layout = new GridLayout(6, false); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| attributesComposite.setLayout(layout); |
| GridData g = new GridData(GridData.FILL, GridData.FILL, true, true); |
| g.widthHint = 400; |
| attributesComposite.setLayoutData(g); |
| attributesComposite.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND)); |
| FormToolkit toolkit = new FormToolkit(parent.getDisplay()); |
| |
| TaskRepository repository = getTaskRepository(); |
| ITask nTask = new TaskTask(repository.getConnectorKind(), repository.getRepositoryUrl(), data.getTaskId()); |
| ITaskDataWorkingCopy workingCopy = TasksUi.getTaskDataManager().createWorkingCopy(nTask, data); |
| |
| final TaskDataModel model = new TaskDataModel(repository, nTask, workingCopy); |
| factory = new AttributeEditorFactory(model, repository); |
| model.addModelListener(new TaskDataModelListener() { |
| |
| @Override |
| public void attributeChanged(TaskDataModelEvent event) { |
| getContainer().updateButtons(); |
| } |
| }); |
| targetTaskData = workingCopy.getLocalData(); |
| final TaskAttribute target = targetTaskData.getRoot(); |
| createFieldControls(attributesComposite, toolkit, layout.numColumns, target); |
| Point p = scrolledBodyComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| scrolledComposite.setMinSize(p); |
| |
| } |
| |
| private void createFieldControls(Composite attributesComposite, FormToolkit toolkit, int columnCount, |
| TaskAttribute target) { |
| int currentColumn = 1; |
| int currentPriority = 0; |
| int currentLayoutPriority = 0; |
| for (Field field : schema.getFields()) { |
| TaskAttribute dataAttribute = target.getAttribute(field.getKey()); |
| AbstractAttributeEditor attributeEditor = factory.createEditor(field.getType(), dataAttribute); |
| editorMap.put(dataAttribute.getId(), attributeEditor); |
| |
| String layoutPriorityString = dataAttribute.getMetaData().getValue("LayoutPriority"); |
| int layoutPriority = layoutPriorityString == null ? -1 : Integer.parseInt(layoutPriorityString); |
| int priority = (attributeEditor.getLayoutHint() != null) |
| ? attributeEditor.getLayoutHint().getPriority() |
| : LayoutHint.DEFAULT_PRIORITY; |
| // TODO: copied from AbstractTaskEditorAttributeSection.createAttributeControls (only layoutPriority is new) |
| if (priority != currentPriority || currentLayoutPriority != layoutPriority) { |
| currentPriority = priority; |
| currentLayoutPriority = layoutPriority; |
| if (currentColumn > 1) { |
| while (currentColumn <= columnCount) { |
| Label l = toolkit.createLabel(attributesComposite, ""); //$NON-NLS-1$ |
| |
| GridData gd = GridDataFactory.fillDefaults() |
| .align(SWT.LEFT, SWT.CENTER) |
| .hint(0, SWT.DEFAULT) |
| .create(); |
| l.setLayoutData(gd); |
| |
| currentColumn++; |
| } |
| currentColumn = 1; |
| } |
| } |
| |
| if (attributeEditor.hasLabel()) { |
| attributeEditor.createLabelControl(attributesComposite, toolkit); |
| Label label = attributeEditor.getLabelControl(); |
| label.setBackground(attributesComposite.getBackground()); |
| label.setForeground(attributesComposite.getForeground()); |
| 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) |
| .grab(true, true) |
| .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); |
| attributeEditor.getControl().setBackground( |
| attributesComposite.getParent().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); |
| attributeEditor.getControl().setForeground(attributesComposite.getForeground()); |
| LayoutHint layoutHint = attributeEditor.getLayoutHint(); |
| GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); |
| RowSpan rowSpan = (layoutHint != null && layoutHint.rowSpan != null) ? layoutHint.rowSpan : RowSpan.SINGLE; |
| ColumnSpan columnSpan = (layoutHint != null && layoutHint.columnSpan != null) |
| ? layoutHint.columnSpan |
| : ColumnSpan.SINGLE; |
| gd.horizontalIndent = 1;// prevent clipping of decorators on Windows |
| 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); |
| |
| currentColumn += gd.horizontalSpan; |
| currentColumn %= columnCount; |
| } |
| } |
| |
| @Override |
| public boolean isPageComplete() { |
| setMessage(pageDetails.getPageDescription()); |
| boolean result = super.isPageComplete(); |
| if (!result) { |
| return result; |
| } |
| setErrorMessage(null); |
| setMessage(""); |
| boolean oneFieldHasValue = false; |
| for (Field field : schema.getFields()) { |
| oneFieldHasValue |= (targetTaskData.getRoot().getAttribute(field.getKey()).hasValue() |
| && !targetTaskData.getRoot().getAttribute(field.getKey()).getValue().equals("")); |
| if (field.isQueryRequired()) { |
| String text = targetTaskData.getRoot().getAttribute(field.getKey()).getValue(); |
| if (text == null || text.length() == 0) { |
| setMessage("Enter a value for " + field.getLabel()); |
| return false; |
| } |
| } |
| if (field.getType().equals("url")) { |
| String text = targetTaskData.getRoot().getAttribute(field.getKey()).getValue(); |
| if (text != null && text.length() > 0) { |
| Matcher m = URL_PATTERN.matcher(text); |
| if (m.find()) { |
| setErrorMessage(null); |
| return true; |
| } else { |
| setErrorMessage("Please specify a valid URL in " + field.getLabel()); |
| return false; |
| } |
| } |
| } |
| } |
| if (!oneFieldHasValue) { |
| setErrorMessage("Please fill at least on field!"); |
| } |
| return true; |
| } |
| |
| protected String getQueryUrl(String repsitoryUrl) { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(repsitoryUrl); |
| sb.append("/"); |
| sb.append(pageDetails.getQueryUrlPart()); |
| sb.append(search.toQuery()); |
| return sb.toString(); |
| |
| } |
| |
| @Override |
| public void applyTo(IRepositoryQuery query) { |
| query.setSummary(this.getQueryTitle()); |
| query.setUrl(getQueryUrl(getTaskRepository().getRepositoryUrl())); |
| if (pageDetails.getQueryAttributeName() != null) { |
| query.setAttribute(pageDetails.getQueryAttributeName(), Boolean.TRUE.toString()); |
| } |
| } |
| |
| //FIXME: REST überarbeiten |
| @Override |
| protected void doRefreshControls() { |
| // ignore |
| |
| } |
| |
| //FIXME: REST überarbeiten |
| @Override |
| protected boolean hasRepositoryConfiguration() { |
| // ignore |
| return true; |
| } |
| |
| //FIXME: REST überarbeiten |
| @Override |
| protected boolean restoreState(@NonNull IRepositoryQuery query) { |
| // ignore |
| return false; |
| } |
| |
| protected TaskData getTargetTaskData() { |
| return targetTaskData; |
| } |
| |
| } |