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.resource.JFaceResources; |
31 |
import org.eclipse.jface.text.templates.ContextTypeRegistry; |
32 |
import org.eclipse.jface.text.templates.Template; |
33 |
import org.eclipse.jface.text.templates.TemplateContextType; |
34 |
import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; |
35 |
import org.eclipse.jface.text.templates.persistence.TemplateStore; |
36 |
import org.eclipse.jface.util.IPropertyChangeListener; |
37 |
import org.eclipse.jface.util.PropertyChangeEvent; |
38 |
import org.eclipse.jface.viewers.ColumnPixelData; |
39 |
import org.eclipse.jface.viewers.DoubleClickEvent; |
40 |
import org.eclipse.jface.viewers.IDoubleClickListener; |
41 |
import org.eclipse.jface.viewers.ISelectionChangedListener; |
42 |
import org.eclipse.jface.viewers.IStructuredSelection; |
43 |
import org.eclipse.jface.viewers.ITableLabelProvider; |
44 |
import org.eclipse.jface.viewers.ITreeContentProvider; |
45 |
import org.eclipse.jface.viewers.LabelProvider; |
46 |
import org.eclipse.jface.viewers.SelectionChangedEvent; |
47 |
import org.eclipse.jface.viewers.StructuredSelection; |
48 |
import org.eclipse.jface.viewers.TreeViewer; |
49 |
import org.eclipse.jface.viewers.Viewer; |
50 |
import org.eclipse.jface.viewers.ViewerComparator; |
51 |
import org.eclipse.swt.SWT; |
52 |
import org.eclipse.swt.custom.CLabel; |
53 |
import org.eclipse.swt.custom.SashForm; |
54 |
import org.eclipse.swt.custom.ViewForm; |
55 |
import org.eclipse.swt.dnd.Clipboard; |
56 |
import org.eclipse.swt.dnd.DND; |
57 |
import org.eclipse.swt.dnd.DragSourceAdapter; |
58 |
import org.eclipse.swt.dnd.DragSourceEvent; |
59 |
import org.eclipse.swt.dnd.DropTargetAdapter; |
60 |
import org.eclipse.swt.dnd.DropTargetEvent; |
61 |
import org.eclipse.swt.dnd.Transfer; |
62 |
import org.eclipse.swt.events.ControlEvent; |
63 |
import org.eclipse.swt.events.ControlListener; |
64 |
import org.eclipse.swt.graphics.GC; |
65 |
import org.eclipse.swt.graphics.Image; |
66 |
import org.eclipse.swt.graphics.Point; |
67 |
import org.eclipse.swt.layout.GridData; |
68 |
import org.eclipse.swt.widgets.Composite; |
69 |
import org.eclipse.swt.widgets.Control; |
70 |
import org.eclipse.swt.widgets.Menu; |
71 |
import org.eclipse.swt.widgets.Shell; |
72 |
import org.eclipse.swt.widgets.Tree; |
73 |
import org.eclipse.swt.widgets.TreeColumn; |
74 |
import org.eclipse.swt.widgets.TreeItem; |
75 |
import org.eclipse.ui.IActionBars; |
76 |
import org.eclipse.ui.IWorkbenchActionConstants; |
77 |
import org.eclipse.ui.IWorkbenchPartSite; |
78 |
import org.eclipse.ui.actions.ActionFactory; |
79 |
import org.eclipse.ui.dialogs.PreferencesUtil; |
80 |
import org.eclipse.ui.dnd.IDragAndDropService; |
81 |
import org.eclipse.ui.internal.texteditor.NLSUtility; |
82 |
import org.eclipse.ui.internal.texteditor.TextEditorPlugin; |
83 |
import org.eclipse.ui.part.Page; |
84 |
import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; |
85 |
|
86 |
/** |
87 |
* An abstract base class for template pages. |
88 |
* <p> |
89 |
* Clients who are defining an editor may elect to provide a corresponding |
90 |
* templates page. This templates page will be presented to the user via the |
91 |
* Templates View (the user decides whether their workbench window contains this |
92 |
* view) whenever that editor is active. This class should be subclassed by |
93 |
* clients. |
94 |
* </p> |
95 |
* <p> |
96 |
* Internally, a TemplatesPage uses the template store to display different |
97 |
* categories. A link to editor mode on the templates page allows to filtering |
98 |
* of the categories to only that are supported in this context. |
99 |
* </p> |
100 |
* |
101 |
* @since 3.4 |
102 |
*/ |
103 |
public abstract class TemplatesPage extends Page { |
104 |
|
105 |
/** |
106 |
* Sashform size |
107 |
*/ |
108 |
private static final String SASH_SIZE_PREF_ID = TextEditorPlugin.PLUGIN_ID |
109 |
+ ".templates.templatesPage.sashSize"; //$NON-NLS-1$ |
110 |
/** |
111 |
* Tree columns widths |
112 |
*/ |
113 |
private static final String COLUMN_NAME_WIDTH_PREF_ID = TextEditorPlugin.PLUGIN_ID |
114 |
+ ".templates.templatesPage.nameWidth"; //$NON-NLS-1$ |
115 |
private static final String COLUMN_DESCRIPTION_WIDTH_PREF_ID = TextEditorPlugin.PLUGIN_ID |
116 |
+ ".templates.templatesPage.descriptionWidth"; //$NON-NLS-1$ |
117 |
/** |
118 |
* Link to editor action setting |
119 |
*/ |
120 |
private static final String LINK_ACTION_PREF_ID = TextEditorPlugin.PLUGIN_ID |
121 |
+ ".templates.templatesPage.linkAction"; //$NON-NLS-1$ |
122 |
/** |
123 |
* Show disabled actions setting |
124 |
*/ |
125 |
private static final String SHOW_DISABLED_ACTION_PREF_ID = TextEditorPlugin.PLUGIN_ID |
126 |
+ ".templates.templatesPage.showDisabledAction"; //$NON-NLS-1$ |
127 |
/** |
128 |
* The ID for the popup menu for this templates page |
129 |
*/ |
130 |
private static final String POPUP_MENU_ID = "org.eclipse.ui.texteditor.templates.PopupMenu"; //$NON-NLS-1$ |
131 |
|
132 |
/** |
133 |
* Default image for a template |
134 |
*/ |
135 |
private static final Image DEFAULT_TEMPLATE_IMAGE = TemplatesPageImages |
136 |
.getImage(TemplatesPageImages.IMG_OBJ_TEMPLATE); |
137 |
/** |
138 |
* Image for the context |
139 |
*/ |
140 |
private static final Image CONTEXT_IMAGE = TemplatesPageImages |
141 |
.getImage(TemplatesPageImages.IMG_OBJ_CONTEXT); |
142 |
|
143 |
/** |
144 |
* Drop support for the editor linked to this page. When a user drops a |
145 |
* template into the active editor, the template is applied at the drop |
146 |
* position. |
147 |
*/ |
148 |
private final class EditorDropTarget extends DropTargetAdapter { |
149 |
/* |
150 |
* (non-Javadoc) |
151 |
* |
152 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) |
153 |
*/ |
154 |
public void dragEnter(DropTargetEvent event) { |
155 |
event.detail = DND.DROP_COPY; |
156 |
} |
157 |
|
158 |
/* |
159 |
* (non-Javadoc) |
160 |
* |
161 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) |
162 |
*/ |
163 |
public void dragOperationChanged(DropTargetEvent event) { |
164 |
event.detail = DND.DROP_COPY; |
165 |
} |
166 |
|
167 |
/* |
168 |
* (non-Javadoc) |
169 |
* |
170 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) |
171 |
*/ |
172 |
public void dragOver(DropTargetEvent event) { |
173 |
event.feedback |= DND.FEEDBACK_SCROLL; |
174 |
event.detail = DND.DROP_NONE; |
175 |
if (isEditorModifiable() |
176 |
&& isValidTemplateForPosition(getSelectedTemplate(), |
177 |
new Point(event.x, event.y))) |
178 |
event.detail = DND.DROP_COPY; |
179 |
} |
180 |
|
181 |
/* |
182 |
* (non-Javadoc) |
183 |
* |
184 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent) |
185 |
*/ |
186 |
public void drop(DropTargetEvent event) { |
187 |
insertTemplate(getSelectedTemplate(), new Point(event.x, event.y)); |
188 |
} |
189 |
} |
190 |
|
191 |
/** |
192 |
* Comparator for the viewer. Sorts the templates by name and then |
193 |
* description and context types by names. |
194 |
*/ |
195 |
private static final class TemplateViewerComparator extends ViewerComparator { |
196 |
/* |
197 |
* (non-Javadoc) |
198 |
* |
199 |
* @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, |
200 |
* java.lang.Object, java.lang.Object) |
201 |
*/ |
202 |
public int compare(Viewer viewer, Object object1, Object object2) { |
203 |
if ((object1 instanceof TemplatePersistenceData) |
204 |
&& (object2 instanceof TemplatePersistenceData)) { |
205 |
Template left = ((TemplatePersistenceData) object1).getTemplate(); |
206 |
Template right = ((TemplatePersistenceData) object2).getTemplate(); |
207 |
int result = left.getName().compareToIgnoreCase(right.getName()); |
208 |
if (result != 0) |
209 |
return result; |
210 |
return left.getDescription().compareToIgnoreCase(right.getDescription()); |
211 |
} |
212 |
if ((object1 instanceof TemplateContextType) |
213 |
&& (object2 instanceof TemplateContextType)) { |
214 |
return ((TemplateContextType) object1).getName().compareToIgnoreCase( |
215 |
((TemplateContextType) object1).getName()); |
216 |
} |
217 |
return super.compare(viewer, object1, object2); |
218 |
} |
219 |
|
220 |
/* |
221 |
* (non-Javadoc) |
222 |
* |
223 |
* @see org.eclipse.jface.viewers.ViewerComparator#isSorterProperty(java.lang.Object, |
224 |
* java.lang.String) |
225 |
*/ |
226 |
public boolean isSorterProperty(Object element, String property) { |
227 |
return true; |
228 |
} |
229 |
} |
230 |
|
231 |
/** |
232 |
* Label provider for templates. |
233 |
*/ |
234 |
private class TemplateLabelProvider extends LabelProvider implements ITableLabelProvider { |
235 |
/* |
236 |
* (non-Javadoc) |
237 |
* |
238 |
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, |
239 |
* int) |
240 |
*/ |
241 |
public Image getColumnImage(Object element, int columnIndex) { |
242 |
if (columnIndex != 0) |
243 |
return null; |
244 |
if (element instanceof TemplateContextType) |
245 |
return CONTEXT_IMAGE; |
246 |
return getImageForTemplate(((TemplatePersistenceData) element).getTemplate()); |
247 |
} |
248 |
|
249 |
/* |
250 |
* (non-Javadoc) |
251 |
* |
252 |
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, |
253 |
* int) |
254 |
*/ |
255 |
public String getColumnText(Object element, int columnIndex) { |
256 |
if (element instanceof TemplatePersistenceData) |
257 |
return getTemplateColumnText((TemplatePersistenceData) element, columnIndex); |
258 |
return getContextColumnText((TemplateContextType) element, columnIndex); |
259 |
} |
260 |
|
261 |
private String getTemplateColumnText(TemplatePersistenceData data, int columnIndex) { |
262 |
switch (columnIndex) { |
263 |
case 0: |
264 |
return data.getTemplate().getName(); |
265 |
case 1: |
266 |
return data.getTemplate().getDescription(); |
267 |
default: |
268 |
return ""; //$NON-NLS-1$ |
269 |
} |
270 |
} |
271 |
|
272 |
private String getContextColumnText(TemplateContextType contextType, int columnIndex) { |
273 |
switch (columnIndex) { |
274 |
case 0: |
275 |
return contextType.getName(); |
276 |
default: |
277 |
return ""; //$NON-NLS-1$ |
278 |
} |
279 |
} |
280 |
} |
281 |
|
282 |
/** |
283 |
* Content provider for templates. Provides all the enabled templates |
284 |
* defined for this editor. |
285 |
*/ |
286 |
private class TemplatesContentProvider implements ITreeContentProvider { |
287 |
/* |
288 |
* (non-Javadoc) |
289 |
* |
290 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) |
291 |
*/ |
292 |
public Object[] getChildren(Object parentElement) { |
293 |
if (parentElement instanceof TemplatePersistenceData) |
294 |
return new Object[0]; |
295 |
else if (parentElement instanceof TemplateContextType) { |
296 |
TemplateContextType contextType = (TemplateContextType) parentElement; |
297 |
return getTemplates(contextType.getId()); |
298 |
} |
299 |
return null; |
300 |
} |
301 |
|
302 |
private TemplatePersistenceData[] getTemplates(String contextId) { |
303 |
List templateList = new ArrayList(); |
304 |
TemplatePersistenceData[] datas = getTemplateStore().getTemplateData(false); |
305 |
for (int i = 0; i < datas.length; i++) { |
306 |
if (datas[i].isEnabled() |
307 |
&& datas[i].getTemplate().getContextTypeId().equals(contextId)) |
308 |
templateList.add(datas[i]); |
309 |
} |
310 |
return (TemplatePersistenceData[]) templateList |
311 |
.toArray(new TemplatePersistenceData[templateList.size()]); |
312 |
} |
313 |
|
314 |
/* |
315 |
* (non-Javadoc) |
316 |
* |
317 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) |
318 |
*/ |
319 |
public Object getParent(Object element) { |
320 |
if (element instanceof TemplatePersistenceData) { |
321 |
TemplatePersistenceData templateData = (TemplatePersistenceData) element; |
322 |
return getContextTypeRegistry().getContextType( |
323 |
templateData.getTemplate().getContextTypeId()); |
324 |
} |
325 |
return null; |
326 |
} |
327 |
|
328 |
/* |
329 |
* (non-Javadoc) |
330 |
* |
331 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) |
332 |
*/ |
333 |
public boolean hasChildren(Object element) { |
334 |
if (element instanceof TemplateContextType) |
335 |
return true; |
336 |
return false; |
337 |
} |
338 |
|
339 |
/* |
340 |
* (non-Javadoc) |
341 |
* |
342 |
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) |
343 |
*/ |
344 |
public Object[] getElements(Object inputElement) { |
345 |
List contextTypes = new ArrayList(); |
346 |
|
347 |
for (Iterator iterator = getContextTypeRegistry().contextTypes(); iterator.hasNext();) { |
348 |
TemplateContextType contextType = (TemplateContextType) iterator.next(); |
349 |
if (isActiveContext(contextType) || !fLinkWithEditor) |
350 |
contextTypes.add(contextType); |
351 |
} |
352 |
return contextTypes.toArray(new TemplateContextType[contextTypes.size()]); |
353 |
} |
354 |
|
355 |
private boolean isActiveContext(TemplateContextType contextType) { |
356 |
return fActiveTypes == null || fActiveTypes.contains(contextType.getId()); |
357 |
} |
358 |
|
359 |
/* |
360 |
* (non-Javadoc) |
361 |
* |
362 |
* @see org.eclipse.jface.viewers.IContentProvider#dispose() |
363 |
*/ |
364 |
public void dispose() { |
365 |
} |
366 |
|
367 |
/* |
368 |
* (non-Javadoc) |
369 |
* |
370 |
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, |
371 |
* java.lang.Object, java.lang.Object) |
372 |
*/ |
373 |
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
374 |
} |
375 |
} |
376 |
|
377 |
/** |
378 |
* Listener to monitor changes to template store |
379 |
*/ |
380 |
private IPropertyChangeListener fTemplateChangeListener; |
381 |
|
382 |
/** |
383 |
* Control for this pagebook view |
384 |
*/ |
385 |
private SashForm fControl; |
386 |
|
387 |
/* Actions */ |
388 |
private Action fInsertAction; |
389 |
private Action fAddAction; |
390 |
private Action fEditAction; |
391 |
private Action fRemoveAction; |
392 |
private Action fLinkWithEditorAction; |
393 |
private Action fCollapseAllAction; |
394 |
private Action fPreferencePageAction; |
395 |
|
396 |
/* Clipboard actions */ |
397 |
private Action fPasteAction; |
398 |
private Action fCopyAction; |
399 |
|
400 |
/* Options and values saved in preference store */ |
401 |
private boolean fLinkWithEditor; |
402 |
private int fSashSize; |
403 |
private int fNameWidth; |
404 |
private int fDescriptionWidth; |
405 |
|
406 |
/** Currently selected templates and type */ |
407 |
private ArrayList fSelectedTemplateList = new ArrayList(); |
408 |
private TemplateContextType fSelectedType; |
409 |
|
410 |
/** Current active context types for the editor */ |
411 |
private List fActiveTypes; |
412 |
|
413 |
/* Preference stores */ |
414 |
/** |
415 |
* Preference store to store the dialog setting for this page |
416 |
*/ |
417 |
private IPreferenceStore fPreferenceStore; |
418 |
|
419 |
/* Controls */ |
420 |
private Tree fTemplatesTree; |
421 |
private TreeViewer fTreeViewer; |
422 |
private Menu fContextMenu; |
423 |
|
424 |
/** |
425 |
* The template that is being dragged |
426 |
*/ |
427 |
private TemplatePersistenceData fDnDTemplate; |
428 |
|
429 |
/** |
430 |
* Creates a new template view page. |
431 |
*/ |
432 |
protected TemplatesPage() { |
433 |
super(); |
434 |
setupPreferenceStore(); |
435 |
} |
436 |
|
437 |
/* |
438 |
* (non-Javadoc) |
439 |
* |
440 |
* @see org.eclipse.ui.part.Page#createControl(org.eclipse.swt.widgets.Composite) |
441 |
*/ |
442 |
public void createControl(Composite ancestor) { |
443 |
setupActions(); |
444 |
|
445 |
fControl = new SashForm(ancestor, SWT.VERTICAL); |
446 |
|
447 |
createTemplateTree(); |
448 |
setupPatternViewer(fControl); |
449 |
|
450 |
hookContextMenu(); |
451 |
initializeDND(); |
452 |
updateButtons(); |
453 |
|
454 |
fControl.setWeights(new int[] { fSashSize, 100 - fSashSize }); |
455 |
fTemplateChangeListener = new IPropertyChangeListener() { |
456 |
public void propertyChange(PropertyChangeEvent event) { |
457 |
refresh(); |
458 |
} |
459 |
}; |
460 |
getTemplatePreferenceStore().addPropertyChangeListener(fTemplateChangeListener); |
461 |
} |
462 |
|
463 |
/* |
464 |
* (non-Javadoc) |
465 |
* |
466 |
* @see org.eclipse.ui.part.Page#setFocus() |
467 |
*/ |
468 |
public void setFocus() { |
469 |
} |
470 |
|
471 |
/* |
472 |
* (non-Javadoc) |
473 |
* |
474 |
* @see org.eclipse.ui.part.Page#getControl() |
475 |
*/ |
476 |
public Control getControl() { |
477 |
return fControl; |
478 |
} |
479 |
|
480 |
/* |
481 |
* (non-Javadoc) |
482 |
* |
483 |
* @see org.eclipse.ui.part.Page#dispose() |
484 |
*/ |
485 |
public void dispose() { |
486 |
if (fContextMenu != null && !fContextMenu.isDisposed()) |
487 |
fContextMenu.dispose(); |
488 |
if (fTemplateChangeListener != null) |
489 |
getTemplatePreferenceStore().removePropertyChangeListener(fTemplateChangeListener); |
490 |
super.dispose(); |
491 |
} |
492 |
|
493 |
/** |
494 |
* Get the shell |
495 |
* |
496 |
* @return the shell for this view site |
497 |
*/ |
498 |
protected Shell getShell() { |
499 |
return getSite().getShell(); |
500 |
} |
501 |
|
502 |
/** |
503 |
* The caret position in the editor has moved into a new context type. It is |
504 |
* the subclasses responsibility to see that this is called only when needed |
505 |
* by keeping track of editor contents (eg. partitions). |
506 |
* |
507 |
* @param ids |
508 |
*/ |
509 |
protected void updateContextTypes(String[] ids) { |
510 |
fActiveTypes = Arrays.asList(ids); |
511 |
if (fLinkWithEditorAction != null && fLinkWithEditor) |
512 |
refresh(); |
513 |
} |
514 |
|
515 |
/** |
516 |
* Setup the editor site as a drop target. Should be invoked by the |
517 |
* subclasses for the D&D to work with the editor. |
518 |
* |
519 |
* @param site |
520 |
* @param viewer |
521 |
*/ |
522 |
protected void setupEditorDropTarget(IWorkbenchPartSite site, Control viewer) { |
523 |
IDragAndDropService dndService = (IDragAndDropService) site |
524 |
.getService(IDragAndDropService.class); |
525 |
EditorDropTarget editorDropTarget = new EditorDropTarget(); |
526 |
dndService.addMergedDropTarget(viewer, DND.DROP_COPY, new Transfer[] { TemplateTransfer |
527 |
.getInstance() }, editorDropTarget); |
528 |
} |
529 |
|
530 |
/** |
531 |
* Convert the clipboard contents into a template |
532 |
* |
533 |
* @param clipBoard |
534 |
* @return the template or null if contents are not valid |
535 |
*/ |
536 |
protected Template getTemplateFromClipboard(Clipboard clipBoard) { |
537 |
Template[] contents = (Template[]) clipBoard.getContents(TemplateTransfer.getInstance()); |
538 |
if (contents != null) |
539 |
return new Template(contents[0].getName(), contents[0].getDescription(), |
540 |
getContextTypeId(), contents[0].getPattern(), true); |
541 |
return null; |
542 |
} |
543 |
|
544 |
/** |
545 |
* Get the image to be used for the given template. Clients can override to |
546 |
* provide a different image. |
547 |
* |
548 |
* @param template |
549 |
* @return handle to the image |
550 |
*/ |
551 |
protected Image getImageForTemplate(Template template) { |
552 |
return DEFAULT_TEMPLATE_IMAGE; |
553 |
} |
554 |
|
555 |
/** |
556 |
* Subclasses should override and facilitate inserting the template code |
557 |
* into the active editor. |
558 |
* |
559 |
* @param template |
560 |
* @param position |
561 |
*/ |
562 |
abstract protected void insertTemplate(Template template, Point position); |
563 |
|
564 |
/** |
565 |
* Get the context type registry for the associated editor. |
566 |
* |
567 |
* @return the contextTypeRegistry |
568 |
*/ |
569 |
abstract protected ContextTypeRegistry getContextTypeRegistry(); |
570 |
|
571 |
/** |
572 |
* Get the template store for the associated editor |
573 |
* |
574 |
* @return the template store |
575 |
*/ |
576 |
abstract protected TemplateStore getTemplateStore(); |
577 |
|
578 |
/** |
579 |
* Get the preference store used to create the template store returned by |
580 |
* {@link TemplatesPage#getTemplateStore()}. |
581 |
* |
582 |
* @return the preference store |
583 |
*/ |
584 |
abstract protected IPreferenceStore getTemplatePreferenceStore(); |
585 |
|
586 |
/** |
587 |
* Check whether the template is valid for the given drop position |
588 |
* |
589 |
* @param template |
590 |
* @param position |
591 |
* @return true if the template is valid |
592 |
*/ |
593 |
abstract protected boolean isValidTemplateForPosition(Template template, Point position); |
594 |
|
595 |
/** |
596 |
* Check whether the linked editor is modifiable |
597 |
* |
598 |
* @return true if the editor is modifiable |
599 |
*/ |
600 |
abstract protected boolean isEditorModifiable(); |
601 |
|
602 |
/** |
603 |
* Get the pattern data from the clipboard. This data will be stored for the |
604 |
* template. |
605 |
* |
606 |
* @param clipBoard |
607 |
* @return pattern data or null if the clipboard does not have valid content |
608 |
*/ |
609 |
abstract protected String getTemplateDataFromClipboard(Clipboard clipBoard); |
610 |
|
611 |
/** |
612 |
* Get the preference page ID for the templates for the given editor. |
613 |
* |
614 |
* @return id of the preference page, null if none exists |
615 |
*/ |
616 |
abstract protected String getPreferencePageId(); |
617 |
|
618 |
/** |
619 |
* Creates the edit dialog. Subclasses may override this method to provide a |
620 |
* custom dialog. |
621 |
* |
622 |
* @param template |
623 |
* the template being edited |
624 |
* @param edit |
625 |
* whether the dialog should be editable |
626 |
* @param isNameModifiable |
627 |
* whether the template name may be modified |
628 |
* @return the created or modified template, or <code>null</code> if the |
629 |
* editing failed |
630 |
*/ |
631 |
abstract protected Template editTemplate(Template template, boolean edit, |
632 |
boolean isNameModifiable); |
633 |
|
634 |
/** |
635 |
* Get the pattern viewer. |
636 |
* |
637 |
* @param parent |
638 |
* @return the viewer |
639 |
*/ |
640 |
abstract protected Viewer createPatternViewer(Composite parent); |
641 |
|
642 |
/** |
643 |
* Get the transfers supported by this editor. |
644 |
* |
645 |
* @return array of transfers supported |
646 |
*/ |
647 |
abstract protected Transfer[] getTransfers(); |
648 |
|
649 |
/** |
650 |
* Create the template pattern from a DnD operation. |
651 |
* |
652 |
* @param transfer |
653 |
* @param data |
654 |
* @return pattern or null if the transfer is not supported |
655 |
*/ |
656 |
abstract protected String getTemplateDataFromDrop(Transfer transfer, Object data); |
657 |
|
658 |
/** |
659 |
* Update the pattern viewer to show the current template. |
660 |
* |
661 |
* @param template |
662 |
*/ |
663 |
abstract protected void updatePatternViewer(Template template); |
664 |
|
665 |
/** |
666 |
* Setup the preference store |
667 |
*/ |
668 |
private void setupPreferenceStore() { |
669 |
fPreferenceStore = TextEditorPlugin.getDefault().getPreferenceStore(); |
670 |
fPreferenceStore.setDefault(LINK_ACTION_PREF_ID, true); |
671 |
fPreferenceStore.setDefault(SHOW_DISABLED_ACTION_PREF_ID, false); |
672 |
fPreferenceStore.setDefault(SASH_SIZE_PREF_ID, 80); |
673 |
fLinkWithEditor = fPreferenceStore.getBoolean(LINK_ACTION_PREF_ID); |
674 |
fSashSize = fPreferenceStore.getInt(SASH_SIZE_PREF_ID); |
675 |
} |
676 |
|
677 |
/** |
678 |
* Setup the menu, context menu and toolbar actions. |
679 |
*/ |
680 |
private void setupActions() { |
681 |
createActions(); |
682 |
IActionBars actionBars = getSite().getActionBars(); |
683 |
|
684 |
actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), fPasteAction); |
685 |
fPasteAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE); |
686 |
fPasteAction.setText(TemplatesPageMessages.TemplatesPage_paste); |
687 |
actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction); |
688 |
fCopyAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY); |
689 |
fCopyAction.setText(TemplatesPageMessages.TemplatesPage_copy); |
690 |
fillToolbar(actionBars); |
691 |
fillMenu(actionBars); |
692 |
} |
693 |
|
694 |
/** |
695 |
* Create all the actions |
696 |
*/ |
697 |
private void createActions() { |
698 |
fInsertAction = new Action(TemplatesPageMessages.TemplatesPage_insert) { |
699 |
public void run() { |
700 |
insertTemplate(getSelectedTemplate(), null); |
701 |
} |
702 |
}; |
703 |
fInsertAction.setImageDescriptor(TemplatesPageImages |
704 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_INSERT)); |
705 |
fInsertAction.setDisabledImageDescriptor(TemplatesPageImages |
706 |
.getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_INSERT)); |
707 |
fInsertAction.setToolTipText(TemplatesPageMessages.TemplatesPage_insert_tooltip); |
708 |
|
709 |
fAddAction = new Action(TemplatesPageMessages.TemplatesPage_new) { |
710 |
public void run() { |
711 |
addTemplate(); |
712 |
} |
713 |
}; |
714 |
fAddAction.setImageDescriptor(TemplatesPageImages |
715 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_NEW)); |
716 |
fAddAction.setToolTipText(TemplatesPageMessages.TemplatesPage_new_tooltip); |
717 |
|
718 |
fEditAction = new Action(TemplatesPageMessages.TemplatesPage_edit) { |
719 |
public void run() { |
720 |
editTemplate(); |
721 |
} |
722 |
}; |
723 |
fEditAction.setImageDescriptor(TemplatesPageImages |
724 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_EDIT)); |
725 |
fEditAction.setDisabledImageDescriptor(TemplatesPageImages |
726 |
.getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_EDIT)); |
727 |
fEditAction.setToolTipText(TemplatesPageMessages.TemplatesPage_edit_tooltip); |
728 |
|
729 |
fRemoveAction = new Action(TemplatesPageMessages.TemplatesPage_remove) { |
730 |
public void run() { |
731 |
removeTemplate(); |
732 |
} |
733 |
}; |
734 |
fRemoveAction.setImageDescriptor(TemplatesPageImages |
735 |
.getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_DELETE)); |
736 |
fRemoveAction.setImageDescriptor(TemplatesPageImages |
737 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_DELETE)); |
738 |
fRemoveAction.setToolTipText(TemplatesPageMessages.TemplatesPage_remove_tooltip); |
739 |
|
740 |
fLinkWithEditorAction = new Action(TemplatesPageMessages.TemplatesPage_link_to_editor, |
741 |
IAction.AS_CHECK_BOX) { |
742 |
public void run() { |
743 |
fLinkWithEditor = fLinkWithEditorAction.isChecked(); |
744 |
fPreferenceStore.setValue(LINK_ACTION_PREF_ID, fLinkWithEditor); |
745 |
refresh(); |
746 |
} |
747 |
}; |
748 |
fLinkWithEditorAction.setImageDescriptor(TemplatesPageImages |
749 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_LINK)); |
750 |
fLinkWithEditorAction.setChecked(fPreferenceStore.getBoolean(LINK_ACTION_PREF_ID)); |
751 |
fLinkWithEditorAction |
752 |
.setToolTipText(TemplatesPageMessages.TemplatesPage_link_to_editor_tooltip); |
753 |
fCollapseAllAction = new Action(TemplatesPageMessages.TemplatesPage_collapse_all) { |
754 |
public void run() { |
755 |
fTreeViewer.collapseAll(); |
756 |
} |
757 |
}; |
758 |
fCollapseAllAction.setImageDescriptor(TemplatesPageImages |
759 |
.getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_COLLAPSE_ALL)); |
760 |
fCollapseAllAction |
761 |
.setToolTipText(TemplatesPageMessages.TemplatesPage_collapse_all_tooltip); |
762 |
|
763 |
if (getPreferencePageId() != null) { |
764 |
fPreferencePageAction = new Action( |
765 |
TemplatesPageMessages.TemplatesPage_preference_page) { |
766 |
public void run() { |
767 |
showPreferencePage(); |
768 |
} |
769 |
}; |
770 |
fPreferencePageAction |
771 |
.setToolTipText(TemplatesPageMessages.TemplatesPage_preference_page_tooltip); |
772 |
} |
773 |
|
774 |
fPasteAction = new Action() { |
775 |
public void run() { |
776 |
final Template template = readClipboardContents(); |
777 |
if (template != null) |
778 |
getShell().getDisplay().asyncExec(new Runnable() { |
779 |
public void run() { |
780 |
addTemplate(template); |
781 |
} |
782 |
}); |
783 |
} |
784 |
|
785 |
private Template readClipboardContents() { |
786 |
Clipboard clipBoard = new Clipboard(getShell().getDisplay()); |
787 |
String pattern = getTemplateDataFromClipboard(clipBoard); |
788 |
if (pattern != null) |
789 |
return new Template(createTemplateName(), |
790 |
TemplatesPageMessages.TemplatesPage_paste_description, |
791 |
getContextTypeId(), pattern, true); |
792 |
return getTemplateFromClipboard(clipBoard); |
793 |
} |
794 |
}; |
795 |
|
796 |
fCopyAction = new Action() { |
797 |
public void run() { |
798 |
if (!isSingleTemplateSelected()) |
799 |
return; |
800 |
Template[] templates = new Template[] { getSelectedTemplate() }; |
801 |
Clipboard clipBoard = new Clipboard(getShell().getDisplay()); |
802 |
clipBoard.setContents(new Object[] { templates }, new Transfer[] { TemplateTransfer |
803 |
.getInstance() }); |
804 |
} |
805 |
}; |
806 |
} |
807 |
|
808 |
/** |
809 |
* Fill the view menu |
810 |
* |
811 |
* @param actionBars |
812 |
*/ |
813 |
private void fillMenu(IActionBars actionBars) { |
814 |
IMenuManager menuManager = actionBars.getMenuManager(); |
815 |
|
816 |
if (fPreferencePageAction != null) { |
817 |
menuManager.add(fPreferencePageAction); |
818 |
menuManager.add(new Separator()); |
819 |
} |
820 |
|
821 |
menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
822 |
} |
823 |
|
824 |
/** |
825 |
* Fill the toolbar |
826 |
* |
827 |
* @param actionBars |
828 |
*/ |
829 |
private void fillToolbar(IActionBars actionBars) { |
830 |
IToolBarManager toolBarManager = actionBars.getToolBarManager(); |
831 |
toolBarManager.add(fInsertAction); |
832 |
toolBarManager.add(fAddAction); |
833 |
toolBarManager.add(fEditAction); |
834 |
toolBarManager.add(fRemoveAction); |
835 |
|
836 |
toolBarManager.add(new Separator()); |
837 |
|
838 |
toolBarManager.add(fLinkWithEditorAction); |
839 |
toolBarManager.add(fCollapseAllAction); |
840 |
} |
841 |
|
842 |
/** |
843 |
* Hookup the context menu |
844 |
*/ |
845 |
private void hookContextMenu() { |
846 |
MenuManager menuMgr = new MenuManager(POPUP_MENU_ID); |
847 |
menuMgr.setRemoveAllWhenShown(true); |
848 |
menuMgr.addMenuListener(new IMenuListener() { |
849 |
public void menuAboutToShow(IMenuManager manager) { |
850 |
fillContextMenu(manager); |
851 |
} |
852 |
}); |
853 |
fContextMenu = menuMgr.createContextMenu(fTreeViewer.getControl()); |
854 |
fTreeViewer.getControl().setMenu(fContextMenu); |
855 |
getSite().registerContextMenu(POPUP_MENU_ID, menuMgr, fTreeViewer); |
856 |
} |
857 |
|
858 |
/** |
859 |
* Fill the context menu items |
860 |
* |
861 |
* @param manager |
862 |
*/ |
863 |
private void fillContextMenu(IMenuManager manager) { |
864 |
manager.add(fInsertAction); |
865 |
manager.add(new Separator()); |
866 |
manager.add(fAddAction); |
867 |
manager.add(fEditAction); |
868 |
manager.add(fRemoveAction); |
869 |
manager.add(new Separator()); |
870 |
manager.add(fCopyAction); |
871 |
manager.add(fPasteAction); |
872 |
// Other plug-ins can contribute there actions here |
873 |
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
874 |
} |
875 |
|
876 |
/** |
877 |
* Create the tree to display templates |
878 |
*/ |
879 |
private void createTemplateTree() { |
880 |
Composite treeComposite = new Composite(fControl, SWT.NONE); |
881 |
GridData data = new GridData(GridData.FILL_BOTH); |
882 |
treeComposite.setLayoutData(data); |
883 |
|
884 |
TreeColumnLayout columnLayout = new TreeColumnLayout(); |
885 |
treeComposite.setLayout(columnLayout); |
886 |
fTemplatesTree = new Tree(treeComposite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI |
887 |
| SWT.FULL_SELECTION); |
888 |
fTemplatesTree.setHeaderVisible(true); |
889 |
fTemplatesTree.setLinesVisible(true); |
890 |
|
891 |
GC gc = new GC(getShell()); |
892 |
gc.setFont(JFaceResources.getDialogFont()); |
893 |
|
894 |
TreeColumn columnName = new TreeColumn(fTemplatesTree, SWT.NONE); |
895 |
columnName.setText(TemplatesPageMessages.TemplatesPage_column_name); |
896 |
int minWidth = fPreferenceStore.getInt(COLUMN_NAME_WIDTH_PREF_ID); |
897 |
if (minWidth == 0) |
898 |
minWidth = gc.stringExtent("XXXXXXXXXXXXXXX").x; //$NON-NLS-1$ |
899 |
columnLayout.setColumnData(columnName, new ColumnPixelData(minWidth, false)); |
900 |
columnName.addControlListener(new ControlListener() { |
901 |
public void controlMoved(ControlEvent e) { |
902 |
} |
903 |
|
904 |
public void controlResized(ControlEvent e) { |
905 |
fNameWidth = ((TreeColumn) e.getSource()).getWidth(); |
906 |
fPreferenceStore.setValue(COLUMN_NAME_WIDTH_PREF_ID, fNameWidth); |
907 |
} |
908 |
}); |
909 |
|
910 |
TreeColumn columnDescription = new TreeColumn(fTemplatesTree, SWT.NONE); |
911 |
columnDescription.setText(TemplatesPageMessages.TemplatesPage_column_description); |
912 |
minWidth = fPreferenceStore.getInt(COLUMN_DESCRIPTION_WIDTH_PREF_ID); |
913 |
if (minWidth == 0) |
914 |
minWidth = gc.stringExtent("XXXXXXXXXXXXXXXXXXXXXXXXX").x; //$NON-NLS-1$ |
915 |
columnLayout.setColumnData(columnDescription, new ColumnPixelData(minWidth, false)); |
916 |
columnDescription.addControlListener(new ControlListener() { |
917 |
public void controlMoved(ControlEvent e) { |
918 |
} |
919 |
|
920 |
public void controlResized(ControlEvent e) { |
921 |
fDescriptionWidth = ((TreeColumn) e.getSource()).getWidth(); |
922 |
fPreferenceStore.setValue(COLUMN_DESCRIPTION_WIDTH_PREF_ID, fDescriptionWidth); |
923 |
} |
924 |
}); |
925 |
|
926 |
gc.dispose(); |
927 |
|
928 |
createTreeViewer(); |
929 |
} |
930 |
|
931 |
/** |
932 |
* Create the tree viewer and setup the providers |
933 |
*/ |
934 |
private void createTreeViewer() { |
935 |
fTreeViewer = new TreeViewer(fTemplatesTree); |
936 |
fTreeViewer.setLabelProvider(new TemplateLabelProvider()); |
937 |
fTreeViewer.setContentProvider(new TemplatesContentProvider()); |
938 |
|
939 |
fTreeViewer.setComparator(new TemplateViewerComparator()); |
940 |
fTreeViewer.setInput(getTemplatePreferenceStore()); |
941 |
fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { |
942 |
public void doubleClick(DoubleClickEvent e) { |
943 |
updateSelectedItems(); |
944 |
insertTemplate(getSelectedTemplate(), null); |
945 |
} |
946 |
}); |
947 |
|
948 |
fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
949 |
public void selectionChanged(SelectionChangedEvent e) { |
950 |
updateSelectedItems(); |
951 |
updateButtons(); |
952 |
} |
953 |
}); |
954 |
fTreeViewer.expandAll(); |
955 |
} |
956 |
|
957 |
/** |
958 |
* Setup the pattern viewer |
959 |
* |
960 |
* @param parent |
961 |
*/ |
962 |
private void setupPatternViewer(Composite parent) { |
963 |
ViewForm viewForm = new ViewForm(parent, SWT.NONE); |
964 |
viewForm.setBorderVisible(false); |
965 |
CLabel previewLabel = new CLabel(viewForm, SWT.NONE); |
966 |
previewLabel.setText(TemplatesPageMessages.TemplatesPage_preview); |
967 |
previewLabel.setImage(TemplatesPageImages.getImage(TemplatesPageImages.IMG_OBJ_PREVIEW)); |
968 |
viewForm.setTopLeft(previewLabel); |
969 |
|
970 |
Viewer viewer = createPatternViewer(viewForm); |
971 |
viewForm.setContent(viewer.getControl()); |
972 |
viewForm.addControlListener(new ControlListener() { |
973 |
public void controlMoved(ControlEvent e) { |
974 |
} |
975 |
|
976 |
public void controlResized(ControlEvent e) { |
977 |
int[] weights = fControl.getWeights(); |
978 |
fSashSize = (int) (weights[0] * 100.0 / (weights[0] + weights[1])); |
979 |
fPreferenceStore.setValue(SASH_SIZE_PREF_ID, fSashSize); |
980 |
} |
981 |
}); |
982 |
} |
983 |
|
984 |
/** |
985 |
* Update the selected items. The templates are stored in |
986 |
* fSelectedTemplateList and the context type is stored in fSelectedType. |
987 |
* |
988 |
* If all selected templates do not belong to the same context type the type |
989 |
* selection is set to null. |
990 |
*/ |
991 |
private void updateSelectedItems() { |
992 |
IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); |
993 |
|
994 |
fSelectedTemplateList.clear(); |
995 |
fSelectedType = null; |
996 |
|
997 |
if (selection.size() == 1) { |
998 |
Object item = selection.getFirstElement(); |
999 |
if (item instanceof TemplateContextType) |
1000 |
fSelectedType = (TemplateContextType) item; |
1001 |
else |
1002 |
fSelectedTemplateList.add(item); |
1003 |
} else if (selection.size() > 1) { |
1004 |
for (Iterator iterator = selection.iterator(); iterator.hasNext();) { |
1005 |
Object item = iterator.next(); |
1006 |
if (item instanceof TemplateContextType) { |
1007 |
fSelectedTemplateList.clear(); |
1008 |
break; |
1009 |
} |
1010 |
fSelectedTemplateList.add(item); |
1011 |
} |
1012 |
} |
1013 |
if (!fSelectedTemplateList.isEmpty()) { |
1014 |
String contextTypeId = ((TemplatePersistenceData) fSelectedTemplateList.get(0)) |
1015 |
.getTemplate().getContextTypeId(); |
1016 |
fSelectedType = getContextTypeRegistry().getContextType(contextTypeId); |
1017 |
for (Iterator iterator = fSelectedTemplateList.iterator(); iterator.hasNext();) { |
1018 |
TemplatePersistenceData template = (TemplatePersistenceData) iterator.next(); |
1019 |
if (!contextTypeId.equals(template.getTemplate().getContextTypeId())) { |
1020 |
fSelectedType = null; |
1021 |
break; |
1022 |
} |
1023 |
} |
1024 |
} |
1025 |
updatePatternViewer(getSelectedTemplate()); |
1026 |
} |
1027 |
|
1028 |
/** |
1029 |
* Is a single template selected. |
1030 |
* |
1031 |
* @return true if a single template is selected |
1032 |
*/ |
1033 |
private boolean isSingleTemplateSelected() { |
1034 |
return fSelectedTemplateList.size() == 1; |
1035 |
} |
1036 |
|
1037 |
/** |
1038 |
* Get the selected template |
1039 |
* |
1040 |
* @return the template or null if no/>1 templates are selected. |
1041 |
*/ |
1042 |
private Template getSelectedTemplate() { |
1043 |
if (isSingleTemplateSelected()) |
1044 |
return ((TemplatePersistenceData) fSelectedTemplateList.get(0)).getTemplate(); |
1045 |
return null; |
1046 |
} |
1047 |
|
1048 |
/** |
1049 |
* Get the persistence data element of the selected template |
1050 |
* |
1051 |
* @return template data or null if no/>1 templates are selected |
1052 |
*/ |
1053 |
private TemplatePersistenceData getSelectedTemplateData() { |
1054 |
if (isSingleTemplateSelected()) |
1055 |
return ((TemplatePersistenceData) fSelectedTemplateList.get(0)); |
1056 |
return null; |
1057 |
} |
1058 |
|
1059 |
/** |
1060 |
* Show the preference page. The action is enabled only if |
1061 |
* getPreferencePageId() returns non-null. |
1062 |
*/ |
1063 |
private void showPreferencePage() { |
1064 |
PreferencesUtil.createPreferenceDialogOn(getShell(), getPreferencePageId(), null, null) |
1065 |
.open(); |
1066 |
} |
1067 |
|
1068 |
/** |
1069 |
* Update the state of the buttons |
1070 |
*/ |
1071 |
private void updateButtons() { |
1072 |
fCopyAction.setEnabled(isSingleTemplateSelected()); |
1073 |
fInsertAction.setEnabled(isSingleTemplateSelected()); |
1074 |
fEditAction.setEnabled(isSingleTemplateSelected()); |
1075 |
fRemoveAction.setEnabled((fSelectedTemplateList.size() != 0)); |
1076 |
} |
1077 |
|
1078 |
/** |
1079 |
* Add a template |
1080 |
*/ |
1081 |
private void addTemplate() { |
1082 |
String id = getContextTypeId(); |
1083 |
if (id != null) { |
1084 |
Template template = new Template("", "", id, "", true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
1085 |
|
1086 |
addTemplate(template); |
1087 |
} |
1088 |
} |
1089 |
|
1090 |
/** |
1091 |
* Get contextType of the selected template |
1092 |
* |
1093 |
* @return contextType of the selected template or the first from the |
1094 |
* registry if no templates are selected |
1095 |
*/ |
1096 |
private String getContextTypeId() { |
1097 |
if (fSelectedType != null) |
1098 |
return fSelectedType.getId(); |
1099 |
Iterator it = getContextTypeRegistry().contextTypes(); |
1100 |
if (it.hasNext()) |
1101 |
return ((TemplateContextType) it.next()).getId(); |
1102 |
return null; |
1103 |
} |
1104 |
|
1105 |
/** |
1106 |
* Add a template. The dialog is filled with the values from the given |
1107 |
* template. |
1108 |
* |
1109 |
* @param template |
1110 |
*/ |
1111 |
private void addTemplate(Template template) { |
1112 |
Template newTemplate; |
1113 |
newTemplate = editTemplate(template, false, true); |
1114 |
if (newTemplate != null) { |
1115 |
TemplatePersistenceData data = new TemplatePersistenceData(newTemplate, true); |
1116 |
getTemplateStore().add(data); |
1117 |
saveTemplateStore(); |
1118 |
fSelectedTemplateList.clear(); |
1119 |
fSelectedTemplateList.add(data); |
1120 |
changeSelection(); |
1121 |
} |
1122 |
} |
1123 |
|
1124 |
/** |
1125 |
* Save the template store |
1126 |
*/ |
1127 |
private void saveTemplateStore() { |
1128 |
try { |
1129 |
getTemplateStore().save(); |
1130 |
} catch (IOException e) { |
1131 |
e.printStackTrace(); |
1132 |
MessageDialog.openError(getShell(), |
1133 |
TemplatesPageMessages.TemplatesPage_save_error_message, e.getMessage()); |
1134 |
} |
1135 |
} |
1136 |
|
1137 |
/** |
1138 |
* Change selection |
1139 |
*/ |
1140 |
private void changeSelection() { |
1141 |
fTreeViewer.refresh(); |
1142 |
if (isSingleTemplateSelected()) |
1143 |
fTreeViewer.setSelection(new StructuredSelection(fSelectedTemplateList.get(0)), true); |
1144 |
else |
1145 |
fTreeViewer.setSelection(new StructuredSelection()); |
1146 |
updateSelectedItems(); |
1147 |
} |
1148 |
|
1149 |
/** |
1150 |
* Edit the selected template |
1151 |
*/ |
1152 |
private void editTemplate() { |
1153 |
Template oldTemplate = getSelectedTemplate(); |
1154 |
Template newTemplate = editTemplate(new Template(oldTemplate), true, true); |
1155 |
if (newTemplate != null) { |
1156 |
if (!newTemplate.getName().equals(oldTemplate.getName()) |
1157 |
&& MessageDialog.openQuestion(getShell(), |
1158 |
TemplatesPageMessages.TemplatesPage_question_create_new_title, |
1159 |
TemplatesPageMessages.TemplatesPage_question_create_new_message)) { |
1160 |
fSelectedTemplateList.clear(); |
1161 |
TemplatePersistenceData templateData = new TemplatePersistenceData(newTemplate, |
1162 |
true); |
1163 |
fSelectedTemplateList.add(templateData); |
1164 |
getTemplateStore().add(templateData); |
1165 |
} else { |
1166 |
((TemplatePersistenceData) fSelectedTemplateList.get(0)).setTemplate(newTemplate); |
1167 |
} |
1168 |
changeSelection(); |
1169 |
} |
1170 |
saveTemplateStore(); |
1171 |
} |
1172 |
|
1173 |
/** |
1174 |
* Move the selected template from one context to another |
1175 |
* |
1176 |
* @param modifiedTemplate |
1177 |
*/ |
1178 |
private void moveTemplate(Template modifiedTemplate) { |
1179 |
Template newTemplate = editTemplate(modifiedTemplate, true, true); |
1180 |
if (newTemplate != null) { |
1181 |
fDnDTemplate.setTemplate(newTemplate); |
1182 |
changeSelection(); |
1183 |
} |
1184 |
saveTemplateStore(); |
1185 |
} |
1186 |
|
1187 |
/** |
1188 |
* Remove one or more selected templates |
1189 |
*/ |
1190 |
private void removeTemplate() { |
1191 |
String suffix = fSelectedTemplateList.size() == 1 ? "" : "s"; //$NON-NLS-1$ //$NON-NLS-2$ |
1192 |
String title = NLSUtility.format(TemplatesPageMessages.TemplatesPage_remove_title, |
1193 |
new Object[] { suffix }); |
1194 |
String message = NLSUtility.format(TemplatesPageMessages.TemplatesPage_remove_message, |
1195 |
new Object[] { suffix }); |
1196 |
if (!MessageDialog.openQuestion(getShell(), title, message)) |
1197 |
return; |
1198 |
for (Iterator iterator = fSelectedTemplateList.iterator(); iterator.hasNext();) { |
1199 |
TemplatePersistenceData data = (TemplatePersistenceData) iterator.next(); |
1200 |
getTemplateStore().delete(data); |
1201 |
} |
1202 |
saveTemplateStore(); |
1203 |
fSelectedTemplateList.clear(); |
1204 |
changeSelection(); |
1205 |
} |
1206 |
|
1207 |
/** |
1208 |
* Initialize drag and drop the template items |
1209 |
*/ |
1210 |
private void initializeDND() { |
1211 |
DragSourceAdapter dragListener = new DragSourceAdapter() { |
1212 |
/* |
1213 |
* (non-Javadoc) |
1214 |
* |
1215 |
* @see org.eclipse.swt.dnd.DragSourceAdapter#dragStart(org.eclipse.swt.dnd.DragSourceEvent) |
1216 |
*/ |
1217 |
public void dragStart(DragSourceEvent event) { |
1218 |
if (!isSingleTemplateSelected()) { |
1219 |
event.doit = false; |
1220 |
} else { |
1221 |
fDnDTemplate = getSelectedTemplateData(); |
1222 |
} |
1223 |
} |
1224 |
|
1225 |
/* |
1226 |
* (non-Javadoc) |
1227 |
* |
1228 |
* @see org.eclipse.swt.dnd.DragSourceAdapter#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) |
1229 |
*/ |
1230 |
public void dragSetData(DragSourceEvent event) { |
1231 |
if (isSingleTemplateSelected() |
1232 |
&& TemplateTransfer.getInstance().isSupportedType(event.dataType)) { |
1233 |
event.data = new Template[] { getSelectedTemplate() }; |
1234 |
} |
1235 |
} |
1236 |
}; |
1237 |
fTreeViewer.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] { TemplateTransfer |
1238 |
.getInstance() }, dragListener); |
1239 |
DropTargetAdapter dropListener = new DropTargetAdapter() { |
1240 |
Transfer[] transfers = getTransfers(); |
1241 |
TemplateTransfer templateTransfer = TemplateTransfer.getInstance(); |
1242 |
|
1243 |
/* |
1244 |
* (non-Javadoc) |
1245 |
* |
1246 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) |
1247 |
*/ |
1248 |
public void dragEnter(DropTargetEvent event) { |
1249 |
if (event.detail == DND.DROP_DEFAULT) |
1250 |
event.detail = DND.DROP_COPY; |
1251 |
} |
1252 |
|
1253 |
/* |
1254 |
* (non-Javadoc) |
1255 |
* |
1256 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) |
1257 |
*/ |
1258 |
public void dragOperationChanged(DropTargetEvent event) { |
1259 |
if (event.detail == DND.DROP_DEFAULT) |
1260 |
event.detail = DND.DROP_COPY; |
1261 |
} |
1262 |
|
1263 |
/* |
1264 |
* (non-Javadoc) |
1265 |
* |
1266 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) |
1267 |
*/ |
1268 |
public void dragOver(DropTargetEvent event) { |
1269 |
event.feedback |= DND.FEEDBACK_SCROLL; |
1270 |
if (event.item == null) { |
1271 |
event.detail = DND.DROP_NONE; |
1272 |
return; |
1273 |
} |
1274 |
int index = 0; |
1275 |
boolean isTemplateTransfer = false; |
1276 |
while (index < event.dataTypes.length) { |
1277 |
int i = 0; |
1278 |
while (i < transfers.length) { |
1279 |
if (transfers[i].isSupportedType(event.dataTypes[index])) |
1280 |
break; |
1281 |
i++; |
1282 |
} |
1283 |
if (i < transfers.length) |
1284 |
break; |
1285 |
if (templateTransfer.isSupportedType(event.dataTypes[index])) { |
1286 |
isTemplateTransfer = true; |
1287 |
break; |
1288 |
} |
1289 |
index++; |
1290 |
} |
1291 |
if (index < event.dataTypes.length) { |
1292 |
event.currentDataType = event.dataTypes[index]; |
1293 |
if (event.detail == DND.DROP_DEFAULT || !isTemplateTransfer) |
1294 |
event.detail = DND.DROP_COPY; |
1295 |
return; |
1296 |
} |
1297 |
} |
1298 |
|
1299 |
/* |
1300 |
* (non-Javadoc) |
1301 |
* |
1302 |
* @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent) |
1303 |
*/ |
1304 |
public void drop(DropTargetEvent event) { |
1305 |
if (event.item == null) |
1306 |
return; |
1307 |
Object object = ((TreeItem) event.item).getData(); |
1308 |
String contextId; |
1309 |
if (object instanceof TemplateContextType) |
1310 |
contextId = ((TemplateContextType) object).getId(); |
1311 |
else |
1312 |
contextId = ((TemplatePersistenceData) object).getTemplate().getContextTypeId(); |
1313 |
for (int i = 0; i < transfers.length; i++) { |
1314 |
if (transfers[i].isSupportedType(event.currentDataType)) { |
1315 |
String text = getTemplateDataFromDrop(transfers[i], event.data); |
1316 |
final Template template = new Template(createTemplateName(), |
1317 |
TemplatesPageMessages.TemplatesPage_paste_description, |
1318 |
contextId, text, true); |
1319 |
getShell().getDisplay().asyncExec(new Runnable() { |
1320 |
public void run() { |
1321 |
addTemplate(template); |
1322 |
} |
1323 |
}); |
1324 |
return; |
1325 |
} |
1326 |
} |
1327 |
if (templateTransfer.isSupportedType(event.currentDataType)) { |
1328 |
Template[] templates = (Template[]) event.data; |
1329 |
Template t = templates[0]; |
1330 |
final Template template = new Template(t.getName(), t.getDescription(), |
1331 |
contextId, t.getPattern(), true); |
1332 |
final int dropType = event.detail; |
1333 |
getShell().getDisplay().asyncExec(new Runnable() { |
1334 |
public void run() { |
1335 |
if (dropType == DND.DROP_COPY) |
1336 |
addTemplate(template); |
1337 |
else |
1338 |
moveTemplate(template); |
1339 |
} |
1340 |
}); |
1341 |
} |
1342 |
} |
1343 |
}; |
1344 |
Transfer[] transfers = new Transfer[getTransfers().length + 1]; |
1345 |
System.arraycopy(getTransfers(), 0, transfers, 0, getTransfers().length); |
1346 |
transfers[getTransfers().length] = TemplateTransfer.getInstance(); |
1347 |
fTreeViewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, transfers, dropListener); |
1348 |
} |
1349 |
|
1350 |
/** |
1351 |
* Create a template name |
1352 |
* |
1353 |
* @return a new template name |
1354 |
*/ |
1355 |
private String createTemplateName() { |
1356 |
for (int i = 1; i < Integer.MAX_VALUE; i++) { |
1357 |
String name = TemplatesPageMessages.TemplatesPage_snippet + i; |
1358 |
if (getTemplateStore().findTemplate(name) == null) |
1359 |
return name; |
1360 |
} |
1361 |
return null; |
1362 |
} |
1363 |
|
1364 |
/** |
1365 |
* Refresh the template tree contents |
1366 |
*/ |
1367 |
private void refresh() { |
1368 |
fTreeViewer.refresh(); |
1369 |
fTreeViewer.expandAll(); |
1370 |
} |
1371 |
} |