Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java5
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttribute.java5
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttributeMetaData.java19
-rw-r--r--org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java4
-rw-r--r--org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/TaskAttributeMetaDataTest.java50
-rw-r--r--org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/ui/AttributeEditorTest.java209
-rw-r--r--org.eclipse.mylyn.tasks.ui/icons/ovr16/overlay-required.gifbin0 -> 48 bytes
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java2
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties1
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractAttributeEditor.java54
10 files changed, 346 insertions, 3 deletions
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java
index b50cca6da..ba1f3f4dd 100644
--- a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaTaskDataHandler.java
@@ -546,6 +546,7 @@ public class BugzillaTaskDataHandler extends AbstractTaskDataHandler {
createAttribute(taskData, BugzillaAttribute.SHORT_DESC);
TaskAttribute attributeVersion = createAttribute(taskData, BugzillaAttribute.VERSION);
+ attributeVersion.getMetaData().setRequired(true);
optionValues = repositoryConfiguration.getProductOptionValues(BugzillaAttribute.VERSION,
productAttribute.getValue());
Collections.sort(optionValues);
@@ -557,6 +558,7 @@ public class BugzillaTaskDataHandler extends AbstractTaskDataHandler {
}
TaskAttribute attributeComponent = createAttribute(taskData, BugzillaAttribute.COMPONENT);
+ attributeComponent.getMetaData().setRequired(true);
optionValues = repositoryConfiguration.getProductOptionValues(BugzillaAttribute.COMPONENT,
productAttribute.getValue());
Collections.sort(optionValues);
@@ -607,6 +609,7 @@ public class BugzillaTaskDataHandler extends AbstractTaskDataHandler {
}
TaskAttribute attributeOPSYS = createAttribute(taskData, BugzillaAttribute.OP_SYS);
+ attributeOPSYS.getMetaData().setRequired(true);
optionValues = repositoryConfiguration.getOptionValues(BugzillaAttribute.OP_SYS);
for (String option : optionValues) {
attributeOPSYS.putOption(option, option);
@@ -617,6 +620,7 @@ public class BugzillaTaskDataHandler extends AbstractTaskDataHandler {
}
TaskAttribute attributePriority = createAttribute(taskData, BugzillaAttribute.PRIORITY);
+ attributePriority.getMetaData().setRequired(true);
optionValues = repositoryConfiguration.getOptionValues(BugzillaAttribute.PRIORITY);
for (String option : optionValues) {
attributePriority.putOption(option, option);
@@ -627,6 +631,7 @@ public class BugzillaTaskDataHandler extends AbstractTaskDataHandler {
}
TaskAttribute attributeSeverity = createAttribute(taskData, BugzillaAttribute.BUG_SEVERITY);
+ attributeSeverity.getMetaData().setRequired(true);
optionValues = repositoryConfiguration.getOptionValues(BugzillaAttribute.BUG_SEVERITY);
for (String option : optionValues) {
attributeSeverity.putOption(option, option);
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttribute.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttribute.java
index 12f96bbc6..0f555f39a 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttribute.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttribute.java
@@ -149,6 +149,11 @@ public final class TaskAttribute {
public static final String META_READ_ONLY = "task.meta.readOnly"; //$NON-NLS-1$
/**
+ * @since 3.8
+ */
+ public static final String META_REQUIRED = "task.meta.required"; //$NON-NLS-1$
+
+ /**
* @since 3.6
*/
public static final String COMMENT_ISPRIVATE = "task.common.comment.isprivate"; //$NON-NLS-1$
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttributeMetaData.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttributeMetaData.java
index 7518b411b..ee3b0f599 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttributeMetaData.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/data/TaskAttributeMetaData.java
@@ -40,6 +40,7 @@ public class TaskAttributeMetaData {
setKind(null);
setReadOnly(true);
setType(TaskAttribute.TYPE_SHORT_TEXT);
+ setRequired(false);
// only for test
// putValue(TaskAttribute.META_DESCRIPTION, "Tooltip Defaul Text"); //$NON-NLS-1$
return this;
@@ -98,6 +99,14 @@ public class TaskAttributeMetaData {
return Boolean.parseBoolean(taskAttribute.getMetaDatum(TaskAttribute.META_READ_ONLY));
}
+ /**
+ * @since 3.11
+ * @see TaskAttribute#META_REQUIRED
+ */
+ public boolean isRequired() {
+ return Boolean.parseBoolean(taskAttribute.getMetaDatum(TaskAttribute.META_REQUIRED));
+ }
+
public TaskAttributeMetaData putValue(String key, String value) {
taskAttribute.putMetaDatum(key, value);
return this;
@@ -173,4 +182,14 @@ public class TaskAttributeMetaData {
return this;
}
+ /**
+ * @since 3.11
+ * @see TaskAttribute#META_REQUIRED
+ * @return this
+ */
+ public TaskAttributeMetaData setRequired(boolean value) {
+ taskAttribute.putMetaDatum(TaskAttribute.META_REQUIRED, Boolean.toString(value));
+ return this;
+ }
+
}
diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java
index 1c4070d98..88730ef7f 100644
--- a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java
+++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java
@@ -23,6 +23,7 @@ import org.eclipse.mylyn.tasks.tests.core.PriorityLevelTest;
import org.eclipse.mylyn.tasks.tests.core.RepositoryClientManagerTest;
import org.eclipse.mylyn.tasks.tests.core.RepositoryConnectorContributorTest;
import org.eclipse.mylyn.tasks.tests.core.SynchronizeTasksJobTest;
+import org.eclipse.mylyn.tasks.tests.core.TaskAttributeMetaDataTest;
import org.eclipse.mylyn.tasks.tests.core.TaskInitializationDataTest;
import org.eclipse.mylyn.tasks.tests.core.TaskListUnmatchedContainerTest;
import org.eclipse.mylyn.tasks.tests.core.TaskRepositoryLocationTest;
@@ -33,6 +34,7 @@ import org.eclipse.mylyn.tasks.tests.data.TaskDataDiffTest;
import org.eclipse.mylyn.tasks.tests.data.TaskDataExternalizerTest;
import org.eclipse.mylyn.tasks.tests.data.Xml11InputStreamTest;
import org.eclipse.mylyn.tasks.tests.ui.AbstractRepositoryConnectorUiTest;
+import org.eclipse.mylyn.tasks.tests.ui.AttributeEditorTest;
import org.eclipse.mylyn.tasks.tests.ui.MultipleTaskHyperlinkDetectorTest;
import org.eclipse.mylyn.tasks.tests.ui.ScheduledTaskContainerTest;
import org.eclipse.mylyn.tasks.tests.ui.TaskAttachmentPropertyTesterTest;
@@ -150,6 +152,8 @@ public class AllTasksTests {
suite.addTestSuite(TaskAttributeTest.class);
suite.addTestSuite(TaskAttributeMapperTest.class);
suite.addTestSuite(SupportHandlerManagerTest.class);
+ suite.addTestSuite(TaskAttributeMetaDataTest.class);
+ suite.addTestSuite(AttributeEditorTest.class);
suite.addTestSuite(RepositoryClientManagerTest.class);
suite.addTestSuite(AbstractRepositoryConnectorUiTest.class);
suite.addTestSuite(SynchronizeTasksJobTest.class);
diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/TaskAttributeMetaDataTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/TaskAttributeMetaDataTest.java
new file mode 100644
index 000000000..a63364ff9
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/TaskAttributeMetaDataTest.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.tasks.tests.core;
+
+import junit.framework.TestCase;
+
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
+import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
+import org.eclipse.mylyn.tasks.core.data.TaskData;
+import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector;
+
+/**
+ * @author Benjamin Muskalla
+ */
+public class TaskAttributeMetaDataTest extends TestCase {
+
+ private TaskData data;
+
+ @Override
+ protected void setUp() throws Exception {
+ TaskRepository taskRepository = new TaskRepository("kind", "url");
+ data = new TaskData(new TaskAttributeMapper(taskRepository), MockRepositoryConnector.CONNECTOR_KIND,
+ MockRepositoryConnector.REPOSITORY_URL, "taskid");
+ }
+
+ public void testInitialRequiredAttribute() {
+ TaskAttribute attribute = new TaskAttribute(data.getRoot(), "attributeId");
+ boolean required = attribute.getMetaData().isRequired();
+ assertFalse(required);
+ }
+
+ public void testLifecycleRequiredAttribute() {
+ TaskAttribute attribute = new TaskAttribute(data.getRoot(), "attributeId");
+ attribute.getMetaData().setRequired(true);
+ assertTrue(attribute.getMetaData().isRequired());
+ attribute.getMetaData().setRequired(false);
+ assertFalse(attribute.getMetaData().isRequired());
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/ui/AttributeEditorTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/ui/AttributeEditorTest.java
new file mode 100644
index 000000000..77f3a15a1
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/ui/AttributeEditorTest.java
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.tasks.tests.ui;
+
+import junit.framework.TestCase;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.mylyn.commons.workbench.WorkbenchUtil;
+import org.eclipse.mylyn.internal.tasks.core.data.TaskDataState;
+import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
+import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
+import org.eclipse.mylyn.tasks.core.data.TaskData;
+import org.eclipse.mylyn.tasks.core.data.TaskDataModel;
+import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector;
+import org.eclipse.mylyn.tasks.tests.connector.MockTask;
+import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * @author Benjamin Muskalla
+ */
+public class AttributeEditorTest extends TestCase {
+
+ private class MockAttributeEditor extends AbstractAttributeEditor {
+
+ private MockAttributeEditor(TaskDataModel manager, TaskAttribute taskAttribute) throws CoreException {
+ super(manager, taskAttribute);
+ setControl(new Shell());
+ }
+
+ @Override
+ public void createControl(Composite parent, FormToolkit toolkit) {
+ // ignore
+ }
+
+ @Override
+ public boolean isRequired() {
+ return super.isRequired();
+ }
+
+ @Override
+ public void refresh() {
+ // ignore
+ }
+
+ @Override
+ public Label getLabelControl() {
+ return new Label(new Shell(), SWT.NONE);
+ }
+
+ @Override
+ protected boolean shouldAutoRefresh() {
+ return true;
+ }
+ }
+
+ private TaskRepository repository;
+
+ private TaskData taskData;
+
+ private TaskDataModel manager;
+
+ @Override
+ protected void setUp() throws Exception {
+ repository = new TaskRepository(MockRepositoryConnector.CONNECTOR_KIND, MockRepositoryConnector.REPOSITORY_URL);
+ TasksUiPlugin.getRepositoryManager().addRepository(repository);
+
+ taskData = new TaskData(new TaskAttributeMapper(repository), MockRepositoryConnector.CONNECTOR_KIND,
+ MockRepositoryConnector.REPOSITORY_URL, "1");
+
+ manager = createManager();
+ }
+
+ public void testDetermineNotRequired() throws Exception {
+ TaskAttribute attribute = new TaskAttribute(taskData.getRoot(), "not.required.field");
+ MockAttributeEditor editor = new MockAttributeEditor(manager, attribute);
+ assertFalse(editor.isRequired());
+ attribute.setValue("");
+ assertFalse(editor.isRequired());
+ attribute.setValue("abc");
+ assertFalse(editor.isRequired());
+ }
+
+ public void testDetermineRequired() throws Exception {
+ TaskAttribute attribute = new TaskAttribute(taskData.getRoot(), "a.required.field");
+ attribute.getMetaData().setRequired(true);
+ MockAttributeEditor editor = new MockAttributeEditor(manager, attribute);
+ assertTrue(editor.isRequired());
+ attribute.setValue("");
+ assertTrue(editor.isRequired());
+ attribute.setValue("abc");
+ assertFalse(editor.isRequired());
+ }
+
+ public void testDecorateRequired() throws Exception {
+ final StringBuilder eventLog = new StringBuilder();
+ TaskAttribute attribute = new TaskAttribute(taskData.getRoot(), "a.required.field");
+ MockAttributeEditor editor = new MockAttributeEditor(manager, attribute) {
+ @Override
+ protected void decorateRequired() {
+ eventLog.append("decorateRequired");
+ }
+
+ };
+
+ assertEquals("", eventLog.toString());
+ Color someColor = WorkbenchUtil.getShell().getDisplay().getSystemColor(SWT.COLOR_CYAN);
+ editor.decorate(someColor);
+ assertEquals("", eventLog.toString());
+
+ attribute.getMetaData().setRequired(true);
+ editor.decorate(someColor);
+ assertEquals("decorateRequired", eventLog.toString());
+ eventLog.setLength(0);
+
+ attribute.getMetaData().setRequired(false);
+ editor.decorate(someColor);
+ assertEquals("", eventLog.toString());
+ }
+
+ public void testDecorateRequiredOnChange() throws Exception {
+ final StringBuilder eventLog = new StringBuilder();
+ TaskAttribute attribute = new TaskAttribute(taskData.getRoot(), "a.required.field");
+ MockAttributeEditor editor = new MockAttributeEditor(manager, attribute) {
+
+ @Override
+ protected void decorateRequired() {
+ eventLog.append("decorateRequired");
+ }
+
+ @Override
+ public boolean isRequired() {
+ eventLog.append("asked");
+ return super.isRequired();
+ }
+
+ };
+
+ assertEquals("", eventLog.toString());
+ Color someColor = WorkbenchUtil.getShell().getDisplay().getSystemColor(SWT.COLOR_CYAN);
+
+ attribute.getMetaData().setRequired(true);
+ editor.decorate(someColor);
+ assertEquals("askeddecorateRequired", eventLog.toString());
+ eventLog.setLength(0);
+
+ attribute.setValue("someValue");
+ manager.attributeChanged(attribute);
+
+ assertEquals("asked", eventLog.toString());
+ }
+
+ public void testDecorateRequiredReal() throws Exception {
+ TaskAttribute attribute = new TaskAttribute(taskData.getRoot(), "a.required.field");
+ MockAttributeEditor editor = new MockAttributeEditor(manager, attribute);
+
+ Color someColor = WorkbenchUtil.getShell().getDisplay().getSystemColor(SWT.COLOR_CYAN);
+
+ attribute.getMetaData().setRequired(true);
+ editor.decorate(someColor);
+
+ attribute.getMetaData().setRequired(false);
+ manager.attributeChanged(attribute);
+ }
+
+ public void testNoDecorateWithoutLabel() throws Exception {
+ TaskAttribute attribute = new TaskAttribute(taskData.getRoot(), "a.required.field");
+ MockAttributeEditor editor = new MockAttributeEditor(manager, attribute) {
+ @Override
+ public Label getLabelControl() {
+ return null;
+ }
+ };
+
+ Color someColor = WorkbenchUtil.getShell().getDisplay().getSystemColor(SWT.COLOR_CYAN);
+
+ attribute.getMetaData().setRequired(true);
+ editor.decorate(someColor);
+
+ attribute.getMetaData().setRequired(false);
+ manager.attributeChanged(attribute);
+ }
+
+ private TaskDataModel createManager() throws Exception {
+ MockTask task = new MockTask("taskId");
+ TaskDataState state = new TaskDataState("kind", "url", "taskId");
+ state.setEditsData(taskData);
+ state.setLocalTaskData(taskData);
+ TaskDataModel manager = new TaskDataModel(repository, task, state);
+ return manager;
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.ui/icons/ovr16/overlay-required.gif b/org.eclipse.mylyn.tasks.ui/icons/ovr16/overlay-required.gif
new file mode 100644
index 000000000..1b17af928
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.ui/icons/ovr16/overlay-required.gif
Binary files differ
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java
index 49597de80..5cf42dbf3 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java
@@ -25,6 +25,8 @@ public class Messages extends NLS {
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
+ public static String AbstractAttributeEditor_AttributeIsRequired;
+
public static String AbstractReplyToCommentAction_Reply;
public static String AttachmentSizeFormatter_0_bytes;
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties
index cb12598c9..0586ac69e 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties
@@ -8,6 +8,7 @@
# Contributors:
# Tasktop Technologies - initial API and implementation
###############################################################################
+AbstractAttributeEditor_AttributeIsRequired=This attribute is required
AbstractReplyToCommentAction_Reply=Reply
AttachmentSizeFormatter_0_bytes=0 bytes
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractAttributeEditor.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractAttributeEditor.java
index 38291ebdd..f68a8a97a 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractAttributeEditor.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractAttributeEditor.java
@@ -11,16 +11,22 @@
package org.eclipse.mylyn.tasks.ui.editors;
+import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.LegacyActionTools;
+import org.eclipse.jface.fieldassist.ControlDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.mylyn.internal.tasks.ui.editors.Messages;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
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.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
@@ -66,10 +72,13 @@ public abstract class AbstractAttributeEditor {
private final TaskDataModelListener modelListener = new TaskDataModelListener() {
@Override
public void attributeChanged(TaskDataModelEvent event) {
- if (shouldAutoRefresh() && getTaskAttribute().equals(event.getTaskAttribute())) {
+ if (getTaskAttribute().equals(event.getTaskAttribute())) {
try {
- refreshInProgress = true;
- refresh();
+ if (shouldAutoRefresh()) {
+ refreshInProgress = true;
+ refresh();
+ }
+ updateRequiredDecoration();
} catch (UnsupportedOperationException e) {
} finally {
refreshInProgress = false;
@@ -84,6 +93,8 @@ public abstract class AbstractAttributeEditor {
}
};
+ private ControlDecoration decoration;
+
/**
* @since 3.0
*/
@@ -233,10 +244,47 @@ public abstract class AbstractAttributeEditor {
if (manager.hasOutgoingChanges(getTaskAttribute())) {
decorateOutgoing(color);
}
+ updateRequiredDecoration();
+ }
+ }
+
+ private void updateRequiredDecoration() {
+ if (getLabelControl() != null && isRequired()) {
+ decorateRequired();
+ } else if (decoration != null) {
+ decoration.hide();
+ decoration.dispose();
}
}
/**
+ * @since 3.11
+ */
+ protected void decorateRequired() {
+ decoration = new ControlDecoration(getLabelControl(), SWT.TOP | SWT.RIGHT);
+ decoration.setDescriptionText(Messages.AbstractAttributeEditor_AttributeIsRequired);
+ decoration.setMarginWidth(0);
+ Image image = FieldDecorationRegistry.getDefault()
+ .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR)
+ .getImage();
+ decoration.setImage(image);
+ getLabelControl().addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ decoration.dispose();
+ }
+ });
+ }
+
+ /**
+ * @since 3.11
+ */
+ protected boolean isRequired() {
+ boolean isRequired = getTaskAttribute().getMetaData().isRequired();
+ boolean hasValue = !StringUtils.isEmpty(getTaskAttribute().getValue());
+ return isRequired && !hasValue;
+ }
+
+ /**
* @since 3.0
*/
protected void decorateOutgoing(Color color) {

Back to the top