Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspingel2008-10-17 03:22:28 +0000
committerspingel2008-10-17 03:22:28 +0000
commit4e5deca6699b5d66efb9e2c35537eea08cdbb81d (patch)
treef6bf9dd72e27c7c6d06d9aa48f24a63ce787c33b
parentc038d3cf4e51af59c7f1a586553a6aad145c6e6b (diff)
downloadorg.eclipse.mylyn.tasks-4e5deca6699b5d66efb9e2c35537eea08cdbb81d.tar.gz
org.eclipse.mylyn.tasks-4e5deca6699b5d66efb9e2c35537eea08cdbb81d.tar.xz
org.eclipse.mylyn.tasks-4e5deca6699b5d66efb9e2c35537eea08cdbb81d.zip
NEW - bug 244579: [api] move task editor extension out of the sandbox
https://bugs.eclipse.org/bugs/show_bug.cgi?id=244579
-rw-r--r--org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditorPage.java2
-rw-r--r--org.eclipse.mylyn.tasks.ui/plugin.xml7
-rw-r--r--org.eclipse.mylyn.tasks.ui/schema/taskEditorExtensions.exsd152
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/commands/ViewSourceHandler.java103
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java394
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensionReader.java86
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensions.java167
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorRichTextPart.java38
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorExtension.java64
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java2
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorFactory.java27
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/TracTaskEditorPage.java4
12 files changed, 956 insertions, 90 deletions
diff --git a/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditorPage.java b/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditorPage.java
index e0d8ba877..0cd412d67 100644
--- a/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditorPage.java
+++ b/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditorPage.java
@@ -94,7 +94,7 @@ public class BugzillaTaskEditorPage extends AbstractTaskEditorPage {
@Override
protected AttributeEditorFactory createAttributeEditorFactory() {
- AttributeEditorFactory factory = new AttributeEditorFactory(getModel(), getTaskRepository()) {
+ AttributeEditorFactory factory = new AttributeEditorFactory(getModel(), getTaskRepository(), getEditorSite()) {
@Override
public AbstractAttributeEditor createEditor(String type, TaskAttribute taskAttribute) {
AbstractAttributeEditor editor;
diff --git a/org.eclipse.mylyn.tasks.ui/plugin.xml b/org.eclipse.mylyn.tasks.ui/plugin.xml
index 467cc6e41..ab0b85147 100644
--- a/org.eclipse.mylyn.tasks.ui/plugin.xml
+++ b/org.eclipse.mylyn.tasks.ui/plugin.xml
@@ -7,6 +7,7 @@
<extension-point id="projectLinkProviders" name="Linking Provider from Project to the Task Repository" schema="schema/projectLinkProviders.exsd"/>
<extension-point id="duplicateDetectors" name="duplicateDetectors" schema="schema/duplicateDetectors.exsd"/>
<extension-point id="presentations" name="presentations" schema="schema/presentations.exsd"/>
+ <extension-point id="taskEditorExtensions" name="Task Editor Extension" schema="schema/taskEditorExtensions.exsd"/>
<extension
point="org.eclipse.mylyn.context.core.bridges">
@@ -1745,6 +1746,12 @@
id="org.eclipse.mylyn.tasks.ui.command.maximizePart"
name="Maximize Part">
</command>
+ <command
+ categoryId="org.eclipse.mylyn.tasks.ui.commands"
+ defaultHandler="org.eclipse.mylyn.internal.tasks.ui.commands.ViewSourceHandler"
+ id="org.eclipse.mylyn.sandbox.ui.viewSource.command"
+ name="View Source">
+ </command>
</extension>
<extension
point="org.eclipse.ui.bindings">
diff --git a/org.eclipse.mylyn.tasks.ui/schema/taskEditorExtensions.exsd b/org.eclipse.mylyn.tasks.ui/schema/taskEditorExtensions.exsd
new file mode 100644
index 000000000..515d62613
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.ui/schema/taskEditorExtensions.exsd
@@ -0,0 +1,152 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.mylyn.tasks.ui" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.mylyn.tasks.ui" id="taskEditorExtensions" name="Task Editor Extensions"/>
+ </appinfo>
+ <documentation>
+ An extension to the Mylyn task editor that can provide viewing and editing controls that are markup-aware.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="taskEditorExtension" minOccurs="0" maxOccurs="unbounded"/>
+ <element ref="repositoryAssociation" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="taskEditorExtension">
+ <annotation>
+ <documentation>
+ Declare an extension to the Mylyn task editor. Extensions are typically capable of providing improved editing capabilities, such as markup-aware.
+ </documentation>
+ </annotation>
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ the fully qualified class name of the class that extends org.eclipse.mylyn.internal.sandbox.ui.editors.AbstractTaskEditorExtension
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.mylyn.internal.sandbox.ui.editors.AbstractTaskEditorExtension:"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ a unique identifier identifying the extension
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="identifier"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string" use="required">
+ <annotation>
+ <documentation>
+ A human-readable name for the extension that is presented to the Eclipse user in the UI. Should be translated. Used in the UI to identify the type of extension, so the name should indicate what the extension is for, and it should be short so that it can be displayed on one line (for example as an option in a combo box.) Example: &quot;TracWiki&quot;, or &quot;Textile&quot;.
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="repositoryAssociation">
+ <annotation>
+ <documentation>
+ Associate the task editor extension with a kind of repository. Making such an association causes the taskEditorExtension to become the default or preferred setting for a kind of repository.
+ </documentation>
+ </annotation>
+ <complexType>
+ <attribute name="connectorKind" type="string" use="required">
+ <annotation>
+ <documentation>
+ the kind of connector for that this task editor extension should be associated with.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="taskEditorExtension" type="string" use="required">
+ <annotation>
+ <documentation>
+ the id of the taskEditorExtension to associate
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ 3.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiinfo"/>
+ </appinfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="implementation"/>
+ </appinfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+
+</schema>
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/commands/ViewSourceHandler.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/commands/ViewSourceHandler.java
new file mode 100644
index 000000000..0c2f03484
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/commands/ViewSourceHandler.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 Jingwen Ou 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:
+ * Jingwen Ou - initial API and implementation
+ * Tasktop Technologies - improvements
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.ui.commands;
+
+import java.util.Map;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.HandlerEvent;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.IElementUpdater;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.menus.UIElement;
+
+/**
+ * @author Jingwen Ou
+ * @author Steffen Pingel
+ */
+public class ViewSourceHandler extends AbstractHandler implements IElementUpdater {
+
+ private static boolean checked;
+
+ private static ViewSourceHandler instance;
+
+ public ViewSourceHandler() {
+ instance = this;
+ }
+
+ public boolean isChecked() {
+ return checked;
+ }
+
+ public static void setChecked(boolean checked) {
+ ViewSourceHandler.checked = checked;
+ if (instance != null) {
+ instance.fireHandlerChanged(new HandlerEvent(instance, true, false));
+ }
+ }
+
+ private Control getFocusControl() {
+ return PlatformUI.getWorkbench().getDisplay().getFocusControl();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ Control focusControl = getFocusControl();
+ if (focusControl instanceof StyledText && focusControl.getData(VIEW_SOURCE_ACTION) instanceof IAction) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static final String VIEW_SOURCE_ACTION = "viewSourceAction";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ IWorkbenchSite site = HandlerUtil.getActiveSite(event);
+ if (site instanceof IEditorSite) {
+ IWorkbenchPart part = ((IEditorSite) site).getPart();
+ if (part instanceof FormEditor) {
+ IFormPage page = ((FormEditor) part).getActivePageInstance();
+ Control focusedControl = EditorUtil.getFocusControl(page);
+ if (focusedControl != null) {
+ Object data = focusedControl.getData(VIEW_SOURCE_ACTION);
+ if (data instanceof IAction) {
+ IAction action = (IAction) data;
+ action.setChecked(!action.isChecked());
+ action.run();
+ setChecked(action.isChecked());
+ EditorUtil.reflow(focusedControl);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void updateElement(UIElement element, Map parameters) {
+ element.setChecked(checked);
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java
index f412d4237..59646606a 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java
@@ -6,8 +6,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Raphael Ackermann - initial API and implementation
- * Tasktop Technologies - improvements
+ * Tasktop Technologies - initial API and implementation
+ * Raphael Ackermann - spell checking support on bug 195514
+ * Jingwen Ou - extensibility improvements
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.ui.editors;
@@ -15,6 +16,9 @@ package org.eclipse.mylyn.internal.tasks.ui.editors;
import java.util.Iterator;
import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.TextEvent;
@@ -22,23 +26,34 @@ import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonThemes;
+import org.eclipse.mylyn.internal.tasks.ui.commands.ViewSourceHandler;
import org.eclipse.mylyn.internal.tasks.ui.editors.RepositoryTextViewerConfiguration.Mode;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskDataModel;
import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor;
+import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorExtension;
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.custom.StackLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.contexts.IContextActivation;
+import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.texteditor.AnnotationPreference;
@@ -48,27 +63,58 @@ import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.eclipse.ui.themes.IThemeManager;
/**
- * FIXME comment is out dated
+ * A text attribute editor that can switch between a editor, preview and source view.
*
- * Text viewer generally used for displaying non-editable text. No annotation model or spell checking support. Supports
- * cut/copy/paste/etc..
- *
- * For viewing and editing text. Spell checking w/ annotations supported One or two max per editor, any more and the
- * spell checker will bring the editor to a grinding halt.
- *
- * @author Raphael Ackermann (bug 195514)
+ * @author Raphael Ackermann
* @author Steffen Pingel
+ * @author Jingwen Ou
*/
public class RichTextAttributeEditor extends AbstractAttributeEditor {
- private RepositoryTextViewer viewer;
+ private IContextActivation contextActivation;
- private boolean spellCheckingEnabled;
+ private final IContextService contextService;
- private final int style;
+ private SourceViewer defaultViewer;
+
+ private Composite editorComposite;
+
+ private StackLayout editorLayout;
+
+ private final AbstractTaskEditorExtension extension;
+
+ private SourceViewer editorViewer;
+
+ private SourceViewer previewViewer;
private final TaskRepository taskRepository;
+ private FormToolkit toolkit;
+
+ public class ViewSourceAction extends Action {
+
+ public ViewSourceAction() {
+ super("Viewer Source", SWT.TOGGLE);
+ setChecked(false);
+ }
+
+ @Override
+ public void run() {
+ if (isChecked()) {
+ showDefault();
+ } else {
+ showEditor();
+ }
+ }
+
+ }
+
+ private final IAction viewSourceAction = new ViewSourceAction();
+
+ private boolean spellCheckingEnabled;
+
+ private final int style;
+
private Mode mode;
public RichTextAttributeEditor(TaskDataModel manager, TaskRepository taskRepository, TaskAttribute taskAttribute) {
@@ -77,9 +123,16 @@ public class RichTextAttributeEditor extends AbstractAttributeEditor {
public RichTextAttributeEditor(TaskDataModel manager, TaskRepository taskRepository, TaskAttribute taskAttribute,
int style) {
+ this(manager, taskRepository, taskAttribute, style, null, null);
+ }
+
+ public RichTextAttributeEditor(TaskDataModel manager, TaskRepository taskRepository, TaskAttribute taskAttribute,
+ int style, IContextService contextService, AbstractTaskEditorExtension extension) {
super(manager, taskAttribute);
this.taskRepository = taskRepository;
this.style = style;
+ this.contextService = contextService;
+ this.extension = extension;
if ((style & SWT.MULTI) != 0) {
setLayoutHint(new LayoutHint(RowSpan.MULTIPLE, ColumnSpan.MULTIPLE));
} else {
@@ -97,15 +150,58 @@ public class RichTextAttributeEditor extends AbstractAttributeEditor {
this.mode = mode;
}
- private void configureAsTextEditor(Document document) {
+ private void installListeners(final SourceViewer viewer) {
+ viewer.addTextListener(new ITextListener() {
+ public void textChanged(TextEvent event) {
+ // filter out events caused by text presentation changes, e.g. annotation drawing
+ String value = viewer.getTextWidget().getText();
+ if (!getValue().equals(value)) {
+ setValue(value);
+ EditorUtil.ensureVisible(viewer.getTextWidget());
+ }
+ }
+ });
+ // ensure that tab traverses to next control instead of inserting a tab character unless editing multi-line text
+ if ((style & SWT.MULTI) != 0 && mode != Mode.DEFAULT) {
+ viewer.getTextWidget().addListener(SWT.Traverse, new Listener() {
+ public void handleEvent(Event event) {
+ switch (event.detail) {
+ case SWT.TRAVERSE_TAB_NEXT:
+ case SWT.TRAVERSE_TAB_PREVIOUS:
+ event.doit = true;
+ break;
+ }
+ }
+ });
+ }
+ }
+
+ public String getValue() {
+ return getAttributeMapper().getValue(getTaskAttribute());
+ }
+
+ public boolean isSpellCheckingEnabled() {
+ return spellCheckingEnabled;
+ }
+
+ public void setSpellCheckingEnabled(boolean spellCheckingEnabled) {
+ this.spellCheckingEnabled = spellCheckingEnabled;
+ }
+
+ public void setValue(String value) {
+ getAttributeMapper().setValue(getTaskAttribute(), value);
+ attributeChanged();
+ }
+
+ /** Configures annotation model for spell checking. */
+ private void configureAsEditor(SourceViewer viewer, Document document) {
AnnotationModel annotationModel = new AnnotationModel();
viewer.showAnnotations(false);
viewer.showAnnotationsOverview(false);
IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess();
final SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(viewer, null, annotationAccess,
EditorsUI.getSharedTextColors());
- @SuppressWarnings("unchecked")
- Iterator e = new MarkerAnnotationPreferences().getAnnotationPreferences().iterator();
+ Iterator<?> e = new MarkerAnnotationPreferences().getAnnotationPreferences().iterator();
while (e.hasNext()) {
support.setAnnotationPreference((AnnotationPreference) e.next());
}
@@ -115,46 +211,15 @@ public class RichTextAttributeEditor extends AbstractAttributeEditor {
support.uninstall();
}
});
- viewer.getTextWidget().setIndent(2);
+ //viewer.getTextWidget().setIndent(2);
viewer.setDocument(document, annotationModel);
}
- @Override
- public void createControl(Composite parent, FormToolkit toolkit) {
- int style = this.style;
- if (!isReadOnly() && (style & TasksUiInternal.SWT_NO_SCROLL) == 0) {
- style |= SWT.V_SCROLL;
- }
- viewer = new RepositoryTextViewer(taskRepository, parent, SWT.FLAT | SWT.WRAP | style);
-
- // NOTE: configuration must be applied before the document is set in order for
- // hyper link coloring to work, the Presenter requires the document object up front
- configure();
-
- Document document = new Document(getValue());
- if (isReadOnly()) {
- viewer.setEditable(false);
- viewer.setDocument(document);
- } else {
- viewer.setEditable(true);
- configureAsTextEditor(document);
- installListeners(viewer);
- viewer.getControl().setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
- }
-
- IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
- Font font = themeManager.getCurrentTheme().getFontRegistry().get(CommonThemes.FONT_EDITOR_COMMENT);
- viewer.getTextWidget().setFont(font);
- toolkit.adapt(viewer.getTextWidget(), false, false);
-
- setControl(viewer.getTextWidget());
- }
-
- private RepositoryTextViewerConfiguration configure() {
- RepositoryTextViewerConfiguration configuration = new RepositoryTextViewerConfiguration(taskRepository,
- spellCheckingEnabled);
+ private RepositoryTextViewerConfiguration installHyperlinkPresenter(SourceViewer viewer) {
+ RepositoryTextViewerConfiguration configuration = new RepositoryTextViewerConfiguration(taskRepository, false);
configuration.setMode(getMode());
- viewer.configure(configuration);
+
+ // do not configure viewer, this has already been done in extension
AbstractHyperlinkTextPresentationManager manager;
if (getMode() == Mode.DEFAULT) {
@@ -174,51 +239,218 @@ public class RichTextAttributeEditor extends AbstractAttributeEditor {
return configuration;
}
- private void installListeners(RepositoryTextViewer viewer2) {
- viewer.addTextListener(new ITextListener() {
- public void textChanged(TextEvent event) {
- // filter out events caused by text presentation changes, e.g. annotation drawing
- String value = viewer.getTextWidget().getText();
- if (!getValue().equals(value)) {
- setValue(value);
- EditorUtil.ensureVisible(viewer.getTextWidget());
- }
+ private SourceViewer configure(final SourceViewer viewer, boolean readOnly) {
+ // do this before setting the document to not require invalidating the presentation
+ installHyperlinkPresenter(viewer);
+
+ Document document = new Document(getValue());
+ if (readOnly) {
+ viewer.setDocument(document);
+ if (extension != null) {
+ // setting view source action
+ viewer.getControl().setData(ViewSourceHandler.VIEW_SOURCE_ACTION, viewSourceAction);
+ viewer.getControl().addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ ViewSourceHandler.setChecked(getViewer() == defaultViewer);
+ }
+ });
}
- });
- // ensure that tab traverses to next control instead of inserting a tab character unless editing multi-line text
- if ((style & SWT.MULTI) != 0 && mode != Mode.DEFAULT) {
- viewer.getTextWidget().addListener(SWT.Traverse, new Listener() {
- public void handleEvent(Event event) {
- switch (event.detail) {
- case SWT.TRAVERSE_TAB_NEXT:
- case SWT.TRAVERSE_TAB_PREVIOUS:
- event.doit = true;
- break;
+ } else {
+ configureAsEditor(viewer, document);
+ installListeners(viewer);
+ viewer.getControl().setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
+ }
+
+ // enable cut/copy/paste
+ EditorUtil.setTextViewer(viewer.getTextWidget(), viewer);
+ viewer.setEditable(!readOnly);
+ viewer.getTextWidget().setFont(getFont());
+ toolkit.adapt(viewer.getControl(), false, false);
+
+ return viewer;
+ }
+
+ @Override
+ public void createControl(Composite parent, FormToolkit toolkit) {
+ this.toolkit = toolkit;
+
+ int style = this.style;
+ if (!isReadOnly() && (style & TasksUiInternal.SWT_NO_SCROLL) == 0) {
+ style |= SWT.V_SCROLL;
+ }
+
+ if (extension != null) {
+ editorComposite = new Composite(parent, SWT.NULL);
+ editorLayout = new StackLayout() {
+ @Override
+ protected Point computeSize(Composite composite, int hint, int hint2, boolean flushCache) {
+ return topControl.computeSize(hint, hint2, flushCache);
+ }
+ };
+ editorComposite.setLayout(editorLayout);
+ setControl(editorComposite);
+
+ if (isReadOnly()) {
+ editorViewer = extension.createViewer(taskRepository, editorComposite, style);
+ } else {
+ editorViewer = extension.createEditor(taskRepository, editorComposite, style);
+ editorViewer.getTextWidget().addFocusListener(new FocusListener() {
+ public void focusGained(FocusEvent e) {
+ setContext();
+ }
+
+ public void focusLost(FocusEvent e) {
+ unsetContext();
+ }
+ });
+ editorViewer.getTextWidget().addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ unsetContext();
}
+ });
+ }
+ configure(editorViewer, isReadOnly());
+ show(editorViewer);
+ } else {
+ defaultViewer = createDefaultEditor(parent, style);
+ configure(defaultViewer, isReadOnly());
+ setControl(defaultViewer.getControl());
+ }
+ }
+
+ private SourceViewer createDefaultEditor(Composite parent, int styles) {
+ SourceViewer defaultEditor = new RepositoryTextViewer(taskRepository, parent, styles | SWT.WRAP);
+
+ RepositoryTextViewerConfiguration viewerConfig = new RepositoryTextViewerConfiguration(taskRepository,
+ isSpellCheckingEnabled());
+ viewerConfig.setMode(getMode());
+ defaultEditor.configure(viewerConfig);
+
+ return defaultEditor;
+ }
+
+ public SourceViewer getDefaultViewer() {
+ if (defaultViewer == null) {
+ defaultViewer = createDefaultEditor(editorComposite, style);
+ configure(defaultViewer, isReadOnly());
+
+ // fixed font size
+ defaultViewer.getTextWidget().setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT));
+ // adapt maximize action
+ defaultViewer.getControl().setData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION,
+ editorViewer.getControl().getData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION));
+ // adapt menu to the new viewer
+ installMenu(defaultViewer.getControl(), editorViewer.getControl().getMenu());
+ }
+ return defaultViewer;
+ }
+
+ private void installMenu(final Control control, Menu menu) {
+ if (menu != null) {
+ control.setMenu(menu);
+ control.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ control.setMenu(null);
}
});
}
}
- public String getValue() {
- return getAttributeMapper().getValue(getTaskAttribute());
+ private Font getFont() {
+ IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
+ Font font = themeManager.getCurrentTheme().getFontRegistry().get(CommonThemes.FONT_EDITOR_COMMENT);
+ return font;
+ }
+
+ private SourceViewer getPreviewViewer() {
+ if (extension == null) {
+ return null;
+ }
+
+ // construct as needed
+ if (previewViewer == null) {
+ previewViewer = extension.createViewer(taskRepository, editorComposite, style);
+ configure(previewViewer, true);
+ // adapt maximize action
+ previewViewer.getControl().setData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION,
+ editorViewer.getControl().getData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION));
+ }
+ Document document = new Document(editorViewer.getDocument().get());
+ previewViewer.setDocument(document);
+ return previewViewer;
+ }
+
+ public SourceViewer getEditorViewer() {
+ return editorViewer;
}
public SourceViewer getViewer() {
- return viewer;
+ if (editorLayout == null) {
+ return defaultViewer;
+ }
+ if (defaultViewer != null && editorLayout.topControl == defaultViewer.getControl()) {
+ return defaultViewer;
+ } else if (previewViewer != null && editorLayout.topControl == previewViewer.getControl()) {
+ return previewViewer;
+ } else {
+ return editorViewer;
+ }
}
- public boolean isSpellCheckingEnabled() {
- return spellCheckingEnabled;
+ private void setContext() {
+ if (contextService == null) {
+ return;
+ }
+ if (contextActivation != null) {
+ contextService.deactivateContext(contextActivation);
+ contextActivation = null;
+ }
+ if (contextService != null && extension.getEditorContextId() != null) {
+ contextActivation = contextService.activateContext(extension.getEditorContextId());
+ }
}
- public void setSpellCheckingEnabled(boolean spellCheckingEnabled) {
- this.spellCheckingEnabled = spellCheckingEnabled;
+ /**
+ * Brings <code>viewer</code> to top.
+ */
+ private void show(SourceViewer viewer) {
+ // no extension is available
+ if (editorComposite == null) {
+ return;
+ }
+
+ editorLayout.topControl = viewer.getControl();
+ editorComposite.layout();
+ viewer.getControl().setFocus();
}
- public void setValue(String value) {
- getAttributeMapper().setValue(getTaskAttribute(), value);
- attributeChanged();
+ public void showDefault() {
+ show(getDefaultViewer());
+ }
+
+ public void showPreview() {
+ if (!isReadOnly()) {
+ show(getPreviewViewer());
+ }
+ }
+
+ public void showEditor() {
+ show(getEditorViewer());
+ }
+
+ private void unsetContext() {
+ if (contextService == null) {
+ return;
+ }
+ if (contextActivation != null) {
+ contextService.deactivateContext(contextActivation);
+ contextActivation = null;
+ }
+ }
+
+ public boolean hasPreview() {
+ return extension != null && !isReadOnly();
}
}
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensionReader.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensionReader.java
new file mode 100644
index 000000000..4e74bbd09
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensionReader.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 David Green 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:
+ * David Green - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.ui.editors;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.commons.core.StatusHandler;
+import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
+import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorExtension;
+
+/**
+ * @author David Green
+ */
+public class TaskEditorExtensionReader {
+
+ private static final String CONNECTOR_KIND = "connectorKind";
+
+ public static final String ATTR_ID = "id";
+
+ public static final String ATTR_NAME = "name";
+
+ public static final String EXTENSION_TASK_EDITOR_EXTENSIONS = "org.eclipse.mylyn.tasks.ui.taskEditorExtensions";
+
+ private static final String REPOSITORY_ASSOCIATION = "repositoryAssociation";
+
+ private static final String TASK_EDITOR_EXTENSION = "taskEditorExtension";
+
+ public static void initExtensions() {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+
+ IExtensionPoint editorExtensionPoint = registry.getExtensionPoint(EXTENSION_TASK_EDITOR_EXTENSIONS);
+ IExtension[] editorExtensions = editorExtensionPoint.getExtensions();
+ for (IExtension extension : editorExtensions) {
+ IConfigurationElement[] elements = extension.getConfigurationElements();
+ for (IConfigurationElement element : elements) {
+ if (element.getName().equals(TASK_EDITOR_EXTENSION)) {
+ readEditorExtension(element);
+ } else if (element.getName().equals(REPOSITORY_ASSOCIATION)) {
+ readEditorExtensionAssociation(element);
+ }
+ }
+ }
+ }
+
+ private static void readEditorExtension(IConfigurationElement element) {
+ try {
+ String id = element.getAttribute(ATTR_ID);
+ String name = element.getAttribute(ATTR_NAME);
+ AbstractTaskEditorExtension extension = (AbstractTaskEditorExtension) element.createExecutableExtension("class");
+ TaskEditorExtensions.addTaskEditorExtension(id, name, extension);
+ } catch (CoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not load taskEditorExtension",
+ e));
+ } catch (Exception e) {
+ StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not load taskEditorExtension",
+ e));
+ }
+ }
+
+ private static void readEditorExtensionAssociation(IConfigurationElement element) {
+ try {
+ String repository = element.getAttribute(CONNECTOR_KIND);
+ String taskEditorExtension = element.getAttribute(TASK_EDITOR_EXTENSION);
+ TaskEditorExtensions.addRepositoryAssociation(repository, taskEditorExtension);
+ } catch (Exception e) {
+ StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
+ "Could not load repositoryAssociation", e));
+ }
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensions.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensions.java
new file mode 100644
index 000000000..6e08fd414
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensions.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 David Green 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:
+ * David Green - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.ui.editors;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.commons.core.StatusHandler;
+import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorExtension;
+
+/**
+ * @author David Green
+ */
+public class TaskEditorExtensions {
+
+ public static final String REPOSITORY_PROPERTY_EDITOR_EXTENSION = "editorExtension";
+
+ private static Map<String, RegisteredTaskEditorExtension> extensionsById = new HashMap<String, RegisteredTaskEditorExtension>();
+
+ private static Map<String, String> associationByConnectorKind = new HashMap<String, String>();
+
+ private static boolean initialized;
+
+ public static SortedSet<RegisteredTaskEditorExtension> getTaskEditorExtensions() {
+ init();
+ return new TreeSet<RegisteredTaskEditorExtension>(extensionsById.values());
+ }
+
+ public static void addTaskEditorExtension(String id, String name, AbstractTaskEditorExtension extension) {
+ Assert.isNotNull(id);
+ RegisteredTaskEditorExtension previous = extensionsById.put(id, new RegisteredTaskEditorExtension(extension,
+ id, name));
+ if (previous != null) {
+ StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Duplicate taskEditorExtension id="
+ + id, null));
+ }
+ }
+
+ public static void addRepositoryAssociation(String connectorKind, String extensionId) {
+ if (connectorKind == null || extensionId == null) {
+ throw new IllegalArgumentException();
+ }
+ String previous = associationByConnectorKind.put(connectorKind, extensionId);
+ if (previous != null) {
+ StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, String.format(
+ "Duplicate association for repository %s: %s replaces %s", connectorKind, extensionId, previous),
+ null));
+ }
+ }
+
+ /**
+ * get a task editor extension for a specific repository
+ *
+ * @param taskRepository
+ * @return the extension, or null if there is none
+ *
+ * @see #getDefaultTaskEditorExtension(TaskRepository)
+ */
+ public static AbstractTaskEditorExtension getTaskEditorExtension(TaskRepository taskRepository) {
+ init();
+ String extensionId = getTaskEditorExtensionId(taskRepository);
+ if (extensionId != null) {
+ RegisteredTaskEditorExtension taskEditorExtension = extensionsById.get(extensionId);
+ return taskEditorExtension == null ? null : taskEditorExtension.getExtension();
+ }
+ return null;
+ }
+
+ public static String getTaskEditorExtensionId(TaskRepository taskRepository) {
+ init();
+ String id = taskRepository.getProperty(REPOSITORY_PROPERTY_EDITOR_EXTENSION);
+ if (id == null) {
+ // TODO 3.1 disabled until bug 244653 is resolved
+ //id = getDefaultTaskEditorExtensionId(taskRepository);
+ }
+ return id;
+ }
+
+ public static void setTaskEditorExtensionId(TaskRepository repository, String editorExtensionId) {
+ repository.setProperty(REPOSITORY_PROPERTY_EDITOR_EXTENSION, editorExtensionId);
+ }
+
+ public static String getDefaultTaskEditorExtensionId(TaskRepository taskRepository) {
+ init();
+ return associationByConnectorKind.get(taskRepository.getConnectorKind());
+ }
+
+ /**
+ * get a default task editor extension for a specific repository
+ *
+ * @param taskRepository
+ * @return the extension, or null if there is none
+ *
+ * @see #getTaskEditorExtension(TaskRepository)
+ */
+ public static AbstractTaskEditorExtension getDefaultTaskEditorExtension(TaskRepository taskRepository) {
+ init();
+ String extensionId = getDefaultTaskEditorExtensionId(taskRepository);
+ if (extensionId != null) {
+ RegisteredTaskEditorExtension taskEditorExtension = extensionsById.get(extensionId);
+ return taskEditorExtension == null ? null : taskEditorExtension.getExtension();
+ }
+ return null;
+ }
+
+ private static void init() {
+ if (!initialized) {
+ initialized = true;
+ TaskEditorExtensionReader.initExtensions();
+ }
+ }
+
+ public static class RegisteredTaskEditorExtension implements Comparable<RegisteredTaskEditorExtension> {
+
+ private final String id;
+
+ private final String name;
+
+ private final AbstractTaskEditorExtension extension;
+
+ private RegisteredTaskEditorExtension(AbstractTaskEditorExtension extension, String id, String name) {
+ this.extension = extension;
+ this.id = id;
+ this.name = name;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public AbstractTaskEditorExtension getExtension() {
+ return extension;
+ }
+
+ public int compareTo(RegisteredTaskEditorExtension o) {
+ if (o == this) {
+ return 0;
+ }
+ int i = name.compareTo(o.name);
+ if (i == 0) {
+ i = id.compareTo(o.id);
+ }
+ return i;
+ }
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorRichTextPart.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorRichTextPart.java
index d02fc9705..ee1d245a8 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorRichTextPart.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorRichTextPart.java
@@ -14,6 +14,7 @@ package org.eclipse.mylyn.internal.tasks.ui.editors;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages;
@@ -27,6 +28,7 @@ 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.Control;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
@@ -158,6 +160,12 @@ public class TaskEditorRichTextPart extends AbstractTaskEditorPart {
}
}
+ getEditor().getControl().setData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION, getMaximizePartAction());
+ if (getEditor().getControl() instanceof Composite) {
+ for (Control control : ((Composite) getEditor().getControl()).getChildren()) {
+ control.setData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION, getMaximizePartAction());
+ }
+ }
getTaskEditorPage().getAttributeEditorToolkit().adapt(editor);
toolkit.paintBordersFor(composite);
@@ -234,10 +242,6 @@ public class TaskEditorRichTextPart extends AbstractTaskEditorPart {
@Override
public void run() {
- toogleToMaximizePart();
- }
-
- private void toogleToMaximizePart() {
if (!(getEditor().getControl().getLayoutData() instanceof GridData)) {
return;
}
@@ -273,4 +277,30 @@ public class TaskEditorRichTextPart extends AbstractTaskEditorPart {
}
}
+ @Override
+ protected void fillToolBar(ToolBarManager manager) {
+ if (getEditor().hasPreview()) {
+ Action toggleEditingAction = new Action("", SWT.TOGGLE) {
+ @Override
+ public void run() {
+ toggleEditing(this);
+ }
+ };
+ toggleEditingAction.setImageDescriptor(CommonImages.PREVIEW_WEB);
+ toggleEditingAction.setToolTipText("Preview");
+ toggleEditingAction.setChecked(false);
+ manager.add(toggleEditingAction);
+ }
+ manager.add(getMaximizePartAction());
+ super.fillToolBar(manager);
+ }
+
+ private void toggleEditing(Action action) {
+ if (action.isChecked()) {
+ editor.showPreview();
+ } else {
+ editor.showEditor();
+ }
+ }
+
}
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorExtension.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorExtension.java
new file mode 100644
index 000000000..1bf8c010a
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorExtension.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 David Green 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:
+ * David Green - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.tasks.ui.editors;
+
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.contexts.IContextService;
+
+/**
+ * An extension that provides task editor capabilities beyond the default, oriented towards providing markup-aware
+ * editing and viewing
+ *
+ * @author David Green
+ * @since 3.1
+ */
+public abstract class AbstractTaskEditorExtension {
+
+ /**
+ * The key to access the {@link TaskRepository} property that stores the URL of an associated wiki.
+ */
+ public static final String INTERNAL_WIKI_LINK_PATTERN = "wikiLinkPattern";
+
+ /**
+ * Creates a source viewer that can be used to view content in the task editor. The source viewer should be
+ * configured with a source viewer configuration prior to returning.
+ *
+ * @param taskRepository
+ * the task repository for which the viewer is created
+ * @param parent
+ * the control parent of the source viewer
+ * @param style
+ * the styles to use
+ */
+ public abstract SourceViewer createViewer(TaskRepository taskRepository, Composite parent, int style);
+
+ /**
+ * Creates a source viewer that can be used to edit content in the task editor. The source viewer should be
+ * configured with a source viewer configuration prior to returning.
+ *
+ * @param taskRepository
+ * the task repository for which the viewer is created
+ * @param parent
+ * the control parent of the source viewer
+ * @param style
+ * the styles to use
+ */
+ public abstract SourceViewer createEditor(TaskRepository taskRepository, Composite parent, int style);
+
+ /**
+ * Returns the editor context id, to be passed to the {@link IContextService} when the editor is in focus.
+ */
+ public abstract String getEditorContextId();
+
+}
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java
index 30a6bff5e..ebcbecc2d 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java
@@ -487,7 +487,7 @@ public abstract class AbstractTaskEditorPage extends FormPage implements ISelect
}
protected AttributeEditorFactory createAttributeEditorFactory() {
- return new AttributeEditorFactory(getModel(), getTaskRepository());
+ return new AttributeEditorFactory(getModel(), getTaskRepository(), getEditorSite());
}
AttributeEditorToolkit createAttributeEditorToolkit() {
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorFactory.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorFactory.java
index 25647899d..7d3c9cf10 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorFactory.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2004, 2008 Tasktop Technologies and others.
+ * Copyright (c) 2004, 2008 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
@@ -19,6 +19,7 @@ import org.eclipse.mylyn.internal.tasks.ui.editors.MultiSelectionAttributeEditor
import org.eclipse.mylyn.internal.tasks.ui.editors.PersonAttributeEditor;
import org.eclipse.mylyn.internal.tasks.ui.editors.RichTextAttributeEditor;
import org.eclipse.mylyn.internal.tasks.ui.editors.SingleSelectionAttributeEditor;
+import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorExtensions;
import org.eclipse.mylyn.internal.tasks.ui.editors.TextAttributeEditor;
import org.eclipse.mylyn.internal.tasks.ui.editors.RepositoryTextViewerConfiguration.Mode;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
@@ -28,6 +29,8 @@ import org.eclipse.mylyn.tasks.core.data.TaskDataModel;
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.ui.contexts.IContextService;
+import org.eclipse.ui.services.IServiceLocator;
/**
* @since 3.0
@@ -39,9 +42,21 @@ public class AttributeEditorFactory {
private final TaskRepository taskRepository;
+ private final IServiceLocator serviceLocator;
+
public AttributeEditorFactory(TaskDataModel model, TaskRepository taskRepository) {
+ this(model, taskRepository, null);
+ }
+
+ /**
+ * @since 3.1
+ */
+ public AttributeEditorFactory(TaskDataModel model, TaskRepository taskRepository, IServiceLocator serviceLocator) {
+ Assert.isNotNull(model);
+ Assert.isNotNull(taskRepository);
this.model = model;
this.taskRepository = taskRepository;
+ this.serviceLocator = serviceLocator;
}
public AbstractAttributeEditor createEditor(String type, TaskAttribute taskAttribute) {
@@ -54,6 +69,16 @@ public class AttributeEditorFactory {
} else if (TaskAttribute.TYPE_PERSON.equals(type)) {
return new PersonAttributeEditor(model, taskAttribute);
} else if (TaskAttribute.TYPE_LONG_RICH_TEXT.equals(type)) {
+ if (serviceLocator != null) {
+ IContextService contextService = (IContextService) serviceLocator.getService(IContextService.class);
+ if (contextService != null) {
+ AbstractTaskEditorExtension extension = TaskEditorExtensions.getTaskEditorExtension(model.getTaskRepository());
+ if (extension != null) {
+ return new RichTextAttributeEditor(model, taskRepository, taskAttribute, SWT.MULTI,
+ contextService, extension);
+ }
+ }
+ }
return new RichTextAttributeEditor(model, taskRepository, taskAttribute);
} else if (TaskAttribute.TYPE_LONG_TEXT.equals(type)) {
return new LongTextAttributeEditor(model, taskAttribute);
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/TracTaskEditorPage.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/TracTaskEditorPage.java
index 1ea1c51ae..d9e1c9a05 100644
--- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/TracTaskEditorPage.java
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/TracTaskEditorPage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2006, 2008 Steffen Pingel and others.
+ * Copyright (c) 2006, 2008 Steffen Pingel 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
@@ -65,7 +65,7 @@ public class TracTaskEditorPage extends AbstractTaskEditorPage {
@Override
protected AttributeEditorFactory createAttributeEditorFactory() {
- AttributeEditorFactory factory = new AttributeEditorFactory(getModel(), getTaskRepository()) {
+ AttributeEditorFactory factory = new AttributeEditorFactory(getModel(), getTaskRepository(), getEditorSite()) {
@Override
public AbstractAttributeEditor createEditor(String type, TaskAttribute taskAttribute) {
if (TracAttribute.CC.getTracKey().equals(taskAttribute.getId())) {

Back to the top