### Eclipse Workspace Patch 1.0
#P org.eclipse.mylyn.commons.ui
Index: src/org/eclipse/mylyn/internal/provisional/commons/ui/CommonTextSupport.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/internal/provisional/commons/ui/CommonTextSupport.java,v
retrieving revision 1.1
diff -u -r1.1 CommonTextSupport.java
--- src/org/eclipse/mylyn/internal/provisional/commons/ui/CommonTextSupport.java 13 Jan 2009 08:43:27 -0000 1.1
+++ src/org/eclipse/mylyn/internal/provisional/commons/ui/CommonTextSupport.java 27 May 2009 07:30:28 -0000
@@ -25,6 +25,7 @@
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
@@ -208,6 +209,7 @@
private ISelectionChangedListener selectionChangedListener;
public CommonTextSupport(IHandlerService handlerService) {
+ Assert.isNotNull(handlerService);
this.handlerService = handlerService;
}
#P org.eclipse.mylyn.tasks.ui
Index: src/org/eclipse/mylyn/tasks/ui/wizards/TaskAttachmentPage.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/wizards/TaskAttachmentPage.java,v
retrieving revision 1.21
diff -u -r1.21 TaskAttachmentPage.java
--- src/org/eclipse/mylyn/tasks/ui/wizards/TaskAttachmentPage.java 8 Apr 2009 04:54:10 -0000 1.21
+++ src/org/eclipse/mylyn/tasks/ui/wizards/TaskAttachmentPage.java 27 May 2009 07:30:29 -0000
@@ -20,11 +20,15 @@
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.mylyn.context.core.ContextCore;
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages;
+import org.eclipse.mylyn.internal.provisional.commons.ui.CommonTextSupport;
import org.eclipse.mylyn.internal.tasks.core.data.FileTaskAttachmentSource;
+import org.eclipse.mylyn.internal.tasks.ui.editors.RichTextEditor;
+import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorExtensions;
import org.eclipse.mylyn.internal.tasks.ui.wizards.Messages;
import org.eclipse.mylyn.tasks.core.data.TaskAttachmentMapper;
import org.eclipse.mylyn.tasks.core.data.TaskAttachmentModel;
import org.eclipse.mylyn.tasks.ui.TasksUiImages;
+import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorExtension;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
@@ -38,6 +42,10 @@
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.contexts.IContextActivation;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.handlers.IHandlerService;
/**
* A wizard page to enter details of a new attachment.
@@ -64,7 +72,7 @@
private Button attachContextButton;
- private Text commentText;
+ private RichTextEditor commentEditor;
private Text descriptionText;
@@ -82,6 +90,12 @@
private boolean first = true;
+ private IContextService contextService;
+
+ private IContextActivation commentContext;
+
+ private CommonTextSupport textSupport;
+
public TaskAttachmentPage(TaskAttachmentModel model) {
super("AttachmentDetails"); //$NON-NLS-1$
this.model = model;
@@ -120,14 +134,30 @@
Label label = new Label(composite, SWT.NONE);
label.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
label.setText(Messages.TaskAttachmentPage_Comment);
- commentText = new Text(composite, SWT.V_SCROLL | SWT.BORDER | SWT.WRAP);
- commentText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
- commentText.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- apply();
+ AbstractTaskEditorExtension extension = TaskEditorExtensions.getTaskEditorExtension(model.getTaskRepository());
+ String contextId = extension.getEditorContextId();
+ if (contextId != null) {
+ contextService = (IContextService) PlatformUI.getWorkbench().getService(IContextService.class);
+ if (contextService != null) {
+ commentContext = contextService.activateContext(contextId);
}
+ }
- });
+ commentEditor = new RichTextEditor(getModel().getTaskRepository(), SWT.V_SCROLL | SWT.BORDER | SWT.WRAP,
+ contextService, extension) {
+ @Override
+ protected void valueChanged(String value) {
+ apply();
+ };
+ };
+ commentEditor.createControl(composite, null);
+ commentEditor.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+
+ IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
+ if (handlerService != null) {
+ textSupport = new CommonTextSupport(handlerService);
+ textSupport.install(commentEditor.getViewer(), true);
+ }
new Label(composite, SWT.NONE).setText(Messages.TaskAttachmentPage_Content_Type);// .setBackground(parent.getBackground());
@@ -223,7 +253,7 @@
if (descriptionText != null) {
descriptionText.setFocus();
} else {
- commentText.setFocus();
+ commentEditor.getControl().setFocus();
}
Dialog.applyDialogFont(composite);
@@ -249,7 +279,7 @@
private void apply() {
taskAttachment.applyTo(model.getAttribute());
- model.setComment(commentText.getText());
+ model.setComment(commentEditor.getText());
model.setAttachContext(attachContextButton.getSelection());
model.setContentType(taskAttachment.getContentType());
}
@@ -305,10 +335,22 @@
if (descriptionText != null) {
descriptionText.setFocus();
} else {
- commentText.setFocus();
+ commentEditor.getControl().setFocus();
}
first = false;
}
}
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (contextService != null && commentContext != null) {
+ contextService.deactivateContext(commentContext);
+ commentContext = null;
+ }
+ if (textSupport != null) {
+ textSupport.dispose();
+ }
+ }
+
}
Index: src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java,v
retrieving revision 1.37
diff -u -r1.37 RichTextAttributeEditor.java
--- src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java 30 Apr 2009 04:03:35 -0000 1.37
+++ src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java 27 May 2009 07:30:29 -0000
@@ -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
@@ -7,31 +7,14 @@
*
* Contributors:
* Tasktop Technologies - initial API and implementation
- * Raphael Ackermann - spell checking support on bug 195514
- * Jingwen Ou - extensibility improvements
- * David Green - fix for bug 256702
*******************************************************************************/
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;
-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.CommonFormUtil;
-import org.eclipse.mylyn.internal.provisional.commons.ui.CommonTextSupport;
-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;
@@ -42,93 +25,23 @@
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;
-import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
-import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
-import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
-import org.eclipse.ui.themes.IThemeManager;
/**
* A text attribute editor that can switch between a editor, preview and source view.
*
- * @author Raphael Ackermann
* @author Steffen Pingel
- * @author Jingwen Ou
+ * @see RichTextEditor
*/
public class RichTextAttributeEditor extends AbstractAttributeEditor {
- private IContextActivation contextActivation;
-
- private final IContextService contextService;
-
- 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(Messages.RichTextAttributeEditor_Viewer_Source, SWT.TOGGLE);
- setChecked(false);
- setEnabled(false);
- }
-
- @Override
- public void run() {
- if (isChecked()) {
- showDefault();
- } else {
- showEditor();
- }
- if (editorLayout != null) {
- EditorUtil.reflow(editorLayout.topControl);
- }
- ViewSourceHandler.setChecked(isChecked());
- }
-
- }
-
- private final IAction viewSourceAction = new ViewSourceAction();
-
- private boolean spellCheckingEnabled;
-
- private final int style;
+ private final RichTextEditor editor;
private Mode mode;
- private AbstractRenderingEngine renderingEngine;
-
- private BrowserPreviewViewer browserViewer;
+ protected boolean ignoreNotification;
public RichTextAttributeEditor(TaskDataModel manager, TaskRepository taskRepository, TaskAttribute taskAttribute) {
this(manager, taskRepository, taskAttribute, SWT.MULTI);
@@ -142,397 +55,116 @@
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;
+ this.editor = new RichTextEditor(taskRepository, style, contextService, extension) {
+ @Override
+ public void valueChanged(String value) {
+ if (!ignoreNotification) {
+ RichTextAttributeEditor.this.setValue(value);
+ }
+ };
+ };
+ this.editor.setReadOnly(isReadOnly());
if ((style & SWT.MULTI) != 0) {
setLayoutHint(new LayoutHint(RowSpan.MULTIPLE, ColumnSpan.MULTIPLE));
} else {
setLayoutHint(new LayoutHint(RowSpan.SINGLE, ColumnSpan.MULTIPLE));
}
setMode(Mode.DEFAULT);
- }
-
- public Mode getMode() {
- return mode;
- }
-
- public void setMode(Mode mode) {
- Assert.isNotNull(mode);
- this.mode = mode;
- }
-
- 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);
- CommonFormUtil.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());
- Iterator> e = new MarkerAnnotationPreferences().getAnnotationPreferences().iterator();
- while (e.hasNext()) {
- support.setAnnotationPreference((AnnotationPreference) e.next());
- }
- support.install(EditorsUI.getPreferenceStore());
- viewer.getTextWidget().addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- support.uninstall();
- }
- });
- //viewer.getTextWidget().setIndent(2);
- viewer.setDocument(document, annotationModel);
- }
-
- private RepositoryTextViewerConfiguration installHyperlinkPresenter(SourceViewer viewer) {
- RepositoryTextViewerConfiguration configuration = new RepositoryTextViewerConfiguration(taskRepository, false);
- configuration.setMode(getMode());
-
- // do not configure viewer, this has already been done in extension
-
- AbstractHyperlinkTextPresentationManager manager;
- if (getMode() == Mode.DEFAULT) {
- manager = new HighlightingHyperlinkTextPresentationManager();
- manager.setHyperlinkDetectors(configuration.getDefaultHyperlinkDetectors(viewer, null));
- manager.install(viewer);
-
- manager = new TaskHyperlinkTextPresentationManager();
- manager.setHyperlinkDetectors(configuration.getDefaultHyperlinkDetectors(viewer, Mode.TASK));
- manager.install(viewer);
- } else if (getMode() == Mode.TASK_RELATION) {
- manager = new TaskHyperlinkTextPresentationManager();
- manager.setHyperlinkDetectors(configuration.getDefaultHyperlinkDetectors(viewer, Mode.TASK_RELATION));
- manager.install(viewer);
- }
-
- return configuration;
- }
-
- 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);
- }
- });
- }
- } else {
- configureAsEditor(viewer, document);
- installListeners(viewer);
- viewer.getControl().setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
- }
-
- // enable cut/copy/paste
- CommonTextSupport.setTextViewer(viewer.getTextWidget(), viewer);
- viewer.setEditable(!readOnly);
- viewer.getTextWidget().setFont(getFont());
- toolkit.adapt(viewer.getControl(), false, false);
-
- return viewer;
+ refresh();
}
@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 || renderingEngine != 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 (extension != null) {
- 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(editorComposite, style);
- configure(defaultViewer, isReadOnly());
- show(defaultViewer);
- }
-
- if (!isReadOnly() && (style & TasksUiInternal.SWT_NO_SCROLL) == 0) {
- editorComposite.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
- }
-
- viewSourceAction.setEnabled(true);
- } else {
- defaultViewer = createDefaultEditor(parent, style);
- configure(defaultViewer, isReadOnly());
- setControl(defaultViewer.getControl());
-
- viewSourceAction.setEnabled(false);
- }
+ editor.createControl(parent, toolkit);
+ setControl(editor.getControl());
}
- private SourceViewer createDefaultEditor(Composite parent, int styles) {
- SourceViewer defaultEditor = new SourceViewer(parent, null, styles | SWT.WRAP);
-
- RepositoryTextViewerConfiguration viewerConfig = new RepositoryTextViewerConfiguration(taskRepository,
- isSpellCheckingEnabled() && !isReadOnly());
- 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 SourceViewer getEditorViewer() {
+ return editor.getEditorViewer();
}
- private Font getFont() {
- IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
- Font font = themeManager.getCurrentTheme().getFontRegistry().get(CommonThemes.FONT_EDITOR_COMMENT);
- return font;
+ public Mode getMode() {
+ return mode;
}
- private SourceViewer getPreviewViewer() {
- if (extension == null) {
- return null;
- }
-
- // construct as needed
- if (previewViewer == null) {
- // previewer should always have a vertical scroll bar if it's editable
- int previewViewerStyle = style;
- if (getEditorViewer() != null) {
- previewViewerStyle |= SWT.V_SCROLL;
- }
- previewViewer = extension.createViewer(taskRepository, editorComposite, previewViewerStyle);
- 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 AbstractRenderingEngine getRenderingEngine() {
+ return editor.getRenderingEngine();
}
- public SourceViewer getEditorViewer() {
- return editorViewer;
+ public String getValue() {
+ return getAttributeMapper().getValue(getTaskAttribute());
}
public SourceViewer getViewer() {
- 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;
- }
+ return editor.getViewer();
}
- 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 IAction getViewSourceAction() {
+ return editor.getViewSourceAction();
}
- /**
- * Brings viewer
to top.
- */
- private void show(SourceViewer viewer) {
- show(viewer.getControl());
+ public boolean hasBrowser() {
+ return editor.hasBrowser();
}
- /**
- * Brings control
to top.
- */
- private void show(Control control) {
- // no extension is available
- if (editorComposite == null) {
- return;
- }
-
- editorLayout.topControl = control;
- if (editorComposite.getParent().getLayout() instanceof FillWidthLayout) {
- ((FillWidthLayout) editorComposite.getParent().getLayout()).flush();
- }
- editorComposite.layout();
- control.setFocus();
+ public boolean hasPreview() {
+ return editor.hasPreview();
}
- public void showDefault() {
- show(getDefaultViewer());
+ public boolean isSpellCheckingEnabled() {
+ return editor.isSpellCheckingEnabled();
}
- public void showPreview() {
- if (!isReadOnly()) {
- show(getPreviewViewer());
- }
+ public void setMode(Mode mode) {
+ Assert.isNotNull(mode);
+ this.mode = mode;
}
- public void showEditor() {
- if (getEditorViewer() != null) {
- show(getEditorViewer());
- } else {
- show(getDefaultViewer());
- }
+ public void setRenderingEngine(AbstractRenderingEngine renderingEngine) {
+ editor.setRenderingEngine(renderingEngine);
}
- private void unsetContext() {
- if (contextService == null) {
- return;
- }
- if (contextActivation != null) {
- contextService.deactivateContext(contextActivation);
- contextActivation = null;
- }
+ public void setSpellCheckingEnabled(boolean spellCheckingEnabled) {
+ editor.setSpellCheckingEnabled(spellCheckingEnabled);
}
- public boolean hasPreview() {
- return extension != null && !isReadOnly();
+ public void setValue(String value) {
+ getAttributeMapper().setValue(getTaskAttribute(), value);
+ attributeChanged();
}
- public boolean hasBrowser() {
- return renderingEngine != null;
+ public void showBrowser() {
+ editor.showBrowser();
}
- private BrowserPreviewViewer getBrowserViewer() {
- if (editorComposite == null || renderingEngine == null) {
- return null;
- }
-
- if (browserViewer == null) {
- browserViewer = new BrowserPreviewViewer(getModel().getTaskRepository(), renderingEngine);
- browserViewer.createControl(editorComposite, toolkit);
- }
- return browserViewer;
+ public void showDefault() {
+ editor.showDefault();
}
- public AbstractRenderingEngine getRenderingEngine() {
- return renderingEngine;
+ public void showEditor() {
+ editor.showEditor();
}
- public void setRenderingEngine(AbstractRenderingEngine renderingEngine) {
- this.renderingEngine = renderingEngine;
+ public void showPreview() {
+ editor.showPreview();
}
- public void showBrowser() {
- BrowserPreviewViewer viewer = getBrowserViewer();
- viewer.update(getValue());
- if (viewer != null) {
- show(viewer.getControl());
+ @Override
+ public void setReadOnly(boolean readOnly) {
+ super.setReadOnly(readOnly);
+ if (editor != null) {
+ editor.setReadOnly(readOnly);
}
}
- public IAction getViewSourceAction() {
- return viewSourceAction;
+ @Override
+ public void refresh() {
+ try {
+ ignoreNotification = true;
+ editor.setText(getValue());
+ } finally {
+ ignoreNotification = false;
+ }
}
}
Index: src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextEditor.java
===================================================================
RCS file: src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextEditor.java
diff -N src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextEditor.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextEditor.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,557 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ * Raphael Ackermann - spell checking support on bug 195514
+ * Jingwen Ou - extensibility improvements
+ * David Green - fix for bug 256702
+ *******************************************************************************/
+
+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;
+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.CommonFormUtil;
+import org.eclipse.mylyn.internal.provisional.commons.ui.CommonTextSupport;
+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.ui.editors.AbstractRenderingEngine;
+import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorExtension;
+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;
+import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
+import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+import org.eclipse.ui.themes.IThemeManager;
+
+/**
+ * A text attribute editor that can switch between a editor, preview and source view.
+ *
+ * @author Raphael Ackermann
+ * @author Steffen Pingel
+ * @author Jingwen Ou
+ */
+public class RichTextEditor {
+
+ public class ViewSourceAction extends Action {
+
+ public ViewSourceAction() {
+ super(Messages.RichTextAttributeEditor_Viewer_Source, SWT.TOGGLE);
+ setChecked(false);
+ setEnabled(false);
+ }
+
+ @Override
+ public void run() {
+ if (isChecked()) {
+ showDefault();
+ } else {
+ showEditor();
+ }
+ if (editorLayout != null) {
+ EditorUtil.reflow(editorLayout.topControl);
+ }
+ ViewSourceHandler.setChecked(isChecked());
+ }
+
+ }
+
+ private BrowserPreviewViewer browserViewer;
+
+ private IContextActivation contextActivation;
+
+ private final IContextService contextService;
+
+ private Control control;
+
+ private SourceViewer defaultViewer;
+
+ private final Document document;
+
+ private Composite editorComposite;
+
+ private StackLayout editorLayout;
+
+ private SourceViewer editorViewer;
+
+ private final AbstractTaskEditorExtension extension;
+
+ private Mode mode;
+
+ private SourceViewer previewViewer;
+
+ boolean readOnly;
+
+ private AbstractRenderingEngine renderingEngine;
+
+ private final TaskRepository repository;
+
+ private boolean spellCheckingEnabled;
+
+ private final int style;
+
+ private FormToolkit toolkit;
+
+ private final IAction viewSourceAction;
+
+ private String text;
+
+ public RichTextEditor(TaskRepository repository, int style) {
+ this(repository, style, null, null);
+ }
+
+ public RichTextEditor(TaskRepository repository, int style, IContextService contextService,
+ AbstractTaskEditorExtension extension) {
+ this.repository = repository;
+ this.style = style;
+ this.contextService = contextService;
+ this.extension = extension;
+ this.text = ""; //$NON-NLS-1$
+ this.document = new Document();
+ this.viewSourceAction = new ViewSourceAction();
+ setMode(Mode.DEFAULT);
+ }
+
+ private SourceViewer configure(final SourceViewer viewer, Document document, boolean readOnly) {
+ // do this before setting the document to not require invalidating the presentation
+ installHyperlinkPresenter(viewer);
+
+ 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);
+ }
+ });
+ }
+ } else {
+ configureAsEditor(viewer, document);
+ installListeners(viewer);
+ viewer.getControl().setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
+ }
+
+ // enable cut/copy/paste
+ CommonTextSupport.setTextViewer(viewer.getTextWidget(), viewer);
+ viewer.setEditable(!readOnly);
+ viewer.getTextWidget().setFont(getFont());
+ if (toolkit != null) {
+ toolkit.adapt(viewer.getControl(), false, false);
+ }
+
+ return viewer;
+ }
+
+ /** 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());
+ Iterator> e = new MarkerAnnotationPreferences().getAnnotationPreferences().iterator();
+ while (e.hasNext()) {
+ support.setAnnotationPreference((AnnotationPreference) e.next());
+ }
+ support.install(EditorsUI.getPreferenceStore());
+ viewer.getTextWidget().addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ support.uninstall();
+ }
+ });
+ //viewer.getTextWidget().setIndent(2);
+ viewer.setDocument(document, annotationModel);
+ }
+
+ 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 || renderingEngine != 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 (extension != null) {
+ if (isReadOnly()) {
+ editorViewer = extension.createViewer(repository, editorComposite, style);
+ } else {
+ editorViewer = extension.createEditor(repository, 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, document, isReadOnly());
+ show(editorViewer);
+ } else {
+ defaultViewer = createDefaultEditor(editorComposite, style);
+ configure(defaultViewer, document, isReadOnly());
+ show(defaultViewer);
+ }
+
+ if (!isReadOnly() && (style & TasksUiInternal.SWT_NO_SCROLL) == 0) {
+ editorComposite.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
+ }
+
+ viewSourceAction.setEnabled(true);
+ } else {
+ defaultViewer = createDefaultEditor(parent, style);
+ configure(defaultViewer, document, isReadOnly());
+ setControl(defaultViewer.getControl());
+
+ viewSourceAction.setEnabled(false);
+ }
+ }
+
+ private SourceViewer createDefaultEditor(Composite parent, int styles) {
+ SourceViewer defaultEditor = new SourceViewer(parent, null, styles | SWT.WRAP);
+
+ RepositoryTextViewerConfiguration viewerConfig = new RepositoryTextViewerConfiguration(repository,
+ isSpellCheckingEnabled() && !isReadOnly());
+ viewerConfig.setMode(getMode());
+ defaultEditor.configure(viewerConfig);
+
+ return defaultEditor;
+ }
+
+ private BrowserPreviewViewer getBrowserViewer() {
+ if (editorComposite == null || renderingEngine == null) {
+ return null;
+ }
+
+ if (browserViewer == null) {
+ browserViewer = new BrowserPreviewViewer(getRepository(), renderingEngine);
+ browserViewer.createControl(editorComposite, toolkit);
+ }
+ return browserViewer;
+ }
+
+ public Control getControl() {
+ return control;
+ }
+
+ public SourceViewer getDefaultViewer() {
+ if (defaultViewer == null) {
+ defaultViewer = createDefaultEditor(editorComposite, style);
+ configure(defaultViewer, document, 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;
+ }
+
+ public SourceViewer getEditorViewer() {
+ return editorViewer;
+ }
+
+ private Font getFont() {
+ IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
+ Font font = themeManager.getCurrentTheme().getFontRegistry().get(CommonThemes.FONT_EDITOR_COMMENT);
+ return font;
+ }
+
+ public Mode getMode() {
+ return mode;
+ }
+
+ private SourceViewer getPreviewViewer() {
+ if (extension == null) {
+ return null;
+ }
+
+ // construct as needed
+ if (previewViewer == null) {
+ // previewer should always have a vertical scroll bar if it's editable
+ int previewViewerStyle = style;
+ if (getEditorViewer() != null) {
+ previewViewerStyle |= SWT.V_SCROLL;
+ }
+ previewViewer = extension.createViewer(repository, editorComposite, previewViewerStyle);
+ configure(previewViewer, new Document(editorViewer.getDocument().get()), true);
+ // adapt maximize action
+ previewViewer.getControl().setData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION,
+ editorViewer.getControl().getData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION));
+ } else {
+ // update content
+ previewViewer.setDocument(new Document(editorViewer.getDocument().get()));
+ }
+ return previewViewer;
+ }
+
+ public AbstractRenderingEngine getRenderingEngine() {
+ return renderingEngine;
+ }
+
+ public TaskRepository getRepository() {
+ return repository;
+ }
+
+ public String getText() {
+ return this.text;
+ }
+
+ public SourceViewer getViewer() {
+ 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 IAction getViewSourceAction() {
+ return viewSourceAction;
+ }
+
+ public boolean hasBrowser() {
+ return renderingEngine != null;
+ }
+
+ public boolean hasPreview() {
+ return extension != null && !isReadOnly();
+ }
+
+ private RepositoryTextViewerConfiguration installHyperlinkPresenter(SourceViewer viewer) {
+ RepositoryTextViewerConfiguration configuration = new RepositoryTextViewerConfiguration(repository, false);
+ configuration.setMode(getMode());
+
+ // do not configure viewer, this has already been done in extension
+
+ AbstractHyperlinkTextPresentationManager manager;
+ if (getMode() == Mode.DEFAULT) {
+ manager = new HighlightingHyperlinkTextPresentationManager();
+ manager.setHyperlinkDetectors(configuration.getDefaultHyperlinkDetectors(viewer, null));
+ manager.install(viewer);
+
+ manager = new TaskHyperlinkTextPresentationManager();
+ manager.setHyperlinkDetectors(configuration.getDefaultHyperlinkDetectors(viewer, Mode.TASK));
+ manager.install(viewer);
+ } else if (getMode() == Mode.TASK_RELATION) {
+ manager = new TaskHyperlinkTextPresentationManager();
+ manager.setHyperlinkDetectors(configuration.getDefaultHyperlinkDetectors(viewer, Mode.TASK_RELATION));
+ manager.install(viewer);
+ }
+
+ return configuration;
+ }
+
+ 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 (!RichTextEditor.this.text.equals(value)) {
+ RichTextEditor.this.text = value;
+ valueChanged(value);
+ CommonFormUtil.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;
+ }
+ }
+ });
+ }
+ }
+
+ 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 boolean isReadOnly() {
+ return readOnly;
+ }
+
+ 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());
+ }
+ }
+
+ private void setControl(Control control) {
+ this.control = control;
+ }
+
+ public void setMode(Mode mode) {
+ Assert.isNotNull(mode);
+ this.mode = mode;
+ }
+
+ public void setReadOnly(boolean readOnly) {
+ this.readOnly = readOnly;
+ }
+
+ public void setRenderingEngine(AbstractRenderingEngine renderingEngine) {
+ this.renderingEngine = renderingEngine;
+ }
+
+ public void setSpellCheckingEnabled(boolean spellCheckingEnabled) {
+ this.spellCheckingEnabled = spellCheckingEnabled;
+ }
+
+ public void setText(String value) {
+ this.text = value;
+ document.set(value);
+ }
+
+ /**
+ * Brings control
to top.
+ */
+ private void show(Control control) {
+ // no extension is available
+ if (editorComposite == null) {
+ return;
+ }
+
+ editorLayout.topControl = control;
+ if (editorComposite.getParent().getLayout() instanceof FillWidthLayout) {
+ ((FillWidthLayout) editorComposite.getParent().getLayout()).flush();
+ }
+ editorComposite.layout();
+ control.setFocus();
+ }
+
+ /**
+ * Brings viewer
to top.
+ */
+ private void show(SourceViewer viewer) {
+ show(viewer.getControl());
+ }
+
+ public void showBrowser() {
+ BrowserPreviewViewer viewer = getBrowserViewer();
+ viewer.update(getText());
+ if (viewer != null) {
+ show(viewer.getControl());
+ }
+ }
+
+ public void showDefault() {
+ show(getDefaultViewer());
+ }
+
+ public void showEditor() {
+ if (getEditorViewer() != null) {
+ show(getEditorViewer());
+ } else {
+ show(getDefaultViewer());
+ }
+ }
+
+ public void showPreview() {
+ if (!isReadOnly()) {
+ show(getPreviewViewer());
+ }
+ }
+
+ private void unsetContext() {
+ if (contextService == null) {
+ return;
+ }
+ if (contextActivation != null) {
+ contextService.deactivateContext(contextActivation);
+ contextActivation = null;
+ }
+ }
+
+ protected void valueChanged(String value) {
+ }
+
+}