Removed
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2004, 2008 Jingwen Ou and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
8 |
* Contributors: |
9 |
* Jingwen Ou - initial API and implementation |
10 |
* Tasktop Technologies - improvements |
11 |
*******************************************************************************/ |
12 |
|
13 |
package org.eclipse.mylyn.internal.sandbox.ui.editors; |
14 |
|
15 |
import java.util.Iterator; |
16 |
|
17 |
import org.eclipse.jface.action.Action; |
18 |
import org.eclipse.jface.action.IAction; |
19 |
import org.eclipse.jface.resource.JFaceResources; |
20 |
import org.eclipse.jface.text.Document; |
21 |
import org.eclipse.jface.text.ITextListener; |
22 |
import org.eclipse.jface.text.TextEvent; |
23 |
import org.eclipse.jface.text.source.AnnotationModel; |
24 |
import org.eclipse.jface.text.source.IAnnotationAccess; |
25 |
import org.eclipse.jface.text.source.SourceViewer; |
26 |
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonThemes; |
27 |
import org.eclipse.mylyn.internal.sandbox.ui.commands.ViewSourceHandler; |
28 |
import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil; |
29 |
import org.eclipse.mylyn.internal.tasks.ui.editors.RepositoryTextViewer; |
30 |
import org.eclipse.mylyn.internal.tasks.ui.editors.RepositoryTextViewerConfiguration; |
31 |
import org.eclipse.mylyn.internal.tasks.ui.editors.RichTextAttributeEditor; |
32 |
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskHyperlinkDetector; |
33 |
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskHyperlinkTextPresentationManager; |
34 |
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; |
35 |
import org.eclipse.mylyn.tasks.core.TaskRepository; |
36 |
import org.eclipse.mylyn.tasks.core.data.TaskAttribute; |
37 |
import org.eclipse.mylyn.tasks.core.data.TaskDataModel; |
38 |
import org.eclipse.swt.SWT; |
39 |
import org.eclipse.swt.custom.StackLayout; |
40 |
import org.eclipse.swt.events.DisposeEvent; |
41 |
import org.eclipse.swt.events.DisposeListener; |
42 |
import org.eclipse.swt.events.FocusAdapter; |
43 |
import org.eclipse.swt.events.FocusEvent; |
44 |
import org.eclipse.swt.events.FocusListener; |
45 |
import org.eclipse.swt.graphics.Font; |
46 |
import org.eclipse.swt.graphics.Point; |
47 |
import org.eclipse.swt.widgets.Composite; |
48 |
import org.eclipse.swt.widgets.Control; |
49 |
import org.eclipse.swt.widgets.Menu; |
50 |
import org.eclipse.ui.PlatformUI; |
51 |
import org.eclipse.ui.contexts.IContextActivation; |
52 |
import org.eclipse.ui.contexts.IContextService; |
53 |
import org.eclipse.ui.editors.text.EditorsUI; |
54 |
import org.eclipse.ui.forms.widgets.FormToolkit; |
55 |
import org.eclipse.ui.texteditor.AnnotationPreference; |
56 |
import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; |
57 |
import org.eclipse.ui.texteditor.MarkerAnnotationPreferences; |
58 |
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; |
59 |
import org.eclipse.ui.themes.IThemeManager; |
60 |
|
61 |
/** |
62 |
* A text attribute that can switch between a source editor and a preview using StackLayout. |
63 |
* |
64 |
* @author Jingwen Ou |
65 |
* @author Steffen Pingel |
66 |
*/ |
67 |
public class ExtensibleRichTextAttributeEditor extends RichTextAttributeEditor { |
68 |
|
69 |
private IContextActivation contextActivation; |
70 |
|
71 |
private final IContextService contextService; |
72 |
|
73 |
private SourceViewer defaultViewer; |
74 |
|
75 |
private Composite editorComposite; |
76 |
|
77 |
private StackLayout editorLayout; |
78 |
|
79 |
private final AbstractTaskEditorExtension extension; |
80 |
|
81 |
private SourceViewer editorViewer; |
82 |
|
83 |
private SourceViewer previewViewer; |
84 |
|
85 |
private int styles; |
86 |
|
87 |
private final TaskRepository taskRepository; |
88 |
|
89 |
private FormToolkit toolkit; |
90 |
|
91 |
public class ViewSourceAction extends Action { |
92 |
|
93 |
public ViewSourceAction() { |
94 |
super("Viewer Source", SWT.TOGGLE); |
95 |
setChecked(false); |
96 |
} |
97 |
|
98 |
@Override |
99 |
public void run() { |
100 |
if (isChecked()) { |
101 |
showDefault(); |
102 |
} else { |
103 |
showEditor(); |
104 |
} |
105 |
} |
106 |
|
107 |
} |
108 |
|
109 |
private final IAction viewSourceAction = new ViewSourceAction(); |
110 |
|
111 |
public ExtensibleRichTextAttributeEditor(IContextService contextService, TaskDataModel manager, |
112 |
TaskRepository taskRepository, AbstractTaskEditorExtension extension, TaskAttribute taskAttribute, |
113 |
int styles) { |
114 |
super(manager, taskRepository, taskAttribute, styles); |
115 |
this.contextService = contextService; |
116 |
this.taskRepository = taskRepository; |
117 |
this.extension = extension; |
118 |
this.styles = styles; |
119 |
} |
120 |
|
121 |
/** Configures annontation model for spell checking. */ |
122 |
private void configureAsTextEditor(SourceViewer viewer, Document document) { |
123 |
AnnotationModel annotationModel = new AnnotationModel(); |
124 |
viewer.showAnnotations(false); |
125 |
viewer.showAnnotationsOverview(false); |
126 |
IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess(); |
127 |
final SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(viewer, null, annotationAccess, |
128 |
EditorsUI.getSharedTextColors()); |
129 |
Iterator<?> e = new MarkerAnnotationPreferences().getAnnotationPreferences().iterator(); |
130 |
while (e.hasNext()) { |
131 |
support.setAnnotationPreference((AnnotationPreference) e.next()); |
132 |
} |
133 |
support.install(EditorsUI.getPreferenceStore()); |
134 |
viewer.getTextWidget().addDisposeListener(new DisposeListener() { |
135 |
public void widgetDisposed(DisposeEvent e) { |
136 |
support.uninstall(); |
137 |
} |
138 |
}); |
139 |
viewer.getTextWidget().setIndent(2); |
140 |
viewer.setDocument(document, annotationModel); |
141 |
} |
142 |
|
143 |
private SourceViewer configureEditor(final SourceViewer viewer, boolean readOnly) { |
144 |
Document document = new Document(getValue()); |
145 |
if (readOnly) { |
146 |
viewer.setDocument(document); |
147 |
// setting view source action |
148 |
viewer.getControl().setData(ViewSourceHandler.VIEW_SOURCE_ACTION, viewSourceAction); |
149 |
viewer.getControl().addFocusListener(new FocusAdapter() { |
150 |
@Override |
151 |
public void focusGained(FocusEvent e) { |
152 |
ViewSourceHandler.setChecked(getViewer() == defaultViewer); |
153 |
} |
154 |
}); |
155 |
} else { |
156 |
configureAsTextEditor(viewer, document); |
157 |
viewer.addTextListener(new ITextListener() { |
158 |
public void textChanged(TextEvent event) { |
159 |
// filter out events caused by text presentation changes, e.g. annotation drawing |
160 |
String value = viewer.getTextWidget().getText(); |
161 |
if (!getValue().equals(value)) { |
162 |
setValue(value); |
163 |
EditorUtil.ensureVisible(viewer.getTextWidget()); |
164 |
} |
165 |
} |
166 |
}); |
167 |
|
168 |
viewer.getControl().setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER); |
169 |
|
170 |
// drop & drag support, under review |
171 |
TaskEditorDropTarget.addDropTargetSupport(viewer); |
172 |
} |
173 |
|
174 |
// enable cut/copy/paste |
175 |
EditorUtil.setTextViewer(viewer.getTextWidget(), viewer); |
176 |
viewer.setEditable(!readOnly); |
177 |
viewer.getTextWidget().setFont(getFont()); |
178 |
toolkit.adapt(viewer.getControl(), false, false); |
179 |
|
180 |
TaskHyperlinkTextPresentationManager hyperlinkTextPresentationManager = new TaskHyperlinkTextPresentationManager(); |
181 |
hyperlinkTextPresentationManager.setHyperlinkDetector(new TaskHyperlinkDetector()); |
182 |
hyperlinkTextPresentationManager.install(viewer); |
183 |
|
184 |
return viewer; |
185 |
} |
186 |
|
187 |
@Override |
188 |
public void createControl(Composite parent, FormToolkit toolkit) { |
189 |
this.toolkit = toolkit; |
190 |
|
191 |
editorComposite = new Composite(parent, SWT.NULL); |
192 |
editorLayout = new StackLayout() { |
193 |
@Override |
194 |
protected Point computeSize(Composite composite, int hint, int hint2, boolean flushCache) { |
195 |
return topControl.computeSize(hint, hint2, flushCache); |
196 |
} |
197 |
}; |
198 |
editorComposite.setLayout(editorLayout); |
199 |
setControl(editorComposite); |
200 |
|
201 |
if (!isReadOnly() && (styles & TasksUiInternal.SWT_NO_SCROLL) == 0) { |
202 |
styles |= SWT.V_SCROLL; |
203 |
} |
204 |
|
205 |
if (isReadOnly()) { |
206 |
editorViewer = extension.createViewer(taskRepository, editorComposite, styles); |
207 |
} else { |
208 |
editorViewer = extension.createEditor(taskRepository, editorComposite, styles); |
209 |
editorViewer.getTextWidget().addFocusListener(new FocusListener() { |
210 |
public void focusGained(FocusEvent e) { |
211 |
setContext(); |
212 |
} |
213 |
|
214 |
public void focusLost(FocusEvent e) { |
215 |
unsetContext(); |
216 |
} |
217 |
}); |
218 |
editorViewer.getTextWidget().addDisposeListener(new DisposeListener() { |
219 |
public void widgetDisposed(DisposeEvent e) { |
220 |
unsetContext(); |
221 |
} |
222 |
}); |
223 |
} |
224 |
configureEditor(editorViewer, isReadOnly()); |
225 |
|
226 |
show(editorViewer); |
227 |
} |
228 |
|
229 |
private SourceViewer createDefaultEditor(Composite parent, int styles) { |
230 |
SourceViewer defaultEditor = new RepositoryTextViewer(taskRepository, parent, styles | SWT.WRAP); |
231 |
|
232 |
RepositoryTextViewerConfiguration viewerConfig = new RepositoryTextViewerConfiguration(taskRepository, |
233 |
isSpellCheckingEnabled()); |
234 |
viewerConfig.setMode(getMode()); |
235 |
defaultEditor.configure(viewerConfig); |
236 |
|
237 |
return defaultEditor; |
238 |
} |
239 |
|
240 |
private SourceViewer getDefaultViewer() { |
241 |
if (defaultViewer == null) { |
242 |
defaultViewer = createDefaultEditor(editorComposite, styles); |
243 |
configureEditor(defaultViewer, isReadOnly()); |
244 |
|
245 |
// fixed font size |
246 |
defaultViewer.getTextWidget().setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT)); |
247 |
// adapt maximize action |
248 |
defaultViewer.getControl().setData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION, |
249 |
editorViewer.getControl().getData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION)); |
250 |
// adapt menu to the new viewer |
251 |
installMenu(defaultViewer.getControl(), editorViewer.getControl().getMenu()); |
252 |
} |
253 |
return defaultViewer; |
254 |
} |
255 |
|
256 |
private void installMenu(final Control control, Menu menu) { |
257 |
if (menu != null) { |
258 |
control.setMenu(menu); |
259 |
control.addDisposeListener(new DisposeListener() { |
260 |
public void widgetDisposed(DisposeEvent e) { |
261 |
control.setMenu(null); |
262 |
} |
263 |
}); |
264 |
} |
265 |
} |
266 |
|
267 |
private Font getFont() { |
268 |
IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); |
269 |
Font font = themeManager.getCurrentTheme().getFontRegistry().get(CommonThemes.FONT_EDITOR_COMMENT); |
270 |
return font; |
271 |
} |
272 |
|
273 |
private SourceViewer getPreviewViewer() { |
274 |
// construct as needed |
275 |
if (previewViewer == null) { |
276 |
previewViewer = extension.createViewer(taskRepository, editorComposite, styles); |
277 |
configureEditor(previewViewer, true); |
278 |
// adapt maximize action |
279 |
previewViewer.getControl().setData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION, |
280 |
editorViewer.getControl().getData(EditorUtil.KEY_TOGGLE_TO_MAXIMIZE_ACTION)); |
281 |
} |
282 |
Document document = new Document(editorViewer.getDocument().get()); |
283 |
previewViewer.setDocument(document); |
284 |
return previewViewer; |
285 |
} |
286 |
|
287 |
public SourceViewer getEditorViewer() { |
288 |
return editorViewer; |
289 |
} |
290 |
|
291 |
@Override |
292 |
public SourceViewer getViewer() { |
293 |
if (defaultViewer != null && editorLayout.topControl == defaultViewer.getControl()) { |
294 |
return defaultViewer; |
295 |
} else if (previewViewer != null && editorLayout.topControl == previewViewer.getControl()) { |
296 |
return previewViewer; |
297 |
} else { |
298 |
return editorViewer; |
299 |
} |
300 |
} |
301 |
|
302 |
private void setContext() { |
303 |
if (contextActivation != null) { |
304 |
contextService.deactivateContext(contextActivation); |
305 |
contextActivation = null; |
306 |
} |
307 |
if (contextService != null && extension.getEditorContextId() != null) { |
308 |
contextActivation = contextService.activateContext(extension.getEditorContextId()); |
309 |
} |
310 |
} |
311 |
|
312 |
/** |
313 |
* Brings <code>viewer</code> to top. |
314 |
*/ |
315 |
private void show(SourceViewer viewer) { |
316 |
editorLayout.topControl = viewer.getControl(); |
317 |
editorComposite.layout(); |
318 |
viewer.getControl().setFocus(); |
319 |
} |
320 |
|
321 |
public void showDefault() { |
322 |
show(getDefaultViewer()); |
323 |
} |
324 |
|
325 |
public void showPreview() { |
326 |
if (!isReadOnly()) { |
327 |
show(getPreviewViewer()); |
328 |
} |
329 |
} |
330 |
|
331 |
public void showEditor() { |
332 |
show(getEditorViewer()); |
333 |
} |
334 |
|
335 |
private void unsetContext() { |
336 |
if (contextActivation != null) { |
337 |
contextService.deactivateContext(contextActivation); |
338 |
contextActivation = null; |
339 |
} |
340 |
} |
341 |
|
342 |
} |