Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2007 Dakshinamurthy Karra 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 |
* Dakshinamurthy Karra (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 |
10 |
*******************************************************************************/ |
11 |
|
12 |
package org.eclipse.ui.texteditor.templates.view; |
13 |
|
14 |
import java.io.IOException; |
15 |
import java.util.ArrayList; |
16 |
import java.util.Arrays; |
17 |
import java.util.Iterator; |
18 |
import java.util.List; |
19 |
|
20 |
import org.eclipse.jface.action.Action; |
21 |
import org.eclipse.jface.action.IAction; |
22 |
import org.eclipse.jface.action.IMenuListener; |
23 |
import org.eclipse.jface.action.IMenuManager; |
24 |
import org.eclipse.jface.action.IToolBarManager; |
25 |
import org.eclipse.jface.action.MenuManager; |
26 |
import org.eclipse.jface.action.Separator; |
27 |
import org.eclipse.jface.dialogs.MessageDialog; |
28 |
import org.eclipse.jface.layout.TreeColumnLayout; |
29 |
import org.eclipse.jface.preference.IPreferenceStore; |
30 |
import org.eclipse.jface.text.BadLocationException; |
31 |
import org.eclipse.jface.text.Document; |
32 |
import org.eclipse.jface.text.IDocument; |
33 |
import org.eclipse.jface.text.IRegion; |
34 |
import org.eclipse.jface.text.ITextViewerExtension5; |
35 |
import org.eclipse.jface.text.source.ISourceViewer; |
36 |
import org.eclipse.jface.text.source.SourceViewer; |
37 |
import org.eclipse.jface.text.source.SourceViewerConfiguration; |
38 |
import org.eclipse.jface.text.templates.ContextTypeRegistry; |
39 |
import org.eclipse.jface.text.templates.Template; |
40 |
import org.eclipse.jface.text.templates.TemplateContextType; |
41 |
import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; |
42 |
import org.eclipse.jface.text.templates.persistence.TemplateStore; |
43 |
import org.eclipse.jface.util.IPropertyChangeListener; |
44 |
import org.eclipse.jface.util.PropertyChangeEvent; |
45 |
import org.eclipse.jface.viewers.AbstractTreeViewer; |
46 |
import org.eclipse.jface.viewers.ColumnPixelData; |
47 |
import org.eclipse.jface.viewers.DoubleClickEvent; |
48 |
import org.eclipse.jface.viewers.IDoubleClickListener; |
49 |
import org.eclipse.jface.viewers.IPostSelectionProvider; |
50 |
import org.eclipse.jface.viewers.ISelectionChangedListener; |
51 |
import org.eclipse.jface.viewers.ISelectionProvider; |
52 |
import org.eclipse.jface.viewers.IStructuredSelection; |
53 |
import org.eclipse.jface.viewers.ITableLabelProvider; |
54 |
import org.eclipse.jface.viewers.ITreeContentProvider; |
55 |
import org.eclipse.jface.viewers.LabelProvider; |
56 |
import org.eclipse.jface.viewers.SelectionChangedEvent; |
57 |
import org.eclipse.jface.viewers.StructuredSelection; |
58 |
import org.eclipse.jface.viewers.TreeViewer; |
59 |
import org.eclipse.jface.viewers.Viewer; |
60 |
import org.eclipse.jface.viewers.ViewerComparator; |
61 |
import org.eclipse.jface.window.Window; |
62 |
import org.eclipse.swt.SWT; |
63 |
import org.eclipse.swt.custom.CLabel; |
64 |
import org.eclipse.swt.custom.SashForm; |
65 |
import org.eclipse.swt.custom.StyledText; |
66 |
import org.eclipse.swt.custom.ViewForm; |
67 |
import org.eclipse.swt.dnd.Clipboard; |
68 |
import org.eclipse.swt.dnd.DND; |
69 |
import org.eclipse.swt.dnd.DragSourceAdapter; |
70 |
import org.eclipse.swt.dnd.DragSourceEvent; |
71 |
import org.eclipse.swt.dnd.DropTargetAdapter; |
72 |
import org.eclipse.swt.dnd.DropTargetEvent; |
73 |
import org.eclipse.swt.dnd.TextTransfer; |
74 |
import org.eclipse.swt.dnd.Transfer; |
75 |
import org.eclipse.swt.events.ControlEvent; |
76 |
import org.eclipse.swt.events.ControlListener; |
77 |
import org.eclipse.swt.graphics.Image; |
78 |
import org.eclipse.swt.graphics.Point; |
79 |
import org.eclipse.swt.layout.GridData; |
80 |
import org.eclipse.swt.widgets.Composite; |
81 |
import org.eclipse.swt.widgets.Control; |
82 |
import org.eclipse.swt.widgets.Event; |
83 |
import org.eclipse.swt.widgets.Menu; |
84 |
import org.eclipse.swt.widgets.Shell; |
85 |
import org.eclipse.swt.widgets.Tree; |
86 |
import org.eclipse.swt.widgets.TreeColumn; |
87 |
import org.eclipse.swt.widgets.TreeItem; |
88 |
import org.eclipse.ui.IActionBars; |
89 |
import org.eclipse.ui.IWorkbenchActionConstants; |
90 |
import org.eclipse.ui.actions.ActionFactory; |
91 |
import org.eclipse.ui.dialogs.PreferencesUtil; |
92 |
import org.eclipse.ui.dnd.IDragAndDropService; |
93 |
import org.eclipse.ui.internal.texteditor.NLSUtility; |
94 |
import org.eclipse.ui.internal.texteditor.PixelConverter; |
95 |
import org.eclipse.ui.internal.texteditor.TextEditorPlugin; |
96 |
import org.eclipse.ui.internal.texteditor.templates.view.TemplateTransfer; |
97 |
import org.eclipse.ui.internal.texteditor.templates.view.TemplatesPageImages; |
98 |
import org.eclipse.ui.internal.texteditor.templates.view.TemplatesPageMessages; |
99 |
import org.eclipse.ui.part.Page; |
100 |
import org.eclipse.ui.texteditor.AbstractTextEditor; |
101 |
import org.eclipse.ui.texteditor.ITextEditorActionConstants; |
102 |
import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; |
103 |
import org.eclipse.ui.texteditor.templates.TemplatePreferencePage.EditTemplateDialog; |
104 |
|
105 |
import com.ibm.icu.text.Collator; |
106 |
|
107 |
/** |
108 |
* An abstract base class for template pages. |
109 |
* <p> |
110 |
* Clients who are defining an editor may elect to provide a corresponding |
111 |
* templates page. This templates page will be presented to the user via the |
112 |
* Templates View (the user decides whether their workbench window contains this |
113 |
* view) whenever that editor is active. This class should be subclassed by |
114 |
* clients. |
115 |
* </p> |
116 |
* <p> |
117 |
* Internally, a TemplatesPage uses the template store to display different |
118 |
* categories. A link to editor mode on the templates page allows to filtering |
119 |
* of the categories to only that are supported in this context. |
120 |
* </p> |
121 |
* |
122 |
* @since 3.4 |
123 |
*/ |
124 |
public abstract class TemplatesPage extends Page implements ITemplatesPage { |
125 |
|
126 |
/** |
127 |
* Sashform size |
128 |
*/ |
129 |
private static final String SASH_SIZE_PREF_ID = TextEditorPlugin.PLUGIN_ID |
130 |
+ ".templates.templatesPage.sashSize"; //$NON-NLS-1$ |
131 |
/** |
132 |
* Tree columns widths |
133 |
*/ |
134 |
private static final String COLUMN_NAME_WIDTH_PREF_ID = TextEditorPlugin.PLUGIN_ID |
135 |
+ ".templates.templatesPage.nameWidth"; //$NON-NLS-1$ |
136 |
private static final String COLUMN_DESCRIPTION_WIDTH_PREF_ID = TextEditorPlugin.PLUGIN_ID |
137 |
+ ".templates.templatesPage.descriptionWidth"; //$NON-NLS-1$ |
138 |
/** |
139 |
* Link to editor action setting |
140 |
*/ |
141 |
private static final String LINK_ACTION_PREF_ID = TextEditorPlugin.PLUGIN_ID |
142 |
+ ".templates.templatesPage.linkAction"; //$NON-NLS-1$ |
143 |
|
144 |
/** |
145 |
* Context expand/collapse setting prefix |
146 |
*/ |
147 |
private static final String CONTEXT_COLLAPSE_PREF_ID = TextEditorPlugin.PLUGIN_ID |
148 |
+ "templates.templatesPage.context.expand."; //$NON-NLS-1$ |
149 |
|
150 |
/** |
151 |
* The ID for the popup menu for this templates page |
152 |
*/ |
153 |
private static final String POPUP_MENU_ID = "org.eclipse.ui.texteditor.templates.PopupMenu"; //$NON-NLS-1$ |
154 |
|
155 |
/** |
156 |
* Default image for a template |
157 |
*/ |
158 |
private static final Image DEFAULT_TEMPLATE_IMAGE = TemplatesPageImages |
159 |
.getImage(TemplatesPageImages.IMG_OBJ_TEMPLATE); |
160 |
/** |
161 |
* Image for the context |
162 |
*/ |
163 |
private static final Image CONTEXT_IMAGE = TemplatesPageImages |
164 |
.getImage(TemplatesPageImages.IMG_OBJ_CONTEXT); |
165 |
|
166 |
/** |
167 |
* A post selection changed listener for the editor. Depending on the caret |
168 |
* position updates the templates |
169 |
*/ |
170 |
private final class SelectionChangedListener implements ISelectionChangedListener { |
171 |
/* |
172 |
* (non-Javadoc) |
173 |
* |
174 |
* @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) |
175 |
*/ |
176 |
public void selectionChanged(SelectionChangedEvent event) { |
177 |
String[] contextTypes = getContextTypes(); |
178 |
if (needUpdate(contextTypes)) { |
179 |
fCurrentContextTypes = contextTypes; |
180 |
updateContextTypes(fCurrentContextTypes); |
181 |
return; |
182 |
} |
183 |
} |
184 |
|
185 |
/** |
186 |
* Check whether an update of the TemplatesPage is needed |
187 |
* |
188 |
* @param contextTypes |
189 |
* @return true if update is needed |
190 |
*/ |
191 |
private boolean needUpdate(String[] contextTypes) { |
192 |
return fCurrentContextTypes == null |
193 |
|| fCurrentContextTypes.length != contextTypes.length |
194 |
|| contextTypeChanged(contextTypes); |
195 |
} |
196 |
|
197 |
/** |
198 |
* Check whether there is any change in the context types needed |
199 |
* |
200 |
* @param contextTypes |
201 |
* @return true if any of the context types changed |
202 |
*/ |
203 |
private boolean contextTypeChanged(String[] contextTypes) { |
204 |
for (int i = 0; i < contextTypes.length; i++) { |
205 |
if (!contextTypes[i].equals(fCurrentContextTypes[i])) |
206 |
return false; |
207 |
} |
208 |
return true; |
209 |
} |
210 |
} |
211 |
|
212 |
/** |
213 |
* Drop support for the editor linked to this page. When a user drops a |
214 |
* template into the active editor, the template is applied at the drop |
215 |
* position. |
216 |
*/ |
217 |
private final class EditorDropTarget extends DropTargetAdapter { |
218 |
/* |
219 |
* (non-Javadoc) |
220 |
* |
221 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) |
222 |
*/ |
223 |
public void dragEnter(DropTargetEvent event) { |
224 |
event.detail = DND.DROP_COPY; |
225 |
} |
226 |
|
227 |
/* |
228 |
* (non-Javadoc) |
229 |
* |
230 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) |
231 |
*/ |
232 |
public void dragOperationChanged(DropTargetEvent event) { |
233 |
event.detail = DND.DROP_COPY; |
234 |
} |
235 |
|
236 |
/* |
237 |
* (non-Javadoc) |
238 |
* |
239 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) |
240 |
*/ |
241 |
public void dragOver(DropTargetEvent event) { |
242 |
event.feedback |= DND.FEEDBACK_SCROLL; |
243 |
event.detail = DND.DROP_NONE; |
244 |
TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); |
245 |
if (fEditor.isEditorInputModifiable() |
246 |
&& selectedTemplates.length == 1 |
247 |
&& isValidTemplateForPosition(selectedTemplates[0].getTemplate(), new Point( |
248 |
event.x, event.y))) |
249 |
event.detail = DND.DROP_COPY; |
250 |
} |
251 |
|
252 |
/* |
253 |
* (non-Javadoc) |
254 |
* |
255 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent) |
256 |
*/ |
257 |
public void drop(DropTargetEvent event) { |
258 |
TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); |
259 |
insertTemplate(selectedTemplates[0].getTemplate(), new Point(event.x, event.y)); |
260 |
// The highlight of the item is removed once the drop happens - |
261 |
// restore it |
262 |
fTreeViewer.setSelection(new StructuredSelection(selectedTemplates), true); |
263 |
} |
264 |
} |
265 |
|
266 |
/** |
267 |
* Comparator for the viewer. Sorts the templates by name and then |
268 |
* description and context types by names. |
269 |
*/ |
270 |
private static final class TemplateViewerComparator extends ViewerComparator { |
271 |
/* |
272 |
* (non-Javadoc) |
273 |
* |
274 |
* @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, |
275 |
* java.lang.Object, java.lang.Object) |
276 |
*/ |
277 |
public int compare(Viewer viewer, Object object1, Object object2) { |
278 |
if ((object1 instanceof TemplatePersistenceData) |
279 |
&& (object2 instanceof TemplatePersistenceData)) { |
280 |
Template left = ((TemplatePersistenceData) object1).getTemplate(); |
281 |
Template right = ((TemplatePersistenceData) object2).getTemplate(); |
282 |
int result = Collator.getInstance().compare(left.getName(), right.getName()); |
283 |
if (result != 0) |
284 |
return result; |
285 |
return Collator.getInstance() |
286 |
.compare(left.getDescription(), right.getDescription()); |
287 |
} |
288 |
if ((object1 instanceof TemplateContextType) |
289 |
&& (object2 instanceof TemplateContextType)) { |
290 |
return Collator.getInstance().compare(((TemplateContextType) object1).getName(), |
291 |
((TemplateContextType) object1).getName()); |
292 |
} |
293 |
return super.compare(viewer, object1, object2); |
294 |
} |
295 |
|
296 |
/* |
297 |
* (non-Javadoc) |
298 |
* |
299 |
* @see org.eclipse.jface.viewers.ViewerComparator#isSorterProperty(java.lang.Object, |
300 |
* java.lang.String) |
301 |
*/ |
302 |
public boolean isSorterProperty(Object element, String property) { |
303 |
return false; |
304 |
} |
305 |
} |
306 |
|
307 |
/** |
308 |
* Label provider for templates. |
309 |
*/ |
310 |
private final class TemplateLabelProvider extends LabelProvider implements ITableLabelProvider { |
311 |
/* |
312 |
* (non-Javadoc) |
313 |
* |
314 |
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, |
315 |
* int) |
316 |
*/ |
317 |
public Image getColumnImage(Object element, int columnIndex) { |
318 |
if (columnIndex != 0) |
319 |
return null; |
320 |
if (element instanceof TemplateContextType) |
321 |
return CONTEXT_IMAGE; |
322 |
return getImageForTemplate(((TemplatePersistenceData) element).getTemplate()); |
323 |
} |
324 |
|
325 |
/* |
326 |
* (non-Javadoc) |
327 |
* |
328 |
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, |
329 |
* int) |
330 |
*/ |
331 |
public String getColumnText(Object element, int columnIndex) { |
332 |
if (element instanceof TemplatePersistenceData) |
333 |
return getTemplateColumnText((TemplatePersistenceData) element, columnIndex); |
334 |
return getContextColumnText((TemplateContextType) element, columnIndex); |
335 |
} |
336 |
|
337 |
private String getTemplateColumnText(TemplatePersistenceData data, int columnIndex) { |
338 |
switch (columnIndex) { |
339 |
case 0: |
340 |
return data.getTemplate().getName(); |
341 |
case 1: |
342 |
return data.getTemplate().getDescription(); |
343 |
default: |
344 |
return ""; //$NON-NLS-1$ |
345 |
} |
346 |
} |
347 |
|
348 |
private String getContextColumnText(TemplateContextType contextType, int columnIndex) { |
349 |
switch (columnIndex) { |
350 |
case 0: |
351 |
return contextType.getName(); |
352 |
default: |
353 |
return ""; //$NON-NLS-1$ |
354 |
} |
355 |
} |
356 |
} |
357 |
|
358 |
/** |
359 |
* Content provider for templates. Provides all the enabled templates |
360 |
* defined for this editor. |
361 |
*/ |
362 |
private final class TemplatesContentProvider implements ITreeContentProvider { |
363 |
/* |
364 |
* (non-Javadoc) |
365 |
* |
366 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) |
367 |
*/ |
368 |
public Object[] getChildren(Object parentElement) { |
369 |
if (parentElement instanceof TemplatePersistenceData) |
370 |
return new Object[0]; |
371 |
else if (parentElement instanceof TemplateContextType) { |
372 |
TemplateContextType contextType = (TemplateContextType) parentElement; |
373 |
return getTemplates(contextType.getId()); |
374 |
} |
375 |
return null; |
376 |
} |
377 |
|
378 |
private TemplatePersistenceData[] getTemplates(String contextId) { |
379 |
List templateList = new ArrayList(); |
380 |
TemplatePersistenceData[] datas = getTemplateStore().getTemplateData(false); |
381 |
for (int i = 0; i < datas.length; i++) { |
382 |
if (datas[i].isEnabled() |
383 |
&& datas[i].getTemplate().getContextTypeId().equals(contextId)) |
384 |
templateList.add(datas[i]); |
385 |
} |
386 |
return (TemplatePersistenceData[]) templateList |
387 |
.toArray(new TemplatePersistenceData[templateList.size()]); |
388 |
} |
389 |
|
390 |
/* |
391 |
* (non-Javadoc) |
392 |
* |
393 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) |
394 |
*/ |
395 |
public Object getParent(Object element) { |
396 |
if (element instanceof TemplatePersistenceData) { |
397 |
TemplatePersistenceData templateData = (TemplatePersistenceData) element; |
398 |
return getContextTypeRegistry().getContextType( |
399 |
templateData.getTemplate().getContextTypeId()); |
400 |
} |
401 |
return null; |
402 |
} |
403 |
|
404 |
/* |
405 |
* (non-Javadoc) |
406 |
* |
407 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) |
408 |
*/ |
409 |
public boolean hasChildren(Object element) { |
410 |
if (element instanceof TemplateContextType) |
411 |
return true; |
412 |
return false; |
413 |
} |
414 |
|
415 |
/* |
416 |
* (non-Javadoc) |
417 |
* |
418 |
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) |
419 |
*/ |
420 |
public Object[] getElements(Object inputElement) { |
421 |
List contextTypes = new ArrayList(); |
422 |
|
423 |
for (Iterator iterator = getContextTypeRegistry().contextTypes(); iterator.hasNext();) { |
424 |
TemplateContextType contextType = (TemplateContextType) iterator.next(); |
425 |
if (!fLinkWithEditorAction.isChecked() || isActiveContext(contextType)) |
426 |
contextTypes.add(contextType); |
427 |
} |
428 |
return contextTypes.toArray(new TemplateContextType[contextTypes.size()]); |
429 |
} |
430 |
|
431 |
private boolean isActiveContext(TemplateContextType contextType) { |
432 |
return fActiveTypes == null || fActiveTypes.contains(contextType.getId()); |
433 |
} |
434 |
|
435 |
/* |
436 |
* (non-Javadoc) |
437 |
* |
438 |
* @see org.eclipse.jface.viewers.IContentProvider#dispose() |
439 |
*/ |
440 |
public void dispose() { |
441 |
} |
442 |
|
443 |
/* |
444 |
* (non-Javadoc) |
445 |
* |
446 |
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, |
447 |
* java.lang.Object, java.lang.Object) |
448 |
*/ |
449 |
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
450 |
} |
451 |
} |
452 |
|
453 |
/* The editor */ |
454 |
private final AbstractTextEditor fEditor; |
455 |
/* The SourceViewer attached to this editor */ |
456 |
private final ISourceViewer fViewer; |
457 |
|
458 |
/* Listener to monitor changes to template store */ |
459 |
private IPropertyChangeListener fTemplateChangeListener; |
460 |
|
461 |
/* Control for this pagebook view */ |
462 |
private SashForm fControl; |
463 |
|
464 |
/* Actions */ |
465 |
private Action fInsertAction; |
466 |
private Action fAddAction; |
467 |
private Action fEditAction; |
468 |
private Action fRemoveAction; |
469 |
private Action fLinkWithEditorAction; |
470 |
private Action fCollapseAllAction; |
471 |
private Action fPreferencePageAction; |
472 |
|
473 |
/* Clipboard actions */ |
474 |
private Action fPasteAction; |
475 |
private Action fCopyAction; |
476 |
|
477 |
/* Current active context types for the editor */ |
478 |
private List fActiveTypes; |
479 |
|
480 |
/* Preference stores */ |
481 |
private IPreferenceStore fPreferenceStore; |
482 |
|
483 |
/* Controls */ |
484 |
private Tree fTemplatesTree; |
485 |
private TreeViewer fTreeViewer; |
486 |
private Menu fContextMenu; |
487 |
|
488 |
/* Current selection */ |
489 |
private TemplatePersistenceData[] fSelectedTemplates = new TemplatePersistenceData[0]; |
490 |
|
491 |
/* The pattern viewer to be used with this view */ |
492 |
private SourceViewer fPatternViewer; |
493 |
|
494 |
/* Cached results for avoiding processing while drag-over the editor */ |
495 |
private int fCachedOffset; |
496 |
private boolean fCachedResult; |
497 |
private Point fCachedPosition; |
498 |
|
499 |
/* The current context types */ |
500 |
protected String[] fCurrentContextTypes; |
501 |
|
502 |
/* The selection changed listener to monitor the editor selections */ |
503 |
private SelectionChangedListener fSelectionChangedListener; |
504 |
|
505 |
/* Paste action support for the editor */ |
506 |
private IAction fEditorOldPasteAction; |
507 |
private IAction fEditorPasteAction; |
508 |
|
509 |
/** |
510 |
* Creates a new template view page. |
511 |
* |
512 |
* @param editor |
513 |
* @param viewer |
514 |
*/ |
515 |
protected TemplatesPage(AbstractTextEditor editor, ISourceViewer viewer) { |
516 |
super(); |
517 |
fEditor = editor; |
518 |
fViewer = viewer; |
519 |
setupPreferenceStore(); |
520 |
setupEditorDropTarget(); |
521 |
setupSelectionProvider(); |
522 |
setupPasteOperation(); |
523 |
} |
524 |
|
525 |
/* |
526 |
* (non-Javadoc) |
527 |
* |
528 |
* @see org.eclipse.ui.part.Page#createControl(org.eclipse.swt.widgets.Composite) |
529 |
*/ |
530 |
public void createControl(Composite ancestor) { |
531 |
setupActions(); |
532 |
|
533 |
fControl = new SashForm(ancestor, SWT.VERTICAL); |
534 |
|
535 |
createTemplateTree(fControl); |
536 |
createPatternForm(fControl); |
537 |
|
538 |
hookContextMenu(); |
539 |
initializeDND(); |
540 |
updateButtons(); |
541 |
|
542 |
int sashSize = fPreferenceStore.getInt(SASH_SIZE_PREF_ID); |
543 |
fControl.setWeights(new int[] { sashSize, 100 - sashSize }); |
544 |
fTemplateChangeListener = new IPropertyChangeListener() { |
545 |
public void propertyChange(PropertyChangeEvent event) { |
546 |
getShell().getDisplay().asyncExec(new Runnable() { |
547 |
public void run() { |
548 |
refresh(); |
549 |
} |
550 |
}); |
551 |
} |
552 |
}; |
553 |
getTemplatePreferenceStore().addPropertyChangeListener(fTemplateChangeListener); |
554 |
} |
555 |
|
556 |
/* |
557 |
* (non-Javadoc) |
558 |
* |
559 |
* @see org.eclipse.ui.part.Page#setFocus() |
560 |
*/ |
561 |
public void setFocus() { |
562 |
} |
563 |
|
564 |
/* |
565 |
* (non-Javadoc) |
566 |
* |
567 |
* @see org.eclipse.ui.part.Page#getControl() |
568 |
*/ |
569 |
public Control getControl() { |
570 |
return fControl; |
571 |
} |
572 |
|
573 |
/* |
574 |
* (non-Javadoc) |
575 |
* |
576 |
* @see org.eclipse.ui.part.Page#dispose() |
577 |
*/ |
578 |
public void dispose() { |
579 |
ISelectionProvider selectionProvider = fViewer.getSelectionProvider(); |
580 |
if (selectionProvider instanceof IPostSelectionProvider) |
581 |
((IPostSelectionProvider) selectionProvider) |
582 |
.removePostSelectionChangedListener(fSelectionChangedListener); |
583 |
else |
584 |
selectionProvider.removeSelectionChangedListener(fSelectionChangedListener); |
585 |
fEditor.setAction(ITextEditorActionConstants.PASTE, fEditorOldPasteAction); |
586 |
if (fContextMenu != null && !fContextMenu.isDisposed()) |
587 |
fContextMenu.dispose(); |
588 |
if (fTemplateChangeListener != null) |
589 |
getTemplatePreferenceStore().removePropertyChangeListener(fTemplateChangeListener); |
590 |
super.dispose(); |
591 |
} |
592 |
|
593 |
/** |
594 |
* Get the shell |
595 |
* |
596 |
* @return the shell for this view site |
597 |
*/ |
598 |
protected Shell getShell() { |
599 |
return getSite().getShell(); |
600 |
} |
601 |
|
602 |
/** |
603 |
* Get the image to be used for the given template. Clients can override to |
604 |
* provide a different image. |
605 |
* |
606 |
* @param template |
607 |
* @return handle to the image |
608 |
*/ |
609 |
protected Image getImageForTemplate(Template template) { |
610 |
return DEFAULT_TEMPLATE_IMAGE; |
611 |
} |
612 |
|
613 |
/** |
614 |
* Creates the edit dialog. Subclasses may override this method to provide a |
615 |
* custom dialog. |
616 |
* |
617 |
* @param template |
618 |
* the template being edited |
619 |
* @param edit |
620 |
* whether the dialog should be editable |
621 |
* @param isNameModifiable |
622 |
* whether the template name may be modified |
623 |
* @return the created or modified template, or <code>null</code> if the |
624 |
* editing failed |
625 |
*/ |
626 |
protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) { |
627 |
EditTemplateDialog dialog = new EditTemplateDialog(getShell(), template, edit, |
628 |
isNameModifiable, getContextTypeRegistry()); |
629 |
if (dialog.open() == Window.OK) { |
630 |
return dialog.getTemplate(); |
631 |
} |
632 |
return null; |
633 |
} |
634 |
|
635 |
/** |
636 |
* Update the pattern viewer to show the current template. |
637 |
* |
638 |
* @param template |
639 |
*/ |
640 |
protected void updatePatternViewer(Template template) { |
641 |
if (template != null) |
642 |
fPatternViewer.getDocument().set(template.getPattern()); |
643 |
else |
644 |
fPatternViewer.getDocument().set(""); //$NON-NLS-1$ |
645 |
} |
646 |
|
647 |
/** |
648 |
* Creates, configures and returns a source viewer to present the template |
649 |
* pattern on the templates page. Clients may override to provide a custom |
650 |
* source viewer featuring e.g. syntax coloring. |
651 |
* |
652 |
* @param parent |
653 |
* the parent control |
654 |
* @return a configured source viewer |
655 |
*/ |
656 |
protected SourceViewer createPatternViewer(Composite parent) { |
657 |
SourceViewer viewer = new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL |
658 |
| SWT.H_SCROLL); |
659 |
SourceViewerConfiguration configuration = new SourceViewerConfiguration(); |
660 |
viewer.configure(configuration); |
661 |
IDocument document = new Document(); |
662 |
viewer.setDocument(document); |
663 |
viewer.setEditable(false); |
664 |
return viewer; |
665 |
} |
666 |
|
667 |
/** |
668 |
* Get the pattern viewer created by createPatternViewer() |
669 |
* |
670 |
* @return the pattern viewer |
671 |
*/ |
672 |
protected final SourceViewer getPatternViewer() { |
673 |
return fPatternViewer; |
674 |
} |
675 |
|
676 |
/** |
677 |
* Get the editor associated with this view |
678 |
* |
679 |
* @return the editor |
680 |
*/ |
681 |
protected final AbstractTextEditor getEditor() { |
682 |
return fEditor; |
683 |
} |
684 |
|
685 |
/** |
686 |
* The caret position in the editor has moved into a new context type. It is |
687 |
* the subclasses responsibility to see that this is called only when needed |
688 |
* by keeping track of editor contents (eg. partitions). |
689 |
* |
690 |
* @param ids |
691 |
*/ |
692 |
protected final void updateContextTypes(String[] ids) { |
693 |
fActiveTypes = Arrays.asList(ids); |
694 |
if (fLinkWithEditorAction != null && fLinkWithEditorAction.isChecked()) |
695 |
refresh(); |
696 |
} |
697 |
|
698 |
/** |
699 |
* Subclasses should override and facilitate inserting the template code |
700 |
* into the active editor. |
701 |
* |
702 |
* @param template |
703 |
* @param position |
704 |
*/ |
705 |
abstract protected void insertTemplate(Template template, Point position); |
706 |
|
707 |
/** |
708 |
* Get the context type registry for the associated editor. |
709 |
* |
710 |
* @return the contextTypeRegistry |
711 |
*/ |
712 |
abstract protected ContextTypeRegistry getContextTypeRegistry(); |
713 |
|
714 |
/** |
715 |
* Get the template store for the associated editor |
716 |
* |
717 |
* @return the template store |
718 |
*/ |
719 |
abstract protected TemplateStore getTemplateStore(); |
720 |
|
721 |
/** |
722 |
* Get the preference store used to create the template store returned by |
723 |
* {@link TemplatesPage#getTemplateStore()}. |
724 |
* |
725 |
* @return the preference store |
726 |
*/ |
727 |
abstract protected IPreferenceStore getTemplatePreferenceStore(); |
728 |
|
729 |
/** |
730 |
* Get the preference page ID for the templates for the given editor. |
731 |
* |
732 |
* @return id of the preference page, null if none exists |
733 |
*/ |
734 |
abstract protected String getPreferencePageId(); |
735 |
|
736 |
/** |
737 |
* Get the context types supported at the current caret position of the |
738 |
* editor |
739 |
* |
740 |
* @return the ids of the context types |
741 |
*/ |
742 |
protected abstract String[] getContextTypes(); |
743 |
|
744 |
/** |
745 |
* Check whether the given template is valid for the document at the given |
746 |
* position |
747 |
* |
748 |
* @param document |
749 |
* @param template |
750 |
* @param offset |
751 |
* @param length |
752 |
* @return true if the template is valid |
753 |
*/ |
754 |
protected abstract boolean isValidTemplate(IDocument document, Template template, int offset, |
755 |
int length); |
756 |
|
757 |
/** |
758 |
* Setup the preference store |
759 |
*/ |
760 |
private void setupPreferenceStore() { |
761 |
fPreferenceStore = TextEditorPlugin.getDefault().getPreferenceStore(); |
762 |
fPreferenceStore.setDefault(LINK_ACTION_PREF_ID, true); |
763 |
fPreferenceStore.setDefault(SASH_SIZE_PREF_ID, 80); |
764 |
} |
765 |
|
766 |
/** |
767 |
* Setup the paste operation |
768 |
* |
769 |
* We get the editors Paste operation and sets up a new operation that |
770 |
* checks for the clipboard contents for TemplateTransfer data. |
771 |
*/ |
772 |
private void setupPasteOperation() { |
773 |
fEditorOldPasteAction = fEditor.getAction(ITextEditorActionConstants.PASTE); |
774 |
fEditorPasteAction = new Action(TemplatesPageMessages.TemplatesPage_paste) { |
775 |
public void run() { |
776 |
Clipboard clipBoard = new Clipboard(getShell().getDisplay()); |
777 |
Template template = getTemplateFromClipboard(clipBoard); |
778 |
if (template != null) |
779 |
insertTemplate(template, null); |
780 |
else |
781 |
fEditorOldPasteAction.run(); |
782 |
} |
783 |
|
784 |
public void runWithEvent(Event event) { |
785 |
Clipboard clipBoard = new Clipboard(getShell().getDisplay()); |
786 |
Template template = getTemplateFromClipboard(clipBoard); |
787 |
if (template != null) |
788 |
insertTemplate(template, null); |
789 |
else |
790 |
fEditorOldPasteAction.runWithEvent(event); |
791 |
} |
792 |
|
793 |
/** |
794 |
* Convert the clipboard contents into a template |
795 |
* |
796 |
* @param clipBoard |
797 |
* @return the template or null if contents are not valid |
798 |
*/ |
799 |
private Template getTemplateFromClipboard(Clipboard clipBoard) { |
800 |
TemplatePersistenceData[] contents = (TemplatePersistenceData[]) clipBoard |
801 |
.getContents(TemplateTransfer.getInstance()); |
802 |
if (contents != null && contents.length == 1) |
803 |
return contents[0].getTemplate(); |
804 |
return null; |
805 |
} |
806 |
}; |
807 |
fEditorPasteAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE); |
808 |
fEditor.setAction(ITextEditorActionConstants.PASTE, fEditorPasteAction); |
809 |
} |
810 |
|
811 |
/** |
812 |
* Setup a selection listener to monitor the editor |
813 |
*/ |
814 |
private void setupSelectionProvider() { |
815 |
ISelectionProvider selectionProvider = fViewer.getSelectionProvider(); |
816 |
fSelectionChangedListener = new SelectionChangedListener(); |
817 |
if (selectionProvider instanceof IPostSelectionProvider) |
818 |
((IPostSelectionProvider) selectionProvider) |
819 |
.addPostSelectionChangedListener(fSelectionChangedListener); |
820 |
else |
821 |
selectionProvider.addSelectionChangedListener(fSelectionChangedListener); |
822 |
} |
823 |
|
824 |
/** |
825 |
* Setup the editor site as a drop target. |
826 |
*/ |
827 |
private void setupEditorDropTarget() { |
828 |
IDragAndDropService dndService = (IDragAndDropService) fEditor.getSite().getService( |
829 |
IDragAndDropService.class); |
830 |
EditorDropTarget editorDropTarget = new EditorDropTarget(); |
831 |
dndService.addMergedDropTarget((Control) fEditor.getAdapter(Control.class), DND.DROP_COPY, |
832 |
new Transfer[] { TemplateTransfer.getInstance() }, editorDropTarget); |
833 |
} |
834 |
|
835 |
/** |
836 |
* Setup the menu, context menu and toolbar actions. |
837 |
*/ |
838 |
private void setupActions() { |
839 |
createActions(); |
840 |
IActionBars actionBars = getSite().getActionBars(); |
841 |
|
842 |
actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), fPasteAction); |
843 |
fPasteAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE); |
844 |
fPasteAction.setText(TemplatesPageMessages.TemplatesPage_paste); |
845 |
actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction); |
846 |
fCopyAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY); |
847 |
fCopyAction.setText(TemplatesPageMessages.TemplatesPage_copy); |
848 |
fillToolbar(actionBars); |
849 |
fillMenu(actionBars); |
850 |
} |
851 |
|
852 |
/** |
853 |
* Create all the actions |
854 |
*/ |
855 |
private void createActions() { |
856 |
fInsertAction = new Action(TemplatesPageMessages.TemplatesPage_insert) { |
857 |
public void run() { |
858 |
TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); |
859 |
insertTemplate(selectedTemplates[0].getTemplate(), null); |
860 |
} |
861 |
}; |
862 |
fInsertAction.setImageDescriptor(TemplatesPageImages |
863 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_INSERT)); |
864 |
fInsertAction.setDisabledImageDescriptor(TemplatesPageImages |
865 |
.getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_INSERT)); |
866 |
fInsertAction.setToolTipText(TemplatesPageMessages.TemplatesPage_insert_tooltip); |
867 |
|
868 |
fAddAction = new Action(TemplatesPageMessages.TemplatesPage_new) { |
869 |
public void run() { |
870 |
addTemplate(); |
871 |
} |
872 |
}; |
873 |
fAddAction.setImageDescriptor(TemplatesPageImages |
874 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_NEW)); |
875 |
fAddAction.setToolTipText(TemplatesPageMessages.TemplatesPage_new_tooltip); |
876 |
|
877 |
fEditAction = new Action(TemplatesPageMessages.TemplatesPage_edit) { |
878 |
public void run() { |
879 |
editTemplate(); |
880 |
} |
881 |
}; |
882 |
fEditAction.setImageDescriptor(TemplatesPageImages |
883 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_EDIT)); |
884 |
fEditAction.setDisabledImageDescriptor(TemplatesPageImages |
885 |
.getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_EDIT)); |
886 |
fEditAction.setToolTipText(TemplatesPageMessages.TemplatesPage_edit_tooltip); |
887 |
|
888 |
fRemoveAction = new Action(TemplatesPageMessages.TemplatesPage_remove) { |
889 |
public void run() { |
890 |
removeTemplates(); |
891 |
} |
892 |
}; |
893 |
fRemoveAction.setImageDescriptor(TemplatesPageImages |
894 |
.getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_DELETE)); |
895 |
fRemoveAction.setImageDescriptor(TemplatesPageImages |
896 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_DELETE)); |
897 |
fRemoveAction.setToolTipText(TemplatesPageMessages.TemplatesPage_remove_tooltip); |
898 |
|
899 |
fLinkWithEditorAction = new Action(TemplatesPageMessages.TemplatesPage_link_to_editor, |
900 |
IAction.AS_CHECK_BOX) { |
901 |
public void run() { |
902 |
fPreferenceStore.setValue(LINK_ACTION_PREF_ID, fLinkWithEditorAction.isChecked()); |
903 |
refresh(); |
904 |
} |
905 |
}; |
906 |
fLinkWithEditorAction.setImageDescriptor(TemplatesPageImages |
907 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_LINK)); |
908 |
fLinkWithEditorAction.setChecked(fPreferenceStore.getBoolean(LINK_ACTION_PREF_ID)); |
909 |
fLinkWithEditorAction |
910 |
.setToolTipText(TemplatesPageMessages.TemplatesPage_link_to_editor_tooltip); |
911 |
fCollapseAllAction = new Action(TemplatesPageMessages.TemplatesPage_collapse_all) { |
912 |
public void run() { |
913 |
fTreeViewer.collapseAll(); |
914 |
} |
915 |
}; |
916 |
fCollapseAllAction.setImageDescriptor(TemplatesPageImages |
917 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_COLLAPSE_ALL)); |
918 |
fCollapseAllAction.setToolTipText(TemplatesPageMessages.TemplatesPage_collapse_all_tooltip); |
919 |
|
920 |
if (getPreferencePageId() != null) { |
921 |
fPreferencePageAction = new Action(TemplatesPageMessages.TemplatesPage_preference_page) { |
922 |
public void run() { |
923 |
showPreferencePage(); |
924 |
} |
925 |
}; |
926 |
fPreferencePageAction |
927 |
.setToolTipText(TemplatesPageMessages.TemplatesPage_preference_page_tooltip); |
928 |
} |
929 |
|
930 |
fPasteAction = new Action() { |
931 |
public void run() { |
932 |
Clipboard clipBoard = new Clipboard(getShell().getDisplay()); |
933 |
String pattern = ((String) clipBoard.getContents(TextTransfer.getInstance())); |
934 |
if (pattern != null) { |
935 |
final Template template = new Template(createTemplateName(), |
936 |
TemplatesPageMessages.TemplatesPage_paste_description, |
937 |
getContextTypeId(), pattern.replaceAll("\\$", "\\$\\$"), true); //$NON-NLS-1$//$NON-NLS-2$ |
938 |
if (template != null) |
939 |
getShell().getDisplay().asyncExec(new Runnable() { |
940 |
public void run() { |
941 |
addTemplate(template); |
942 |
} |
943 |
}); |
944 |
return ; |
945 |
} |
946 |
TemplatePersistenceData[] templates = (TemplatePersistenceData[]) clipBoard |
947 |
.getContents(TemplateTransfer.getInstance()); |
948 |
if (templates != null) |
949 |
copyTemplates(templates, getContextTypeId()); |
950 |
} |
951 |
}; |
952 |
|
953 |
fCopyAction = new Action() { |
954 |
public void run() { |
955 |
Clipboard clipBoard = new Clipboard(getShell().getDisplay()); |
956 |
clipBoard.setContents(new Object[] { getSelectedTemplates() }, |
957 |
new Transfer[] { TemplateTransfer.getInstance() }); |
958 |
} |
959 |
}; |
960 |
} |
961 |
|
962 |
/** |
963 |
* Fill the toolbar |
964 |
* |
965 |
* @param actionBars |
966 |
*/ |
967 |
private void fillToolbar(IActionBars actionBars) { |
968 |
IToolBarManager toolBarManager = actionBars.getToolBarManager(); |
969 |
toolBarManager.add(fInsertAction); |
970 |
toolBarManager.add(fAddAction); |
971 |
toolBarManager.add(fEditAction); |
972 |
toolBarManager.add(fRemoveAction); |
973 |
|
974 |
toolBarManager.add(new Separator()); |
975 |
|
976 |
toolBarManager.add(fLinkWithEditorAction); |
977 |
toolBarManager.add(fCollapseAllAction); |
978 |
} |
979 |
|
980 |
/** |
981 |
* Fill the view menu |
982 |
* |
983 |
* @param actionBars |
984 |
*/ |
985 |
private void fillMenu(IActionBars actionBars) { |
986 |
IMenuManager menuManager = actionBars.getMenuManager(); |
987 |
|
988 |
if (fPreferencePageAction != null) { |
989 |
menuManager.add(fPreferencePageAction); |
990 |
menuManager.add(new Separator()); |
991 |
} |
992 |
|
993 |
menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
994 |
} |
995 |
|
996 |
/** |
997 |
* Fill the context menu items |
998 |
* |
999 |
* @param manager |
1000 |
*/ |
1001 |
private void fillContextMenu(IMenuManager manager) { |
1002 |
manager.add(fInsertAction); |
1003 |
manager.add(new Separator()); |
1004 |
manager.add(fAddAction); |
1005 |
manager.add(fEditAction); |
1006 |
manager.add(fRemoveAction); |
1007 |
manager.add(new Separator()); |
1008 |
manager.add(fCopyAction); |
1009 |
manager.add(fPasteAction); |
1010 |
// Other plug-ins can contribute there actions here |
1011 |
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
1012 |
} |
1013 |
|
1014 |
/** |
1015 |
* Create the tree to display templates |
1016 |
* |
1017 |
* @param parent |
1018 |
*/ |
1019 |
private void createTemplateTree(Composite parent) { |
1020 |
Composite treeComposite = new Composite(parent, SWT.NONE); |
1021 |
GridData data = new GridData(GridData.FILL_BOTH); |
1022 |
treeComposite.setLayoutData(data); |
1023 |
|
1024 |
TreeColumnLayout columnLayout = new TreeColumnLayout(); |
1025 |
treeComposite.setLayout(columnLayout); |
1026 |
fTemplatesTree = new Tree(treeComposite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI |
1027 |
| SWT.FULL_SELECTION); |
1028 |
fTemplatesTree.setHeaderVisible(true); |
1029 |
fTemplatesTree.setLinesVisible(true); |
1030 |
|
1031 |
PixelConverter pixelConverter = new PixelConverter(fTemplatesTree); |
1032 |
|
1033 |
TreeColumn columnName = new TreeColumn(fTemplatesTree, SWT.NONE); |
1034 |
columnName.setText(TemplatesPageMessages.TemplatesPage_column_name); |
1035 |
int minWidth = fPreferenceStore.getInt(COLUMN_NAME_WIDTH_PREF_ID); |
1036 |
if (minWidth == 0) { |
1037 |
minWidth = pixelConverter.convertWidthInCharsToPixels(30); |
1038 |
} |
1039 |
columnLayout.setColumnData(columnName, new ColumnPixelData(minWidth, true)); |
1040 |
columnName.addControlListener(new ControlListener() { |
1041 |
public void controlMoved(ControlEvent e) { |
1042 |
} |
1043 |
|
1044 |
public void controlResized(ControlEvent e) { |
1045 |
int nameWidth = ((TreeColumn) e.getSource()).getWidth(); |
1046 |
fPreferenceStore.setValue(COLUMN_NAME_WIDTH_PREF_ID, nameWidth); |
1047 |
} |
1048 |
}); |
1049 |
|
1050 |
TreeColumn columnDescription = new TreeColumn(fTemplatesTree, SWT.NONE); |
1051 |
columnDescription.setText(TemplatesPageMessages.TemplatesPage_column_description); |
1052 |
minWidth = fPreferenceStore.getInt(COLUMN_DESCRIPTION_WIDTH_PREF_ID); |
1053 |
if (minWidth == 0) { |
1054 |
minWidth = pixelConverter.convertWidthInCharsToPixels(45); |
1055 |
} |
1056 |
columnLayout.setColumnData(columnDescription, new ColumnPixelData(minWidth, false)); |
1057 |
columnDescription.addControlListener(new ControlListener() { |
1058 |
public void controlMoved(ControlEvent e) { |
1059 |
} |
1060 |
|
1061 |
public void controlResized(ControlEvent e) { |
1062 |
int descriptionWidth = ((TreeColumn) e.getSource()).getWidth(); |
1063 |
fPreferenceStore.setValue(COLUMN_DESCRIPTION_WIDTH_PREF_ID, descriptionWidth); |
1064 |
} |
1065 |
}); |
1066 |
|
1067 |
createTreeViewer(fTemplatesTree); |
1068 |
} |
1069 |
|
1070 |
/** |
1071 |
* Create the tree viewer and setup the providers |
1072 |
* |
1073 |
* @param templatesTree |
1074 |
*/ |
1075 |
private void createTreeViewer(Tree templatesTree) { |
1076 |
fTreeViewer = new TreeViewer(fTemplatesTree); |
1077 |
fTreeViewer.setLabelProvider(new TemplateLabelProvider()); |
1078 |
fTreeViewer.setContentProvider(new TemplatesContentProvider()); |
1079 |
|
1080 |
fTreeViewer.setComparator(new TemplateViewerComparator()); |
1081 |
fTreeViewer.setInput(getTemplatePreferenceStore()); |
1082 |
fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { |
1083 |
public void doubleClick(DoubleClickEvent e) { |
1084 |
updateSelectedItems(); |
1085 |
TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); |
1086 |
insertTemplate(selectedTemplates[0].getTemplate(), null); |
1087 |
} |
1088 |
}); |
1089 |
|
1090 |
fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
1091 |
public void selectionChanged(SelectionChangedEvent e) { |
1092 |
updateSelectedItems(); |
1093 |
updateButtons(); |
1094 |
} |
1095 |
}); |
1096 |
fTreeViewer.expandAll(); |
1097 |
} |
1098 |
|
1099 |
/** |
1100 |
* Setup the pattern viewer |
1101 |
* |
1102 |
* @param parent |
1103 |
*/ |
1104 |
private void createPatternForm(Composite parent) { |
1105 |
ViewForm viewForm = new ViewForm(parent, SWT.NONE); |
1106 |
viewForm.setBorderVisible(false); |
1107 |
CLabel previewLabel = new CLabel(viewForm, SWT.NONE); |
1108 |
previewLabel.setText(TemplatesPageMessages.TemplatesPage_preview); |
1109 |
previewLabel.setImage(TemplatesPageImages.getImage(TemplatesPageImages.IMG_OBJ_PREVIEW)); |
1110 |
viewForm.setTopLeft(previewLabel); |
1111 |
|
1112 |
fPatternViewer = createPatternViewer(viewForm); |
1113 |
viewForm.setContent(fPatternViewer.getControl()); |
1114 |
viewForm.addControlListener(new ControlListener() { |
1115 |
public void controlMoved(ControlEvent e) { |
1116 |
} |
1117 |
|
1118 |
public void controlResized(ControlEvent e) { |
1119 |
int[] weights = fControl.getWeights(); |
1120 |
int sashSize = (int) (weights[0] * 100.0 / (weights[0] + weights[1])); |
1121 |
fPreferenceStore.setValue(SASH_SIZE_PREF_ID, sashSize); |
1122 |
} |
1123 |
}); |
1124 |
} |
1125 |
|
1126 |
/** |
1127 |
* Hookup the context menu |
1128 |
*/ |
1129 |
private void hookContextMenu() { |
1130 |
MenuManager menuMgr = new MenuManager(POPUP_MENU_ID); |
1131 |
menuMgr.setRemoveAllWhenShown(true); |
1132 |
menuMgr.addMenuListener(new IMenuListener() { |
1133 |
public void menuAboutToShow(IMenuManager manager) { |
1134 |
fillContextMenu(manager); |
1135 |
} |
1136 |
}); |
1137 |
fContextMenu = menuMgr.createContextMenu(fTreeViewer.getControl()); |
1138 |
fTreeViewer.getControl().setMenu(fContextMenu); |
1139 |
getSite().registerContextMenu(POPUP_MENU_ID, menuMgr, fTreeViewer); |
1140 |
} |
1141 |
|
1142 |
/** |
1143 |
* Check whether the template is valid for the given drop position |
1144 |
* |
1145 |
* @param template |
1146 |
* @param position |
1147 |
* @return true if the template is valid |
1148 |
*/ |
1149 |
private boolean isValidTemplateForPosition(Template template, Point position) { |
1150 |
StyledText textWidget = (StyledText) fEditor.getAdapter(Control.class); |
1151 |
IDocument document = fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); |
1152 |
try { |
1153 |
if (position.equals(fCachedPosition)) |
1154 |
return fCachedResult; |
1155 |
fCachedPosition = position; |
1156 |
int offset = getOffset(document, textWidget, textWidget.toControl(position.x, |
1157 |
position.y)); |
1158 |
if (fCachedOffset == offset) |
1159 |
return fCachedResult; |
1160 |
fCachedOffset = offset; |
1161 |
if (isValidTemplate(document, template, offset, 0)) |
1162 |
return fCachedResult = true; |
1163 |
} catch (BadLocationException e) { |
1164 |
} |
1165 |
return fCachedResult = false; |
1166 |
} |
1167 |
|
1168 |
/** |
1169 |
* Update the selected items. |
1170 |
*/ |
1171 |
private void updateSelectedItems() { |
1172 |
setSelectedTemplates(); |
1173 |
TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); |
1174 |
|
1175 |
if (selectedTemplates.length == 1) |
1176 |
updatePatternViewer(selectedTemplates[0].getTemplate()); |
1177 |
else |
1178 |
updatePatternViewer(null); |
1179 |
} |
1180 |
|
1181 |
/** |
1182 |
* Show the preference page. The action is enabled only if |
1183 |
* getPreferencePageId() returns non-null. |
1184 |
*/ |
1185 |
private void showPreferencePage() { |
1186 |
PreferencesUtil.createPreferenceDialogOn(getShell(), getPreferencePageId(), null, null) |
1187 |
.open(); |
1188 |
} |
1189 |
|
1190 |
/** |
1191 |
* Update the state of the buttons |
1192 |
*/ |
1193 |
private void updateButtons() { |
1194 |
TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); |
1195 |
fCopyAction.setEnabled(selectedTemplates.length > 0); |
1196 |
fInsertAction.setEnabled(selectedTemplates.length == 1); |
1197 |
fEditAction.setEnabled(selectedTemplates.length == 1); |
1198 |
fRemoveAction.setEnabled(selectedTemplates.length > 0); |
1199 |
} |
1200 |
|
1201 |
/** |
1202 |
* Set the selected templates |
1203 |
*/ |
1204 |
private void setSelectedTemplates() { |
1205 |
IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); |
1206 |
|
1207 |
Iterator it = selection.iterator(); |
1208 |
TemplatePersistenceData[] data = new TemplatePersistenceData[selection.size()]; |
1209 |
int i = 0; |
1210 |
while (it.hasNext()) { |
1211 |
Object o = it.next(); |
1212 |
if (o instanceof TemplatePersistenceData) |
1213 |
data[i++] = (TemplatePersistenceData) o; |
1214 |
else { |
1215 |
fSelectedTemplates = new TemplatePersistenceData[0]; |
1216 |
return; |
1217 |
} |
1218 |
} |
1219 |
fSelectedTemplates = data; |
1220 |
} |
1221 |
|
1222 |
/** |
1223 |
* Get the currently selected templates |
1224 |
* |
1225 |
* @return selected tempaltes |
1226 |
*/ |
1227 |
private TemplatePersistenceData[] getSelectedTemplates() { |
1228 |
return fSelectedTemplates; |
1229 |
} |
1230 |
|
1231 |
/** |
1232 |
* Add a template |
1233 |
*/ |
1234 |
private void addTemplate() { |
1235 |
String id = getContextTypeId(); |
1236 |
if (id != null) { |
1237 |
Template template = new Template("", "", id, "", true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
1238 |
|
1239 |
addTemplate(template); |
1240 |
} |
1241 |
} |
1242 |
|
1243 |
/** |
1244 |
* Get contextType of the selected template |
1245 |
* |
1246 |
* @return contextType of the selected template or the first from the |
1247 |
* registry if no templates are selected |
1248 |
*/ |
1249 |
private String getContextTypeId() { |
1250 |
IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); |
1251 |
Object item; |
1252 |
|
1253 |
if (selection.size() == 0) |
1254 |
return ((TemplateContextType) getContextTypeRegistry().contextTypes().next()).getId(); |
1255 |
|
1256 |
if (selection.size() == 1) { |
1257 |
item = selection.getFirstElement(); |
1258 |
if (item instanceof TemplatePersistenceData) |
1259 |
return ((TemplatePersistenceData) item).getTemplate().getContextTypeId(); |
1260 |
return ((TemplateContextType) item).getId(); |
1261 |
} |
1262 |
Iterator it = selection.iterator(); |
1263 |
String contextId = null; |
1264 |
while (it.hasNext()) { |
1265 |
item = it.next(); |
1266 |
if (contextId == null) |
1267 |
contextId = getContextId(item); |
1268 |
else if (!contextId.equals(getContextId(item))) |
1269 |
return ((TemplateContextType) getContextTypeRegistry().contextTypes().next()) |
1270 |
.getId(); |
1271 |
} |
1272 |
return contextId; |
1273 |
} |
1274 |
|
1275 |
/** |
1276 |
* Get the context id for the given item which is either a template or a |
1277 |
* context type. |
1278 |
* |
1279 |
* @param item |
1280 |
* @return the context type id |
1281 |
*/ |
1282 |
private String getContextId(Object item) { |
1283 |
String contextId; |
1284 |
if (item instanceof TemplatePersistenceData) |
1285 |
contextId = ((TemplatePersistenceData) item).getTemplate().getContextTypeId(); |
1286 |
else |
1287 |
contextId = ((TemplateContextType) item).getId(); |
1288 |
return contextId; |
1289 |
} |
1290 |
|
1291 |
/** |
1292 |
* Add a template. The dialog is filled with the values from the given |
1293 |
* template. |
1294 |
* |
1295 |
* @param template |
1296 |
*/ |
1297 |
private void addTemplate(Template template) { |
1298 |
Template newTemplate; |
1299 |
newTemplate = editTemplate(template, false, true); |
1300 |
if (newTemplate != null) { |
1301 |
TemplatePersistenceData data = new TemplatePersistenceData(newTemplate, true); |
1302 |
getTemplateStore().add(data); |
1303 |
saveTemplateStore(); |
1304 |
refresh(); |
1305 |
fTreeViewer.setSelection(new StructuredSelection(data), true); |
1306 |
} |
1307 |
} |
1308 |
|
1309 |
/** |
1310 |
* Save the template store |
1311 |
*/ |
1312 |
private void saveTemplateStore() { |
1313 |
try { |
1314 |
getTemplateStore().save(); |
1315 |
} catch (IOException e) { |
1316 |
e.printStackTrace(); |
1317 |
MessageDialog.openError(getShell(), |
1318 |
TemplatesPageMessages.TemplatesPage_save_error_message, e.getMessage()); |
1319 |
} |
1320 |
} |
1321 |
|
1322 |
/** |
1323 |
* Edit the selected template |
1324 |
*/ |
1325 |
private void editTemplate() { |
1326 |
Template oldTemplate = getSelectedTemplates()[0].getTemplate(); |
1327 |
Template newTemplate = editTemplate(new Template(oldTemplate), true, true); |
1328 |
if (newTemplate != null) { |
1329 |
if (!newTemplate.getName().equals(oldTemplate.getName()) |
1330 |
&& MessageDialog.openQuestion(getShell(), |
1331 |
TemplatesPageMessages.TemplatesPage_question_create_new_title, |
1332 |
TemplatesPageMessages.TemplatesPage_question_create_new_message)) { |
1333 |
TemplatePersistenceData templateData = new TemplatePersistenceData(newTemplate, |
1334 |
true); |
1335 |
getTemplateStore().add(templateData); |
1336 |
refresh(); |
1337 |
fTreeViewer.setSelection(new StructuredSelection(templateData), true); |
1338 |
} else { |
1339 |
getSelectedTemplates()[0].setTemplate(newTemplate); |
1340 |
} |
1341 |
} |
1342 |
saveTemplateStore(); |
1343 |
} |
1344 |
|
1345 |
/** |
1346 |
* Move the selected template from one context to another |
1347 |
* |
1348 |
* @param templates |
1349 |
* @param contextId |
1350 |
* |
1351 |
*/ |
1352 |
private void moveTemplates(TemplatePersistenceData[] templates, String contextId) { |
1353 |
for (int i = 0; i < templates.length; i++) { |
1354 |
Template t = templates[i].getTemplate(); |
1355 |
templates[i].setTemplate(new Template(t.getName(), t.getDescription(), contextId, t |
1356 |
.getPattern(), t.isAutoInsertable())); |
1357 |
} |
1358 |
saveTemplateStore(); |
1359 |
fTreeViewer.setSelection(new StructuredSelection(templates), true); |
1360 |
} |
1361 |
|
1362 |
/** |
1363 |
* Copy the selected templates to another context |
1364 |
* |
1365 |
* @param templates |
1366 |
* @param contextId |
1367 |
* |
1368 |
*/ |
1369 |
private void copyTemplates(TemplatePersistenceData[] templates, String contextId) { |
1370 |
TemplatePersistenceData[] newTemplates = new TemplatePersistenceData[templates.length]; |
1371 |
for (int i = 0; i < templates.length; i++) { |
1372 |
Template t = templates[i].getTemplate(); |
1373 |
newTemplates[i] = new TemplatePersistenceData(new Template(t.getName(), t |
1374 |
.getDescription(), contextId, t.getPattern(), t.isAutoInsertable()), true); |
1375 |
getTemplateStore().add(newTemplates[i]); |
1376 |
} |
1377 |
saveTemplateStore(); |
1378 |
refresh(); |
1379 |
fTreeViewer.setSelection(new StructuredSelection(newTemplates), true); |
1380 |
} |
1381 |
|
1382 |
/** |
1383 |
* Remove one or more selected templates |
1384 |
*/ |
1385 |
private void removeTemplates() { |
1386 |
String title; |
1387 |
TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); |
1388 |
if (selectedTemplates.length == 1) |
1389 |
title = TemplatesPageMessages.TemplatesPage_remove_title_single; |
1390 |
else |
1391 |
title = TemplatesPageMessages.TemplatesPage_remove_title_multi; |
1392 |
String message; |
1393 |
if (selectedTemplates.length == 1) |
1394 |
message = TemplatesPageMessages.TemplatesPage_remove_message_single; |
1395 |
else |
1396 |
message = NLSUtility.format(TemplatesPageMessages.TemplatesPage_remove_message_multi, |
1397 |
new Object[] { new Integer(selectedTemplates.length) }); |
1398 |
if (!MessageDialog.openQuestion(getShell(), title, message)) |
1399 |
return; |
1400 |
for (int i = 0; i < selectedTemplates.length; i++) { |
1401 |
getTemplateStore().delete(selectedTemplates[i]); |
1402 |
} |
1403 |
saveTemplateStore(); |
1404 |
fTreeViewer.setSelection(new StructuredSelection(new Object[] {}), true); |
1405 |
} |
1406 |
|
1407 |
/** |
1408 |
* Initialize drag and drop the template items |
1409 |
*/ |
1410 |
private void initializeDND() { |
1411 |
DragSourceAdapter dragListener = new DragSourceAdapter() { |
1412 |
/* |
1413 |
* (non-Javadoc) |
1414 |
* |
1415 |
* @see org.eclipse.swt.dnd.DragSourceAdapter#dragStart(org.eclipse.swt.dnd.DragSourceEvent) |
1416 |
*/ |
1417 |
public void dragStart(DragSourceEvent event) { |
1418 |
if (getSelectedTemplates().length == 0) { |
1419 |
event.doit = false; |
1420 |
} |
1421 |
} |
1422 |
|
1423 |
/* |
1424 |
* (non-Javadoc) |
1425 |
* |
1426 |
* @see org.eclipse.swt.dnd.DragSourceAdapter#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) |
1427 |
*/ |
1428 |
public void dragSetData(DragSourceEvent event) { |
1429 |
if (TemplateTransfer.getInstance().isSupportedType(event.dataType)) { |
1430 |
event.data = getSelectedTemplates(); |
1431 |
} |
1432 |
} |
1433 |
}; |
1434 |
fTreeViewer.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] { TemplateTransfer |
1435 |
.getInstance() }, dragListener); |
1436 |
DropTargetAdapter dropListener = new DropTargetAdapter() { |
1437 |
Transfer textTransfer = TextTransfer.getInstance(); |
1438 |
Transfer templateTransfer = TemplateTransfer.getInstance(); |
1439 |
|
1440 |
/* |
1441 |
* (non-Javadoc) |
1442 |
* |
1443 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) |
1444 |
*/ |
1445 |
public void dragEnter(DropTargetEvent event) { |
1446 |
if (event.detail == DND.DROP_DEFAULT) |
1447 |
event.detail = DND.DROP_COPY; |
1448 |
} |
1449 |
|
1450 |
/* |
1451 |
* (non-Javadoc) |
1452 |
* |
1453 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) |
1454 |
*/ |
1455 |
public void dragOperationChanged(DropTargetEvent event) { |
1456 |
if (event.detail == DND.DROP_DEFAULT) |
1457 |
event.detail = DND.DROP_COPY; |
1458 |
} |
1459 |
|
1460 |
/* |
1461 |
* (non-Javadoc) |
1462 |
* |
1463 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) |
1464 |
*/ |
1465 |
public void dragOver(DropTargetEvent event) { |
1466 |
event.feedback |= DND.FEEDBACK_SCROLL; |
1467 |
if (event.item == null) { |
1468 |
event.detail = DND.DROP_NONE; |
1469 |
return; |
1470 |
} |
1471 |
int index = 0; |
1472 |
boolean isTemplateTransfer = false; |
1473 |
while (index < event.dataTypes.length) { |
1474 |
if (textTransfer.isSupportedType(event.dataTypes[index])) { |
1475 |
break; |
1476 |
} |
1477 |
if (templateTransfer.isSupportedType(event.dataTypes[index])) { |
1478 |
isTemplateTransfer = true; |
1479 |
break; |
1480 |
} |
1481 |
index++; |
1482 |
} |
1483 |
if (index < event.dataTypes.length) { |
1484 |
event.currentDataType = event.dataTypes[index]; |
1485 |
if (event.detail == DND.DROP_DEFAULT || !isTemplateTransfer) |
1486 |
event.detail = DND.DROP_COPY; |
1487 |
return; |
1488 |
} |
1489 |
} |
1490 |
|
1491 |
/* |
1492 |
* (non-Javadoc) |
1493 |
* |
1494 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent) |
1495 |
*/ |
1496 |
public void drop(DropTargetEvent event) { |
1497 |
if (event.item == null) |
1498 |
return; |
1499 |
Object object = ((TreeItem) event.item).getData(); |
1500 |
final String contextId; |
1501 |
if (object instanceof TemplateContextType) |
1502 |
contextId = ((TemplateContextType) object).getId(); |
1503 |
else |
1504 |
contextId = ((TemplatePersistenceData) object).getTemplate().getContextTypeId(); |
1505 |
if (textTransfer.isSupportedType(event.currentDataType)) { |
1506 |
String text = ((String) event.data).replaceAll("\\$", "\\$\\$"); //$NON-NLS-1$ //$NON-NLS-2$ |
1507 |
final Template template = new Template(createTemplateName(), |
1508 |
TemplatesPageMessages.TemplatesPage_paste_description, contextId, text, |
1509 |
true); |
1510 |
getShell().getDisplay().asyncExec(new Runnable() { |
1511 |
public void run() { |
1512 |
addTemplate(template); |
1513 |
} |
1514 |
}); |
1515 |
return; |
1516 |
} |
1517 |
if (templateTransfer.isSupportedType(event.currentDataType)) { |
1518 |
final TemplatePersistenceData[] templates = (TemplatePersistenceData[]) event.data; |
1519 |
final int dropType = event.detail; |
1520 |
getShell().getDisplay().asyncExec(new Runnable() { |
1521 |
public void run() { |
1522 |
if (dropType == DND.DROP_COPY) |
1523 |
copyTemplates(templates, contextId); |
1524 |
else |
1525 |
moveTemplates(templates, contextId); |
1526 |
} |
1527 |
}); |
1528 |
} |
1529 |
} |
1530 |
}; |
1531 |
Transfer[] transfers = new Transfer[] { TextTransfer.getInstance(), |
1532 |
TemplateTransfer.getInstance() }; |
1533 |
fTreeViewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, transfers, dropListener); |
1534 |
} |
1535 |
|
1536 |
/** |
1537 |
* Create a template name |
1538 |
* |
1539 |
* @return a new template name |
1540 |
*/ |
1541 |
private String createTemplateName() { |
1542 |
for (int i = 1; i < Integer.MAX_VALUE; i++) { |
1543 |
String name = TemplatesPageMessages.TemplatesPage_snippet + i; |
1544 |
if (getTemplateStore().findTemplate(name) == null) |
1545 |
return name; |
1546 |
} |
1547 |
return null; |
1548 |
} |
1549 |
|
1550 |
/** |
1551 |
* Store the collapse state of a context |
1552 |
*/ |
1553 |
private void storeCollapseState() { |
1554 |
TreeItem[] items = fTreeViewer.getTree().getItems(); |
1555 |
for (int i = 0; i < items.length; i++) { |
1556 |
fPreferenceStore.setValue(CONTEXT_COLLAPSE_PREF_ID |
1557 |
+ ((TemplateContextType) items[i].getData()).getId(), !items[i].getExpanded()); |
1558 |
} |
1559 |
} |
1560 |
|
1561 |
/** |
1562 |
* Refresh the template tree contents |
1563 |
*/ |
1564 |
private void refresh() { |
1565 |
storeCollapseState(); |
1566 |
fTreeViewer.getTree().setRedraw(false); |
1567 |
try { |
1568 |
fTreeViewer.refresh(); |
1569 |
TreeItem[] items = fTreeViewer.getTree().getItems(); |
1570 |
for (int i = 0; i < items.length; i++) { |
1571 |
boolean isExpanded = !fPreferenceStore.getBoolean(CONTEXT_COLLAPSE_PREF_ID |
1572 |
+ ((TemplateContextType) items[i].getData()).getId()); |
1573 |
if (isExpanded) |
1574 |
fTreeViewer.expandToLevel(items[i].getData(), AbstractTreeViewer.ALL_LEVELS); |
1575 |
else |
1576 |
fTreeViewer.collapseToLevel(items[i].getData(), AbstractTreeViewer.ALL_LEVELS); |
1577 |
} |
1578 |
} finally { |
1579 |
fTreeViewer.getTree().setRedraw(true); |
1580 |
} |
1581 |
} |
1582 |
|
1583 |
/** |
1584 |
* Get the document relative offset from the textwidget relative point |
1585 |
* |
1586 |
* @param document |
1587 |
* @param textWidget |
1588 |
* @param point |
1589 |
* @return the offset |
1590 |
* @throws BadLocationException |
1591 |
*/ |
1592 |
private int getOffset(IDocument document, StyledText textWidget, Point point) |
1593 |
throws BadLocationException { |
1594 |
int widgetCaret = fViewer.getTextWidget().getCaretOffset(); |
1595 |
if (fViewer instanceof ITextViewerExtension5) { |
1596 |
ITextViewerExtension5 ext = (ITextViewerExtension5) fViewer; |
1597 |
try { |
1598 |
return ext.widgetOffset2ModelOffset(textWidget.getOffsetAtLocation(point)); |
1599 |
} catch (IllegalArgumentException e) { |
1600 |
int docLineIndex = ext.widgetLine2ModelLine(textWidget.getLineIndex(point.y)); |
1601 |
String lineDelimiter = document.getLineDelimiter(docLineIndex); |
1602 |
int delimLength = lineDelimiter == null ? 0 : lineDelimiter.length(); |
1603 |
return document.getLineOffset(docLineIndex) + document.getLineLength(docLineIndex) |
1604 |
- delimLength; |
1605 |
} |
1606 |
} |
1607 |
IRegion visible = fViewer.getVisibleRegion(); |
1608 |
return widgetCaret + visible.getOffset(); |
1609 |
} |
1610 |
} |