### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.ui Index: ui/org/eclipse/jdt/internal/ui/javaeditor/ClipboardOperationAction.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/ClipboardOperationAction.java,v retrieving revision 1.25 diff -u -r1.25 ClipboardOperationAction.java --- ui/org/eclipse/jdt/internal/ui/javaeditor/ClipboardOperationAction.java 31 Aug 2006 08:52:18 -0000 1.25 +++ ui/org/eclipse/jdt/internal/ui/javaeditor/ClipboardOperationAction.java 6 Aug 2007 07:21:44 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Dakshinamurthy Karra - TemplatesPage support (bug 69581) *******************************************************************************/ package org.eclipse.jdt.internal.ui.javaeditor; @@ -41,12 +42,16 @@ import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.templates.Template; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; import org.eclipse.ui.texteditor.TextEditorAction; +import org.eclipse.ui.texteditor.templates.TemplateTransfer; + +import org.eclipse.ui.views.templates.ITemplatesPage; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; @@ -66,6 +71,7 @@ import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jdt.internal.ui.JavaPlugin; +import org.eclipse.jdt.internal.ui.preferences.JavaTemplatesPage; /** @@ -489,7 +495,12 @@ } } } else { - fOperationTarget.doOperation(fOperationCode); + Template[] templates= (Template[]) clipboard.getContents(TemplateTransfer.getInstance()); + if (templates != null) { + JavaTemplatesPage page= (JavaTemplatesPage) editor.getAdapter(ITemplatesPage.class); + page.insertTemplate(templates[0]); + } else + fOperationTarget.doOperation(fOperationCode); } } Index: ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java,v retrieving revision 1.430 diff -u -r1.430 JavaEditor.java --- ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java 25 Jul 2007 15:56:17 -0000 1.430 +++ ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java 6 Aug 2007 07:22:31 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Dakshinamurthy Karra - TemplatesPage support (bug 69581) *******************************************************************************/ package org.eclipse.jdt.internal.ui.javaeditor; @@ -141,6 +142,7 @@ import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.eclipse.ui.views.templates.ITemplatesPage; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; @@ -194,6 +196,7 @@ import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectNextAction; import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectPreviousAction; import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectionAction; +import org.eclipse.jdt.internal.ui.preferences.JavaTemplatesPage; import org.eclipse.jdt.internal.ui.search.BreakContinueTargetFinder; import org.eclipse.jdt.internal.ui.search.ExceptionOccurrencesFinder; import org.eclipse.jdt.internal.ui.search.ImplementOccurrencesFinder; @@ -1333,6 +1336,12 @@ protected JavaOutlinePage fOutlinePage; /** Outliner context menu Id */ protected String fOutlinerContextMenuId; + /** The templates page + * + * @since 3.4 + */ + private JavaTemplatesPage fTemplatesPage; + /** * The editor selection changed listener. * @@ -1778,6 +1787,10 @@ return fOutlinePage; } + if (required.equals(ITemplatesPage.class)) { + return getTemplatesPage(); + } + if (IEncodingSupport.class.equals(required)) return fEncodingSupport; @@ -1833,6 +1846,17 @@ } /** + * @since 3.4 + */ + private JavaTemplatesPage getTemplatesPage() { + if (fTemplatesPage == null) { + fTemplatesPage= new JavaTemplatesPage(this); + + } + return fTemplatesPage; + } + + /** * React to changed selection. * * @since 3.0 @@ -3225,6 +3249,8 @@ protected void handleCursorPositionChanged() { super.handleCursorPositionChanged(); fCachedSelectedRange= getViewer().getSelectedRange(); + if (fTemplatesPage != null) + fTemplatesPage.cursorPositionChanged(); } private static boolean isBracket(char character) { Index: ui/org/eclipse/jdt/internal/ui/preferences/JavaTemplatesPage.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/JavaTemplatesPage.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/JavaTemplatesPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/JavaTemplatesPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,335 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.ui.preferences; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.window.Window; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.ITextViewerExtension5; +import org.eclipse.jface.text.IUndoManager; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.TextUtilities; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.templates.ContextTypeRegistry; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateContextType; + +import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.ui.texteditor.templates.TemplatesPage; + +import org.eclipse.ui.views.templates.ITemplatesPage; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.JavaCore; + +import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContext; +import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContextType; +import org.eclipse.jdt.internal.corext.template.java.JavaContextType; +import org.eclipse.jdt.internal.corext.template.java.JavaDocContextType; + +import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jdt.ui.text.IJavaPartitions; +import org.eclipse.jdt.ui.text.JavaTextTools; + +import org.eclipse.jdt.internal.ui.JavaPlugin; +import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; +import org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer; +import org.eclipse.jdt.internal.ui.text.SimpleJavaSourceViewerConfiguration; +import org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateProposal; +import org.eclipse.jdt.internal.ui.text.template.preferences.TemplateVariableProcessor; + +/** + * A TemplatesPage implementation for JavaEditor + * + * @since 3.4 + */ +public class JavaTemplatesPage extends TemplatesPage implements ITemplatesPage { + + private static final ContextTypeRegistry TEMPLATE_CONTEXT_REGISTRY= JavaPlugin.getDefault().getTemplateContextRegistry(); + private TemplateVariableProcessor fTemplateProcessor; + private final JavaEditor fEditor; + private IDocument fDocument; + private String fJavaDocId; + private String fJavaId; + private String fCurrentId; + private int fCachedOffset; + private boolean fCachedResult; + + /** + * @param javaEditor + */ + public JavaTemplatesPage(JavaEditor javaEditor) { + super(JavaPlugin.getDefault().getTemplateStore(), JavaPlugin.getDefault().getPreferenceStore(), TEMPLATE_CONTEXT_REGISTRY); + fEditor= javaEditor; + fJavaDocId= new JavaDocContextType().getId(); + fJavaId= new JavaContextType().getId(); + fTemplateProcessor= new TemplateVariableProcessor(); + fDocument= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); + cursorPositionChanged(); + setupEditorDropTarget(fEditor.getSite(), fEditor.getViewer().getTextWidget()); + } + + public void dispose() { + super.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#editTemplate(org.eclipse.jface.text.templates.Template, boolean, boolean) + */ + protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) { + EditTemplateDialog dialog= new EditTemplateDialog(getShell(), template, edit, isNameModifiable, TEMPLATE_CONTEXT_REGISTRY); + if (dialog.open() == Window.OK) { + return dialog.getTemplate(); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#createViewer(org.eclipse.swt.widgets.Composite) + */ + protected SourceViewer createViewer(Composite parent) { + IDocument document= new Document(); + JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools(); + tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING); + IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore(); + SourceViewer viewer= new JavaSourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store); + SimpleJavaSourceViewerConfiguration configuration= new SimpleJavaSourceViewerConfiguration(tools.getColorManager(), store, null, IJavaPartitions.JAVA_PARTITIONING, false); + viewer.configure(configuration); + viewer.setEditable(false); + viewer.setDocument(document); + + Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT); + viewer.getTextWidget().setFont(font); + new JavaSourcePreviewerUpdater(viewer, configuration, store); + + Control control= viewer.getControl(); + GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL); + control.setLayoutData(data); + + return viewer; + } + + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#updateViewerInput(org.eclipse.jface.text.templates.Template) + */ + protected void updateViewerInput(Template template) { + SourceViewer viewer= getViewer(); + + String contextId= template.getContextTypeId(); + TemplateContextType type= TEMPLATE_CONTEXT_REGISTRY.getContextType(contextId); + fTemplateProcessor.setContextType(type); + + IDocument doc= viewer.getDocument(); + + String start= null; + if ("javadoc".equals(contextId)) { //$NON-NLS-1$ + start= "/**" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$ + } else + start= ""; //$NON-NLS-1$ + + doc.set(start + template.getPattern()); + int startLen= start.length(); + viewer.setDocument(doc, startLen, doc.getLength() - startLen); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#getPreferencePageId() + */ + protected String getPreferencePageId() { + return "org.eclipse.jdt.ui.preferences.JavaTemplatePreferencePage"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#insertTemplate(org.eclipse.jface.text.templates.Template) + */ + public void insertTemplate(Template template) { + if (!fEditor.isEditorInputModifiable()) + return; + TemplateContextType type= TEMPLATE_CONTEXT_REGISTRY.getContextType(template.getContextTypeId()); + if (type == null) + return; + ISourceViewer contextViewer= fEditor.getViewer(); + ITextSelection textSelection= (ITextSelection) contextViewer.getSelectionProvider().getSelection(); + IDocument document= contextViewer.getDocument(); + IUndoManager undoManager= ((JavaSourceViewer)fEditor.getViewer()).getUndoManager(); + undoManager.beginCompoundChange(); + + /* + * The Editor checks whether a completion for a word exists before it allows for the template to be + * applied. We pickup the current text at the selection position and replace it with the first char + * of the template name for this to succeed. + * We don't need to go through this, if the editors simply support applyTemplate(Template). + */ + String savedText; + try { + savedText= document.get(textSelection.getOffset(), textSelection.getLength()); + if (savedText.length() == 0) { + String prefix= getIdentifierPart(textSelection.getOffset()); + if (prefix.length() > 0 && !template.getName().startsWith(prefix.toString())) { + return ; + } + if (prefix.length() > 0) { + contextViewer.setSelectedRange(textSelection.getOffset() - prefix.length(), prefix.length()); + textSelection = (ITextSelection) contextViewer.getSelectionProvider().getSelection(); + } + } + document.replace(textSelection.getOffset(), textSelection.getLength(), template.getName().substring(0, 1)); + } catch (BadLocationException e) { + undoManager.endCompoundChange(); + e.printStackTrace(); + return; + } + Position position= new Position(textSelection.getOffset() + 1, 0); + Region region= new Region(textSelection.getOffset() + 1, 0); + contextViewer.getSelectionProvider().setSelection(new TextSelection(textSelection.getOffset(), 1)); + ICompilationUnit compilationUnit= JavaCore.createCompilationUnitFrom(((FileEditorInput) fEditor.getEditorInput()).getFile()); + + CompilationUnitContext context= ((CompilationUnitContextType) type).createContext(document, position, compilationUnit); + context.setVariable("selection", savedText); //$NON-NLS-1$ + if (context.getKey().length() == 0) { + try { + document.replace(textSelection.getOffset(), 1, savedText); + } catch (BadLocationException e) { + e.printStackTrace(); + undoManager.endCompoundChange(); + return; + } + } + TemplateProposal proposal= new TemplateProposal(template, context, region, null); + fEditor.getSite().getPage().activate(fEditor); + proposal.apply(fEditor.getViewer(), ' ', 0, region.getOffset()); + undoManager.endCompoundChange(); + } + + /** + * Invoked by the editor whenever the caret position is updated + */ + public void cursorPositionChanged() { + Point selectedRange= fEditor.getViewer().getSelectedRange(); + int cursor= selectedRange.x + selectedRange.y; + String partition; + try { + partition= TextUtilities.getContentType(fDocument, IJavaPartitions.JAVA_PARTITIONING, cursor, true); + } catch (BadLocationException e) { + return; + } + String id= fJavaId; + if (partition.equals(IJavaPartitions.JAVA_DOC)) + id= fJavaDocId; + if (!id.equals(fCurrentId)) { + fCurrentId= id; + contextTypeChanged(new String[] { id }); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#isValidTempalteForPosition(org.eclipse.jface.text.templates.Template, int, int) + */ + protected boolean isValidTempalteForPosition(Template template, int x, int y) { + StyledText textWidget= fEditor.getViewer().getTextWidget(); + String partition; + try { + int offset= getOffset(textWidget, textWidget.toControl(x, y)); + if (fCachedOffset == offset) + return fCachedResult ; + fCachedOffset = offset ; + partition= TextUtilities.getContentType(fDocument, IJavaPartitions.JAVA_PARTITIONING, offset, true); + String id= fJavaId; + if (partition.equals(IJavaPartitions.JAVA_DOC)) + id= fJavaDocId; + if (isValidTemplate(template, offset) && id.equals(template.getContextTypeId())) + return fCachedResult = true ; + } catch (BadLocationException e) { + } + return fCachedResult = false ; + } + + /** + * Get the document relative offset from the textwidget relative point + * + * @param textWidget + * @param point + * @return offset + * @throws BadLocationException + */ + private int getOffset(StyledText textWidget, Point point) throws BadLocationException { + ITextViewerExtension5 ext = (ITextViewerExtension5) fEditor.getViewer(); + try { + return ext.widgetOffset2ModelOffset(textWidget.getOffsetAtLocation(point)); + } catch (IllegalArgumentException e) { + int docLineIndex= ext.widgetLine2ModelLine(textWidget.getLineIndex(point.y)); + return fDocument.getLineOffset(docLineIndex) + fDocument.getLineLength(docLineIndex); + } + } + + /** + * Check whether the template is valid for the given offset + * + * @param template + * @param offset + * @return true if the template is valid + * @throws BadLocationException + */ + private boolean isValidTemplate(Template template, int offset) throws BadLocationException { + String prefix= getIdentifierPart(offset); + if (prefix.length() > 0 && template.getName().startsWith(prefix.toString())) + return true ; + int line= fDocument.getLineOfOffset(offset); + if (offset == fDocument.getLineOffset(line)) + return true ; + char ch= fDocument.getChar(offset - 1); + if (Character.isWhitespace(ch)) + return true ; + return false ; + } + + /** + * Get the java identifier terminated at the given offset + * + * @param offset + * @return the identifier part + * @throws BadLocationException + */ + private String getIdentifierPart(int offset) throws BadLocationException { + int end= offset; + int start= end; + while (--start >= 0) { + if (!Character.isJavaIdentifierPart(fDocument.getChar(start))) + break; + } + start++; + return fDocument.get(start, end - start); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#isEditorModifiable() + */ + protected boolean isEditorModifiable() { + return fEditor.isEditable(); + } +} #P org.eclipse.ant.ui Index: Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties,v retrieving revision 1.22 diff -u -r1.22 AntEditorMessages.properties --- Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties 27 Mar 2006 19:08:01 -0000 1.22 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties 6 Aug 2007 07:22:59 -0000 @@ -8,6 +8,7 @@ # Contributors: # IBM Corporation - initial API and implementation # John-Mason P. Shackelford - bug 40255 +# Dakshinamurthy Karra - TemplatesPage support ############################################################################### ContentAssistProposal.label=Content &Assist@Ctrl+Space @@ -41,3 +42,8 @@ AntAnnotationHover.multipleMarkersAtThisLine=Multiple markers at this line AntEditor.3=Current text selection does not resolve to an Ant reference + +Editor.Paste.label=&Paste +Editor.Paste.tooltip=Paste +Editor.Paste.image= +Editor.Paste.description=Paste Index: Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java,v retrieving revision 1.109 diff -u -r1.109 AntEditor.java --- Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java 20 Mar 2007 22:09:34 -0000 1.109 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java 6 Aug 2007 07:22:44 -0000 @@ -12,6 +12,7 @@ * IBM Corporation - bug fixes * John-Mason P. Shackelford - bug 40255 * Mark Melvin - bug 93378 + * Dakshinamurthy Karra - TemplatesView support *******************************************************************************/ package org.eclipse.ant.internal.ui.editor; @@ -34,6 +35,7 @@ import org.eclipse.ant.internal.ui.editor.actions.RunToLineAdapter; import org.eclipse.ant.internal.ui.editor.actions.ToggleLineBreakpointAction; import org.eclipse.ant.internal.ui.editor.outline.AntEditorContentOutlinePage; +import org.eclipse.ant.internal.ui.editor.templates.AntTemplatesPage; import org.eclipse.ant.internal.ui.editor.text.AntEditorDocumentProvider; import org.eclipse.ant.internal.ui.editor.text.AntFoldingStructureProvider; import org.eclipse.ant.internal.ui.editor.text.IReconcilingParticipant; @@ -71,6 +73,7 @@ import org.eclipse.jface.text.ISelectionValidator; import org.eclipse.jface.text.ISynchronizable; import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Position; @@ -85,6 +88,7 @@ import org.eclipse.jface.text.source.projection.IProjectionListener; import org.eclipse.jface.text.source.projection.ProjectionSupport; import org.eclipse.jface.text.source.projection.ProjectionViewer; +import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.IPostSelectionProvider; import org.eclipse.jface.viewers.ISelection; @@ -93,6 +97,7 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.graphics.Image; @@ -112,16 +117,53 @@ import org.eclipse.ui.texteditor.ContentAssistAction; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.IEditorStatusLine; +import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; +import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; +import org.eclipse.ui.texteditor.TextEditorAction; import org.eclipse.ui.texteditor.TextOperationAction; +import org.eclipse.ui.texteditor.templates.TemplateTransfer; import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.eclipse.ui.views.templates.ITemplatesPage; /** * The actual editor implementation for Eclipse's Ant integration. */ public class AntEditor extends TextEditor implements IReconcilingParticipant, IProjectionListener { + + /** + * Clipboard paste operation support for templates + * + * @since 3.4 + */ + class ClipboardPasteOperation extends TextEditorAction { + private ITextOperationTarget fOperationTarget; + private int fOperationCode = -1; + + protected ClipboardPasteOperation(ResourceBundle bundle, String prefix, ITextEditor editor, + int style) { + super(bundle, prefix, editor, style); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + ITextEditor editor = getTextEditor(); + Clipboard clipboard = new Clipboard(getSite().getShell().getDisplay()); + Template[] templates = (Template[]) clipboard.getContents(TemplateTransfer + .getInstance()); + if (templates != null) { + AntTemplatesPage page = (AntTemplatesPage) editor.getAdapter(ITemplatesPage.class); + page.insertTemplate(templates[0]); + } else + fOperationTarget.doOperation(fOperationCode); + } + } + + /** * Updates the Ant outline page selection and this editor's range indicator. * @@ -461,7 +503,12 @@ * The page that shows the outline. */ protected AntEditorContentOutlinePage fOutlinePage; - + /** + * The templates page + * + * @since 3.4 + */ + protected AntTemplatesPage fTemplatesPage; private boolean fInitialReconcile= true; @@ -538,6 +585,12 @@ action= new RenameInFileAction(this); action.setActionDefinitionId("org.eclipse.ant.ui.renameInFile"); //$NON-NLS-1$ setAction("renameInFile", action); //$NON-NLS-1$ + + // Override the TextEditor paste operation to support templates + action = new ClipboardPasteOperation(bundle, + "Editor.Paste.", this, ITextOperationTarget.PASTE); //$NON-NLS-1$ + action.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE); + setAction(ITextEditorActionConstants.PASTE, action); } /* @@ -564,6 +617,10 @@ return getOutlinePage(); } + if (key.equals(ITemplatesPage.class)) { + return getTemplatesPage(); + } + if (fProjectionSupport != null) { Object adapter= fProjectionSupport.getAdapter(getSourceViewer(), key); if (adapter != null) { @@ -599,6 +656,29 @@ return fOutlinePage; } + /** + * @since 3.4 + * + * @return the templatespage for this editor + */ + private AntTemplatesPage getTemplatesPage() { + if (fTemplatesPage == null) { + fTemplatesPage = new AntTemplatesPage(this); + } + return fTemplatesPage; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleCursorPositionChanged() + * + * @since 3.4 + */ + protected void handleCursorPositionChanged() { + super.handleCursorPositionChanged(); + if (fTemplatesPage != null) + fTemplatesPage.cursorPositionChanged(); + } + private void doSelectionChanged(SelectionChangedEvent selectionChangedEvent) { IStructuredSelection selection= (IStructuredSelection)selectionChangedEvent.getSelection(); Index: Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplatesPage.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplatesPage.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplatesPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplatesPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - Initial API and implementation + *******************************************************************************/ +package org.eclipse.ant.internal.ui.editor.templates; + +import org.eclipse.ant.internal.ui.AntUIPlugin; +import org.eclipse.ant.internal.ui.editor.AntEditor; +import org.eclipse.ant.internal.ui.editor.formatter.FormattingPreferences; +import org.eclipse.ant.internal.ui.editor.formatter.XmlFormatter; +import org.eclipse.ant.internal.ui.editor.text.AntDocumentSetupParticipant; +import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.jface.text.templates.ContextTypeRegistry; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.texteditor.templates.TemplatesPage; +import org.eclipse.ui.views.templates.ITemplatesPage; + +/** + * An implementation of TemplatesPage for AntEditor + * + * @see TemplatesPage + * @since 3.4 + */ +public class AntTemplatesPage extends TemplatesPage implements ITemplatesPage { + + private static final ContextTypeRegistry CONTEXT_TYPE_REGISTRY = AntTemplateAccess + .getDefault().getContextTypeRegistry(); + private FormattingPreferences fFormattingPreferences = new FormattingPreferences(); + private final AntEditor fEditor; + private String fCurrentId; + + /** + * Constructor + * + * @param editor + */ + public AntTemplatesPage(AntEditor editor) { + super(AntTemplateAccess.getDefault().getTemplateStore(), + AntUIPlugin.getDefault().getPreferenceStore(), CONTEXT_TYPE_REGISTRY); + fEditor = editor; + cursorPositionChanged(); + setupEditorDropTarget(fEditor.getSite(), fEditor.getViewer() + .getTextWidget()); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createViewer(org.eclipse.swt.widgets.Composite) + */ + protected SourceViewer createViewer(Composite parent) { + SourceViewer viewer = new SourceViewer(parent, null, SWT.BORDER + | SWT.V_SCROLL | SWT.H_SCROLL); + + SourceViewerConfiguration configuration = new AntTemplateViewerConfiguration(); + IDocument document = new Document(); + new AntDocumentSetupParticipant().setup(document); + viewer.configure(configuration); + viewer.setDocument(document); + viewer.setEditable(false); + Font font = JFaceResources.getFont(JFaceResources.TEXT_FONT); + viewer.getTextWidget().setFont(font); + + return viewer; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#getFormatterPreferenceKey() + */ + protected String getFormatterPreferenceKey() { + return AntEditorPreferenceConstants.TEMPLATES_USE_CODEFORMATTER; + } + + /* + * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#updateViewerInput() + */ + protected void updateViewerInput(Template template) { + SourceViewer viewer = getViewer(); + + if (AntUIPlugin.getDefault().getPreferenceStore().getBoolean( + getFormatterPreferenceKey())) { + String formatted = XmlFormatter.format(template.getPattern(), + fFormattingPreferences); + viewer.getDocument().set(formatted); + } else { + viewer.getDocument().set(template.getPattern()); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#getPreferencePageId() + */ + protected String getPreferencePageId() { + return "org.eclipse.ant.ui.TemplatesPreferencePage"; //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#insertTemplate(org.eclipse.jface.text.templates.Template) + */ + public void insertTemplate(Template template) { + IRegion region; + TemplateContextType type = CONTEXT_TYPE_REGISTRY + .getContextType(template.getContextTypeId()); + if (type == null) + return; + ISourceViewer contextViewer = fEditor.getViewer(); + ITextSelection textSelection = (ITextSelection) contextViewer + .getSelectionProvider().getSelection(); + region = new Region(textSelection.getOffset(), textSelection + .getLength()); + Point selection = contextViewer.getSelectedRange(); + Position position; + if (selection.y > 0) { + position = new Position(selection.x, selection.y); + } else { + position = new Position(region.getOffset(), region.getLength()); + } + + IDocument document = contextViewer.getDocument(); + AntContext context = new AntContext(type, document, fEditor + .getAntModel(), position); + context.setVariable("selection", textSelection.getText()); //$NON-NLS-1$ + AntTemplateProposal proposal = new AntTemplateProposal(template, + context, region, null, 100); + fEditor.getSite().getPage().activate(fEditor); + proposal.apply(fEditor.getViewer(), ' ', 0, region.getOffset()); + } + + /** + * Invoked by the editor whenever the caret position is updated + */ + public void cursorPositionChanged() { + String id= getContextId(); + if (id.equals(fCurrentId)) + return; + fCurrentId = id; + if (fCurrentId.equals(BuildFileContextType.BUILDFILE_CONTEXT_TYPE)) + contextTypeChanged(new String[] { BuildFileContextType.BUILDFILE_CONTEXT_TYPE }); + else + contextTypeChanged(new String[] { + TargetContextType.TARGET_CONTEXT_TYPE, + TaskContextType.TASK_CONTEXT_TYPE }); + } + + /** + * Get the contextid for the editor + * + * @return contextId + */ + private String getContextId() { + if (fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()) + .getLength() == 0) + return BuildFileContextType.BUILDFILE_CONTEXT_TYPE; + return TargetContextType.TARGET_CONTEXT_TYPE; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#isValidTempalteForPosition(org.eclipse.jface.text.templates.Template, int, int) + */ + protected boolean isValidTempalteForPosition(Template template, int x, int y) { + return getContextId().equals(template.getContextTypeId()); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#isEditorModifiable() + */ + protected boolean isEditorModifiable() { + return fEditor.isEditable() ; + } +} #P org.eclipse.ui.views Index: plugin.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views/plugin.properties,v retrieving revision 1.13 diff -u -r1.13 plugin.properties --- plugin.properties 8 May 2006 20:53:18 -0000 1.13 +++ plugin.properties 6 Aug 2007 07:23:04 -0000 @@ -7,10 +7,11 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Dakshinamurthy Karra - Templates support (bug 69581) ############################################################################### pluginName= Views providerName= Eclipse.org Views.PropertySheet = Properties Views.ContentOutline = Outline - +Views.Templates = Templates Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views/plugin.xml,v retrieving revision 1.26 diff -u -r1.26 plugin.xml --- plugin.xml 23 Feb 2006 19:35:46 -0000 1.26 +++ plugin.xml 6 Aug 2007 07:23:09 -0000 @@ -18,6 +18,13 @@ class="org.eclipse.ui.views.contentoutline.ContentOutline" id="org.eclipse.ui.views.ContentOutline"> + + Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views/META-INF/MANIFEST.MF,v retrieving revision 1.9 diff -u -r1.9 MANIFEST.MF --- META-INF/MANIFEST.MF 7 Sep 2006 19:17:20 -0000 1.9 +++ META-INF/MANIFEST.MF 6 Aug 2007 07:23:09 -0000 @@ -11,7 +11,8 @@ org.eclipse.ui.internal.views.contentoutline;x-internal:=true, org.eclipse.ui.internal.views.properties;x-internal:=true, org.eclipse.ui.views.contentoutline, - org.eclipse.ui.views.properties + org.eclipse.ui.views.properties, + org.eclipse.ui.views.templates Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)", org.eclipse.help;bundle-version="[3.2.0,4.0.0)", org.eclipse.ui;bundle-version="[3.2.0,4.0.0)" Index: src/org/eclipse/ui/internal/views/templates/TemplatesMessages.java =================================================================== RCS file: src/org/eclipse/ui/internal/views/templates/TemplatesMessages.java diff -N src/org/eclipse/ui/internal/views/templates/TemplatesMessages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/views/templates/TemplatesMessages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.views.templates; + +import org.eclipse.osgi.util.NLS; + +/** + * TemplatesMessages is the message class for the messages used in the templates view. + * + */ +public class TemplatesMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.ui.internal.views.templates.TemplatesMessages"; //$NON-NLS-1$ + + // Default message for an empty templates view + public static String Templates_defaultMessage; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, TemplatesMessages.class); + } + + private TemplatesMessages() { + } +} Index: src/org/eclipse/ui/internal/views/templates/TemplatesMessages.properties =================================================================== RCS file: src/org/eclipse/ui/internal/views/templates/TemplatesMessages.properties diff -N src/org/eclipse/ui/internal/views/templates/TemplatesMessages.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/views/templates/TemplatesMessages.properties 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,11 @@ +############################################################################### +# Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Dakshinamurthy Karra - initial API and implementation +############################################################################### +Templates_defaultMessage=No templates available for this editor Index: src/org/eclipse/ui/views/templates/Templates.java =================================================================== RCS file: src/org/eclipse/ui/views/templates/Templates.java diff -N src/org/eclipse/ui/views/templates/Templates.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/templates/Templates.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.views.templates; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.views.ViewsPlugin; +import org.eclipse.ui.internal.views.templates.TemplatesMessages; +import org.eclipse.ui.part.IContributedContentsView; +import org.eclipse.ui.part.IPage; +import org.eclipse.ui.part.MessagePage; +import org.eclipse.ui.part.PageBook; +import org.eclipse.ui.part.PageBookView; + +/** + * Main class for the Templates View. + *

+ * This standard view has id "org.eclipse.ui.views.TemplatesView". + *

+ * When a templates view notices an editor being activated, it + * asks the editor whether it has a template page to include + * in the templates view. This is done using getAdapter: + *
+ * IEditorPart editor = ...;
+ * ITemplatePage templatePage = (ITemplatePage) editor.getAdapter(ITemplatePage.class);
+ * if (templatePage != null) {
+ *    // editor wishes to contribute templatePage to templates view
+ * }
+ * 
+ * If the editor supports a templates page, the editor instantiates + * and configures the page, and returns it. This page is then added to the + * templates view (a pagebook which presents one page at a time) and + * immediately made the current page (the templates view need not be + * visible). If the editor does not support a template page, the templates + * view shows a special default page which makes it clear to the user + * that the templates view is disengaged. When the templates view notices a + * different editor being activated, it flips to the editor's corresponding + * template page. When the templates view notices an editor being + * closed, it may destroy the editor's corresponding content outline page. + *

+ *

+ * The workbench will automatically instantiate this class when a templates + * view is needed for a workbench window. This class was not intended + * to be instantiated or subclassed by clients. + *

+ * + * @since 3.4 + */ +public class Templates extends PageBookView { + /** + * The plugin prefix. + */ + public static final String PREFIX = PlatformUI.PLUGIN_ID + "."; //$NON-NLS-1$ + + /** + * Help context id used for the content outline view + * (value "org.eclipse.ui.content_outline_context"). + */ + public static final String TEMPLATES_VIEW_HELP_CONTEXT_ID = PREFIX + + "templates_view_context";//$NON-NLS-1$ + + /** + * Message to show on the default page. + */ + private String defaultText = TemplatesMessages.Templates_defaultMessage; + + /** + * Creates a content outline view with no content outline pages. + */ + public Templates() { + super(); + } + + /* (non-Javadoc) + * Method declared on PageBookView. + */ + protected IPage createDefaultPage(PageBook book) { + MessagePage page = new MessagePage(); + initPage(page); + page.createControl(book); + page.setMessage(defaultText); + return page; + } + + /** + * The PageBookView implementation of this IWorkbenchPart + * method creates a PageBook control with its default page showing. + */ + public void createPartControl(Composite parent) { + super.createPartControl(parent); + PlatformUI.getWorkbench().getHelpSystem().setHelp(getPageBook(), + TEMPLATES_VIEW_HELP_CONTEXT_ID); + } + + /* (non-Javadoc) + * Method declared on PageBookView. + */ + protected PageRec doCreatePage(IWorkbenchPart part) { + // Try to get template page. + Object obj = ViewsPlugin.getAdapter(part, ITemplatesPage.class, false); + if (obj instanceof ITemplatesPage) { + ITemplatesPage page = (ITemplatesPage) obj; + initPage(page); + page.createControl(getPageBook()); + return new PageRec(part, page); + } + // There is no template page + return null; + } + + /* (non-Javadoc) + * Method declared on PageBookView. + */ + protected void doDestroyPage(IWorkbenchPart part, PageRec rec) { + ITemplatesPage page = (ITemplatesPage) rec.page; + page.dispose(); + rec.dispose(); + } + + /* (non-Javadoc) + * Method declared on IAdaptable. + */ + public Object getAdapter(Class key) { + if (key == IContributedContentsView.class) { + return new IContributedContentsView() { + public IWorkbenchPart getContributingPart() { + return getContributingEditor(); + } + }; + } + return super.getAdapter(key); + } + + /* (non-Javadoc) + * Method declared on PageBookView. + */ + protected IWorkbenchPart getBootstrapPart() { + IWorkbenchPage page = getSite().getPage(); + if (page != null) { + return page.getActiveEditor(); + } + + return null; + } + + /** + * Returns the editor which contributed the current + * page to this view. + * + * @return the editor which contributed the current page + * or null if no editor contributed the current page + */ + private IWorkbenchPart getContributingEditor() { + return getCurrentContributingPart(); + } + + /* (non-Javadoc) + * Method declared on PageBookView. + * We only want to track editors. + */ + protected boolean isImportant(IWorkbenchPart part) { + //We only care about editors + return (part instanceof IEditorPart); + } + + /* (non-Javadoc) + * Method declared on IViewPart. + * Treat this the same as part activation. + */ + public void partBroughtToTop(IWorkbenchPart part) { + partActivated(part); + } +} Index: src/org/eclipse/ui/views/templates/ITemplatesPage.java =================================================================== RCS file: src/org/eclipse/ui/views/templates/ITemplatesPage.java diff -N src/org/eclipse/ui/views/templates/ITemplatesPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/templates/ITemplatesPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.views.templates; + +import org.eclipse.ui.part.IPageBookViewPage; + +/** + * Interface for a template page. This interface defines + * the minimum requirement for pages within the templates view, namely + * they must be pages (implement IPageBookViewPage). + * + * @see TemplatesView + * @since 3.4 + */ +public interface ITemplatesPage extends IPageBookViewPage { +} #P org.eclipse.ui.workbench.texteditor Index: src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.java,v retrieving revision 1.10 diff -u -r1.10 TextEditorTemplateMessages.java --- src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.java 25 May 2005 13:15:37 -0000 1.10 +++ src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.java 6 Aug 2007 07:23:31 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Dakshinamurthy Karra - TemplatesPage support (bug 69581) *******************************************************************************/ package org.eclipse.ui.texteditor.templates; @@ -20,11 +21,43 @@ final class TextEditorTemplateMessages extends NLS { private static final String BUNDLE_NAME= TextEditorTemplateMessages.class.getName(); - private TextEditorTemplateMessages() { // Do not instantiate } + // TemplatesView + public static String TemplatesPage_column_context; + public static String TemplatesPage_column_description; + public static String TemplatesPage_column_name; + public static String TemplatesPage_insert; + public static String TemplatesPage_edit; + public static String TemplatesPage_preference_page; + public static String TemplatesPage_link_to_editor; + public static String TemplatesPage_collapse_expand; + public static String TemplatesPage_new; + public static String TemplatesPage_remove; + public static String TemplatesPage_show_disabled; + public static String TemplatesPage_show_new_dialog; + public static String TemplatesPage_insert_tooltip; + public static String TemplatesPage_edit_tooltip; + public static String TemplatesPage_preference_page_tooltip; + public static String TemplatesPage_link_to_editor_tooltip; + public static String TemplatesPage_collapse_expand_tooltip; + public static String TemplatesPage_new_tooltip; + public static String TemplatesPage_remove_tooltip; + public static String TemplatesPage_show_disabled_tooltip; + public static String TemplatesPage_show_new_dialog_tooltip; + public static String TemplatesPage_preview; + public static String TemplatesPage_question_create_new_message; + public static String TemplatesPage_question_create_new_title; + public static String TemplatesPage_save_error_message; + public static String TemplatesPage_snippet; + public static String TemplatesPage_paste_description; + public static String TemplatesPage_context_description; + public static String TemplatesPage_remove_message; + public static String TemplatesPage_remove_title; + + // TemplatePreferencePage public static String TemplatePreferencePage_error_import; public static String TemplatePreferencePage_error_export; public static String TemplatePreferencePage_error_read_title; Index: src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.properties,v retrieving revision 1.13 diff -u -r1.13 TextEditorTemplateMessages.properties --- src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.properties 28 Mar 2006 16:36:54 -0000 1.13 +++ src/org/eclipse/ui/texteditor/templates/TextEditorTemplateMessages.properties 6 Aug 2007 07:23:31 -0000 @@ -7,8 +7,41 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Dakshinamurthy Karra - TemplatesPage support (bug 69581) ############################################################################### +# templates page (view) +TemplatesPage_collapse_expand=Collapse or Expand +TemplatesPage_column_context=Context +TemplatesPage_column_description=Description +TemplatesPage_save_error_message=Error Saving the Templates +TemplatesPage_column_name=Name +TemplatesPage_edit=&Edit... +TemplatesPage_insert=&Insert... +TemplatesPage_preference_page=&Preference Page... +TemplatesPage_paste_description=Pasted from editor +TemplatesPage_link_to_editor=Link to Editor +TemplatesPage_new=&New... +TemplatesPage_preview=Preview +TemplatesPage_snippet=snippet +TemplatesPage_question_create_new_message= The name of the template has been changed. Click 'Yes' to create an additional template with the new name or 'No' to rename the existing one. +TemplatesPage_context_description=Context +TemplatesPage_remove_title=Removing Templates +TemplatesPage_remove_message=Are you sure you want to remove the selected templates? +TemplatesPage_question_create_new_title= Edit Template +TemplatesPage_remove=&Remove +TemplatesPage_show_disabled=&Show Disabled +TemplatesPage_show_new_dialog=S&how New Dialog on Drop +TemplatesPage_insert_tooltip=Insert into editor +TemplatesPage_edit_tooltip=Edit the template +TemplatesPage_preference_page_tooltip=Show preference page +TemplatesPage_link_to_editor_tooltip=Link with editor +TemplatesPage_collapse_expand_tooltip=Collapse or expand groups +TemplatesPage_new_tooltip=Create a new template +TemplatesPage_remove_tooltip=Remove the template +TemplatesPage_show_disabled_tooltip=Show disabled templates +TemplatesPage_show_new_dialog_tooltip=Show new dialog + # preference page TemplatePreferencePage_error_import=Failed to import templates. TemplatePreferencePage_error_export=Failed to export templates. Index: src/org/eclipse/ui/texteditor/templates/TemplatePreferencePage.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/templates/TemplatePreferencePage.java,v retrieving revision 1.54 diff -u -r1.54 TemplatePreferencePage.java --- src/org/eclipse/ui/texteditor/templates/TemplatePreferencePage.java 28 Jun 2007 15:50:39 -0000 1.54 +++ src/org/eclipse/ui/texteditor/templates/TemplatePreferencePage.java 6 Aug 2007 07:23:26 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Dakshinamurthy Karra - bug 69581 *******************************************************************************/ package org.eclipse.ui.texteditor.templates; @@ -137,7 +138,7 @@ * * @since 3.3 */ - protected static class EditTemplateDialog extends StatusDialog { + public static class EditTemplateDialog extends StatusDialog { private class TextViewerAction extends Action implements IUpdate { Index: src/org/eclipse/ui/texteditor/templates/TemplatesPage.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/templates/TemplatesPage.java diff -N src/org/eclipse/ui/texteditor/templates/TemplatesPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/templates/TemplatesPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1393 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.templates; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.TreeColumnLayout; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.jface.text.templates.ContextTypeRegistry; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; +import org.eclipse.jface.text.templates.persistence.TemplateStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.custom.ViewForm; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSourceAdapter; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.DropTargetAdapter; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.dnd.IDragAndDropService; +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; +import org.eclipse.ui.part.Page; +import org.eclipse.ui.texteditor.templates.TemplatePreferencePage.EditTemplateDialog; + +/** + * An abstract base class for template pages for use with TextEditor and JFace + * {@link Template}. + *

+ * Clients who are defining an editor may elect to provide a corresponding + * templates page. This templates page will be presented to the user via the + * Templates View (the user decides whether their workbench window contains this + * view) whenever that editor is active. This class should be subclassed. + *

+ *

+ * Internally, a TemplatesPage uses the template store to display different + * categories. A link to editor mode on the templates page allows to filtering + * of the categories to only that are supported in this context. + *

+ * @since 3.4 + */ +public abstract class TemplatesPage extends Page { + + /** + * Sashform size + */ + private static final String SASH_SIZE_PREF_ID = TextEditorPlugin.PLUGIN_ID + + ".templates.templatesPage.sashSize"; //$NON-NLS-1$ + /** + * Tree columns widths + */ + private static final String COLUMN_NAME_WIDTH_PREF_ID = TextEditorPlugin.PLUGIN_ID + + ".templates.templatesPage.nameWidth"; //$NON-NLS-1$ + private static final String COLUMN_DESCRIPTION_WIDTH_PREF_ID = TextEditorPlugin.PLUGIN_ID + + ".templates.templatesPage.descriptionWidth"; //$NON-NLS-1$ + /** + * Link to editor action setting + */ + private static final String LINK_ACTION_PREF_ID = TextEditorPlugin.PLUGIN_ID + + ".templates.templatesPage.linkAction"; //$NON-NLS-1$ + /** + * Show disabled actions setting + */ + private static final String SHOW_DISABLED_ACTION_PREF_ID = TextEditorPlugin.PLUGIN_ID + + ".templates.templatesPage.showDisabledAction"; //$NON-NLS-1$ + /** + * Show new dialog on drop setting + */ + private static final String SHOW_NEW_DIALOG_ACTION_PREF_ID = TextEditorPlugin.PLUGIN_ID + + ".templates.templatesPage.showNewDialogAction"; //$NON-NLS-1$; + + /** + * The ID for the popup menu for this templates page + */ + private static final String POPUP_MENU_ID = "org.eclipse.ui.texteditor.templates.PopupMenu"; //$NON-NLS-1$ + + /** + * Drop support for the editor linked to this page. When a user drops a + * template into the active editor, the template is applied at the drop + * position. + */ + private final class EditorDropTarget extends DropTargetAdapter { + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void dragEnter(DropTargetEvent event) { + if (event.detail == DND.DROP_DEFAULT) + event.detail = DND.DROP_COPY; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void dragOperationChanged(DropTargetEvent event) { + if (event.detail == DND.DROP_DEFAULT) + event.detail = DND.DROP_COPY; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void dragOver(DropTargetEvent event) { + event.feedback |= DND.FEEDBACK_SCROLL; + if (!isEditorModifiable()) { + event.detail = DND.DROP_NONE; + return; + } + if (isValidTempalteForPosition(getSelectedTemplate(), event.x, event.y)) { + event.detail = DND.DROP_COPY; + return; + } + event.detail = DND.DROP_NONE; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void drop(DropTargetEvent event) { + insertTemplate(getSelectedTemplate()); + } + } + + /** + * Comparator for the viewer. Sorts the templates by name and then + * description and context types by names. + */ + private static final class TemplateViewerComparator extends ViewerComparator { + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, + * java.lang.Object, java.lang.Object) + */ + public int compare(Viewer viewer, Object object1, Object object2) { + if ((object1 instanceof TemplatePersistenceData) + && (object2 instanceof TemplatePersistenceData)) { + Template left = ((TemplatePersistenceData) object1).getTemplate(); + Template right = ((TemplatePersistenceData) object2).getTemplate(); + int result = left.getName().compareToIgnoreCase(right.getName()); + if (result != 0) + return result; + return left.getDescription().compareToIgnoreCase(right.getDescription()); + } + if ((object1 instanceof TemplateContextType) + && (object2 instanceof TemplateContextType)) { + return ((TemplateContextType) object1).getName().compareToIgnoreCase( + ((TemplateContextType) object1).getName()); + } + return super.compare(viewer, object1, object2); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ViewerComparator#isSorterProperty(java.lang.Object, + * java.lang.String) + */ + public boolean isSorterProperty(Object element, String property) { + return true; + } + } + + /** + * Label provider for templates. + */ + private class TemplateLabelProvider extends LabelProvider implements ITableLabelProvider { + + /* + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, + * int) + */ + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + /* + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, + * int) + */ + public String getColumnText(Object element, int columnIndex) { + if (element instanceof TemplatePersistenceData) + return getTemplateColumnText(((TemplatePersistenceData) element).getTemplate(), + columnIndex); + return getContextColumnText((TemplateContextType) element, columnIndex); + } + + /** + * Return the column text for a template + * + * @param template + * @param columnIndex + * @return the column text + */ + private String getTemplateColumnText(Template template, int columnIndex) { + switch (columnIndex) { + case 0: + return template.getName(); + case 1: + return template.getDescription(); + default: + return ""; //$NON-NLS-1$ + } + } + + /** + * Return the column text for a context + * + * @param contextType + * @param columnIndex + * @return the column text + */ + private String getContextColumnText(TemplateContextType contextType, int columnIndex) { + switch (columnIndex) { + case 0: + return contextType.getName(); + case 1: + return TextEditorTemplateMessages.TemplatesPage_context_description; + default: + return ""; //$NON-NLS-1$ + } + } + + } + + /** + * Content provider for templates. Provides all the templates defined for + * this editor and optionally the disabled ones. + */ + private class TemplatesContentProvider implements ITreeContentProvider { + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof TemplatePersistenceData) + return new Object[0]; + else if (parentElement instanceof TemplateContextType) { + TemplateContextType contextType = (TemplateContextType) parentElement; + return getTemplates(contextType.getId()); + } + return null; + } + + /** + * Get the templates for a given contextId. if ShowDisabled is selected + * the disabled templates are also included. + * + * @param contextId + * @return the templates + */ + private TemplatePersistenceData[] getTemplates(String contextId) { + List templateList = new ArrayList(); + TemplatePersistenceData[] datas = fTemplateStore.getTemplateData(false); + for (int i = 0; i < datas.length; i++) { + if ((fShowDisabled || datas[i].isEnabled()) + && datas[i].getTemplate().getContextTypeId().equals(contextId)) + templateList.add(datas[i]); + } + return (TemplatePersistenceData[]) templateList + .toArray(new TemplatePersistenceData[templateList.size()]); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + public Object getParent(Object element) { + if (element instanceof TemplatePersistenceData) { + TemplatePersistenceData templateData = (TemplatePersistenceData) element; + return fContextTypeRegistry.getContextType(templateData.getTemplate() + .getContextTypeId()); + } + return null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + public boolean hasChildren(Object element) { + if (element instanceof TemplateContextType) + return true; + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + List contextTypes = new ArrayList(); + + for (Iterator iterator = fContextTypeRegistry.contextTypes(); iterator.hasNext();) { + TemplateContextType contextType = (TemplateContextType) iterator.next(); + if (isActiveContext(contextType) || !fLinkWithEditor) + contextTypes.add(contextType); + } + return contextTypes.toArray(new TemplateContextType[contextTypes.size()]); + } + + /** + * Checks whether given context type is active for displaying the + * templates + * + * @param contextType + * @return true if context is active + */ + private boolean isActiveContext(TemplateContextType contextType) { + return fActiveTypes == null || fActiveTypes.contains(contextType.getId()); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, + * java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + } + + /** + * Show/Hide new dialog + */ + private static final int SHOW_DIALOG = 0; + private static final int MAY_HIDE_DIALOG = 1; + + /** The viewer displays the pattern of selected template. */ + private SourceViewer fPatternViewer; + /** The store for our templates. */ + private TemplateStore fTemplateStore; + /** + * The template stores preference page. Used to listen to the changes and + * update the view. Needed when the user selects Preferences and updates the + * templates. + */ + private IPreferenceStore fTemplatePreferenceStore; + private IPropertyChangeListener fTemplateChangeListener; + /** The context type registry. */ + private ContextTypeRegistry fContextTypeRegistry; + + /** The control for this page book view */ + private SashForm fControl; + + /* Actions */ + private Action fInsertAction; + private Action fAddAction; + private Action fEditAction; + private Action fRemoveAction; + private Action fLinkWithEditorAction; + private Action fExpandCollapseAction; + private Action fPreferencePageAction; + private Action fShowDisabledAction; + private Action fShowNewDialogOnDropAction; + + /* Clipboard actions */ + private Action fPasteAction; + private Action fCopyAction; + + /* Options and values saved in preference store */ + private boolean fLinkWithEditor ; + private boolean fShowDisabled ; + private boolean fShowNewDialogOnDrop ; + private int fSashSize; + private int fNameWidth; + private int fDescriptionWidth ; + + /** Currently selected templates and type */ + private ArrayList fSelectedTemplateList = new ArrayList(); + private TemplateContextType fSelectedType; + + /** Current active context types for the editor */ + private List fActiveTypes; + + /* Preference stores */ + /** + * Preference store to store the dialog setting for this page + */ + private IPreferenceStore fPreferenceStore; + + /* Controls */ + private Tree fTemplatesTree; + private TreeViewer fTreeViewer; + private Menu fContextMenu; + + /** + * Creates a new template view page. + * + * @param templateStore + * @param templatePreferenceStore + * @param registry + */ + protected TemplatesPage(TemplateStore templateStore, IPreferenceStore templatePreferenceStore, + ContextTypeRegistry registry) { + super(); + setupPreferenceStore(); + fTemplateStore = templateStore; + fTemplatePreferenceStore = templatePreferenceStore; + if (fTemplatePreferenceStore != null) { + fTemplateChangeListener = new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + refresh(); + } + }; + fTemplatePreferenceStore.addPropertyChangeListener(fTemplateChangeListener); + } + fContextTypeRegistry = registry; + } + + private void setupPreferenceStore() { + fPreferenceStore = TextEditorPlugin.getDefault().getPreferenceStore(); + fPreferenceStore.setDefault(LINK_ACTION_PREF_ID, true); + fPreferenceStore.setDefault(SHOW_DISABLED_ACTION_PREF_ID, false); + fPreferenceStore.setDefault(SHOW_NEW_DIALOG_ACTION_PREF_ID, true); + fPreferenceStore.setDefault(SASH_SIZE_PREF_ID, 80); + fLinkWithEditor = fPreferenceStore.getBoolean(LINK_ACTION_PREF_ID); + fShowDisabled = fPreferenceStore.getBoolean(SHOW_DISABLED_ACTION_PREF_ID); + fShowNewDialogOnDrop = fPreferenceStore.getBoolean(SHOW_NEW_DIALOG_ACTION_PREF_ID); + fSashSize = fPreferenceStore.getInt(SASH_SIZE_PREF_ID); + } + + /** + * Check whether the linked editor is modifiable + * + * @return true if the editor is modifiable + */ + protected boolean isEditorModifiable() { + return true; + } + + /** + * Check whether the template is valid for the current drop position + * + * @param template + * @param x + * @param y + * @return true if the template is valid + */ + protected boolean isValidTempalteForPosition(Template template, int x, int y) { + return true; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.Page#createControl(org.eclipse.swt.widgets.Composite) + */ + public void createControl(Composite ancestor) { + setupActions(); + + fControl = new SashForm(ancestor, SWT.VERTICAL); + + createTemplateTree(); + createPatternViewer(fControl); + + hookContextMenu(); + initializeDND(); + updateButtons(); + + fControl.setWeights(new int[] { fSashSize, 100 - fSashSize }); + } + + /** + * Setup the actions + */ + private void setupActions() { + createActions(); + IActionBars actionBars = getSite().getActionBars(); + + actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), fPasteAction); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction); + + fillToolbar(actionBars); + fillMenu(actionBars); + } + + /** + * Create actions for this view + */ + private void createActions() { + fInsertAction = new Action(TextEditorTemplateMessages.TemplatesPage_insert) { + public void run() { + insertTemplate(getSelectedTemplate()); + } + }; + fInsertAction.setToolTipText(TextEditorTemplateMessages.TemplatesPage_insert_tooltip); + + fAddAction = new Action(TextEditorTemplateMessages.TemplatesPage_new) { + public void run() { + addTemplate(); + } + }; + fAddAction.setImageDescriptor(TemplatesViewImages + .getImageDescriptor(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_NEW)); + fAddAction.setToolTipText(TextEditorTemplateMessages.TemplatesPage_new_tooltip); + + fEditAction = new Action(TextEditorTemplateMessages.TemplatesPage_edit) { + public void run() { + editTemplate(); + } + }; + fEditAction.setImageDescriptor(TemplatesViewImages + .getImageDescriptor(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_EDIT)); + fEditAction.setDisabledImageDescriptor(TemplatesViewImages + .getImageDescriptor(ITemplateViewImageConstants.IMG_DLCL_TEMPLATE_EDIT)); + fEditAction.setToolTipText(TextEditorTemplateMessages.TemplatesPage_edit_tooltip); + + fRemoveAction = new Action(TextEditorTemplateMessages.TemplatesPage_remove) { + public void run() { + removeTemplate(); + } + }; + fRemoveAction.setImageDescriptor(TemplatesViewImages + .getImageDescriptor(ITemplateViewImageConstants.IMG_DLCL_TEMPLATE_DELETE)); + fRemoveAction.setImageDescriptor(TemplatesViewImages + .getImageDescriptor(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_DELETE)); + fRemoveAction.setToolTipText(TextEditorTemplateMessages.TemplatesPage_remove_tooltip); + + fLinkWithEditorAction = new Action(TextEditorTemplateMessages.TemplatesPage_link_to_editor, + IAction.AS_CHECK_BOX) { + public void run() { + fLinkWithEditor = fLinkWithEditorAction.isChecked(); + refresh(); + } + }; + fLinkWithEditorAction.setImageDescriptor(TemplatesViewImages + .getImageDescriptor(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_LINK)); + fLinkWithEditorAction.setChecked(fPreferenceStore.getBoolean(LINK_ACTION_PREF_ID)); + fLinkWithEditorAction.setToolTipText(TextEditorTemplateMessages.TemplatesPage_link_to_editor_tooltip); + fExpandCollapseAction = new Action(TextEditorTemplateMessages.TemplatesPage_collapse_expand) { + public void run() { + Object[] vee = fTreeViewer.getVisibleExpandedElements(); + boolean collapse = vee.length != 0; + if (collapse) + fTreeViewer.collapseAll(); + else + fTreeViewer.expandAll(); + } + }; + fExpandCollapseAction.setImageDescriptor(TemplatesViewImages + .getImageDescriptor(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_COLLAPSE_EXPAND)); + fExpandCollapseAction + .setToolTipText(TextEditorTemplateMessages.TemplatesPage_collapse_expand_tooltip); + + if (getPreferencePageId() != null) { + fPreferencePageAction = new Action( + TextEditorTemplateMessages.TemplatesPage_preference_page) { + public void run() { + showPreferencePage(); + } + }; + fPreferencePageAction + .setToolTipText(TextEditorTemplateMessages.TemplatesPage_preference_page_tooltip); + } + + fShowDisabledAction = new Action(TextEditorTemplateMessages.TemplatesPage_show_disabled, + IAction.AS_CHECK_BOX) { + public void run() { + fShowDisabled = fShowDisabledAction.isChecked(); + refresh(); + } + }; + fShowDisabledAction.setChecked(fPreferenceStore.getBoolean(SHOW_DISABLED_ACTION_PREF_ID)); + fShowDisabledAction + .setToolTipText(TextEditorTemplateMessages.TemplatesPage_show_disabled_tooltip); + + fShowNewDialogOnDropAction = new Action( + TextEditorTemplateMessages.TemplatesPage_show_new_dialog, IAction.AS_CHECK_BOX) { + public void run() { + fShowNewDialogOnDrop = fShowNewDialogOnDropAction.isChecked(); + } + }; + fShowNewDialogOnDropAction.setChecked(fPreferenceStore + .getBoolean(SHOW_NEW_DIALOG_ACTION_PREF_ID)); + fShowNewDialogOnDropAction + .setToolTipText(TextEditorTemplateMessages.TemplatesPage_show_new_dialog_tooltip); + + fPasteAction = new Action() { + public void run() { + Clipboard clipBoard = new Clipboard(getShell().getDisplay()); + final Template template = getTemplateFromCB(clipBoard); + if (template == null) + return; + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + addTemplate(template, MAY_HIDE_DIALOG); + } + }); + } + + private Template getTemplateFromCB(Clipboard clipBoard) { + String text = (String) clipBoard.getContents(TextTransfer.getInstance()); + if (text == null) + return getTemplateFromTemplate(clipBoard); + return new Template(TextEditorTemplateMessages.TemplatesPage_snippet, + TextEditorTemplateMessages.TemplatesPage_paste_description, + getContextTypeId(), text.replaceAll("\\$", "\\$\\$"), true); //$NON-NLS-1$ //$NON-NLS-2$ + } + + private Template getTemplateFromTemplate(Clipboard clipBoard) { + Object contents = clipBoard.getContents(TemplateTransfer.getInstance()); + if (contents == null) + return null; + Template t = ((Template[]) contents)[0]; + return new Template(t.getName(), t.getDescription(), getContextTypeId(), t + .getPattern(), true); + } + }; + + fCopyAction = new Action() { + public void run() { + if (!isSingleTemplateSelected()) + return; + Template[] templates = new Template[] { getSelectedTemplate() }; + Clipboard clipBoard = new Clipboard(getShell().getDisplay()); + clipBoard.setContents(new Object[] { templates }, new Transfer[] { TemplateTransfer + .getInstance() }); + } + }; + } + + /** + * Fill the menu items + * + * @param actionBars + */ + private void fillMenu(IActionBars actionBars) { + IMenuManager menuManager = actionBars.getMenuManager(); + + if (fPreferencePageAction != null) { + menuManager.add(fPreferencePageAction); + menuManager.add(new Separator()); + } + menuManager.add(fShowDisabledAction); + menuManager.add(fShowNewDialogOnDropAction); + + menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + + /** + * Fill items into the toolbar + * + * @param actionBars + */ + private void fillToolbar(IActionBars actionBars) { + IToolBarManager toolBarManager = actionBars.getToolBarManager(); + toolBarManager.add(fAddAction); + toolBarManager.add(fEditAction); + toolBarManager.add(fRemoveAction); + + toolBarManager.add(new Separator()); + + toolBarManager.add(fLinkWithEditorAction); + toolBarManager.add(fExpandCollapseAction); + } + + /** + * Setup the context menu for the viewer. + */ + private void hookContextMenu() { + MenuManager menuMgr = new MenuManager(POPUP_MENU_ID); + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + fillContextMenu(manager); + } + }); + fContextMenu = menuMgr.createContextMenu(fTreeViewer.getControl()); + fTreeViewer.getControl().setMenu(fContextMenu); + getSite().registerContextMenu(POPUP_MENU_ID, menuMgr, fTreeViewer); + } + + /** + * Fill up the context menu + * + * @param manager + */ + private void fillContextMenu(IMenuManager manager) { + manager.add(fInsertAction); + manager.add(new Separator()); + manager.add(fAddAction); + manager.add(fEditAction); + manager.add(fRemoveAction); + // Other plug-ins can contribute there actions here + manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + + /** + * Create the tree control to display template information + */ + private void createTemplateTree() { + Composite treeComposite = new Composite(fControl, SWT.NONE); + GridData data = new GridData(GridData.FILL_BOTH); + treeComposite.setLayoutData(data); + + TreeColumnLayout columnLayout = new TreeColumnLayout(); + treeComposite.setLayout(columnLayout); + fTemplatesTree = new Tree(treeComposite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI + | SWT.FULL_SELECTION); + fTemplatesTree.setHeaderVisible(true); + fTemplatesTree.setLinesVisible(true); + + GC gc = new GC(getShell()); + gc.setFont(JFaceResources.getDialogFont()); + + TreeColumn columnName = new TreeColumn(fTemplatesTree, SWT.NONE); + columnName.setText(TextEditorTemplateMessages.TemplatesPage_column_name); + int minWidth = fPreferenceStore.getInt(COLUMN_NAME_WIDTH_PREF_ID); + if (minWidth == 0) + minWidth = gc.stringExtent(TextEditorTemplateMessages.TemplatesPage_column_name).x + 10; + columnLayout.setColumnData(columnName, new ColumnWeightData(2, minWidth, true)); + columnName.addControlListener(new ControlListener() { + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + fNameWidth = ((TreeColumn)e.getSource()).getWidth(); + } + }); + + TreeColumn columnDescription = new TreeColumn(fTemplatesTree, SWT.NONE); + columnDescription.setText(TextEditorTemplateMessages.TemplatesPage_column_description); + minWidth = fPreferenceStore.getInt(COLUMN_DESCRIPTION_WIDTH_PREF_ID); + if (minWidth == 0) + minWidth = gc.stringExtent(TextEditorTemplateMessages.TemplatesPage_column_description).x + 10; + columnLayout.setColumnData(columnDescription, new ColumnWeightData(3, minWidth, true)); + columnDescription.addControlListener(new ControlListener() { + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + fDescriptionWidth = ((TreeColumn)e.getSource()).getWidth(); + } + }); + + + gc.dispose(); + + createTreeViewer(); + } + + /** + * Create the viewer for the tree control and configure it. + */ + private void createTreeViewer() { + fTreeViewer = new TreeViewer(fTemplatesTree); + fTreeViewer.setLabelProvider(new TemplateLabelProvider()); + fTreeViewer.setContentProvider(new TemplatesContentProvider()); + + fTreeViewer.setComparator(new TemplateViewerComparator()); + fTreeViewer.setInput(fTemplateStore); + fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent e) { + updateSelectedItems(); + insertTemplate(getSelectedTemplate()); + } + }); + + fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent e) { + updateSelectedItems(); + updateButtons(); + } + }); + fTreeViewer.expandAll(); + decorateTemplates(); + } + + /** + * Create a viewer to display the pattern + * + * @param parent + */ + private void createPatternViewer(Composite parent) { + ViewForm viewForm = new ViewForm(parent, SWT.NONE); + viewForm.setBorderVisible(false); + CLabel previewLabel = new CLabel(viewForm, SWT.NONE); + previewLabel.setText(TextEditorTemplateMessages.TemplatesPage_preview); + previewLabel.setImage(TemplatesViewImages + .getImage(ITemplateViewImageConstants.IMG_OBJ_PREVIEW)); + viewForm.setTopLeft(previewLabel); + + fPatternViewer = createViewer(viewForm); + fPatternViewer.setEditable(false); + viewForm.setContent(fPatternViewer.getControl()); + viewForm.addControlListener(new ControlListener() { + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + int[] weights = fControl.getWeights(); + fSashSize = (int) (weights[0] * 100.0 / (weights[0] + weights[1])); + } + }); + } + + /** + * Sets all templates in the tree that are disabled to grey. + */ + private void decorateTemplates() { + TreeItem[] contextItems = fTemplatesTree.getItems(); + Color fgcDisabled = getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY); + Color fgcEnabled = getShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND); + for (int i = 0; i < contextItems.length; i++) { + contextItems[i].setFont(getBoldFont(contextItems[i].getFont())); + TreeItem[] templateItems = contextItems[i].getItems(); + for (int j = 0; j < templateItems.length; j++) { + TemplatePersistenceData templateData = (TemplatePersistenceData) templateItems[j] + .getData(); + if (templateData == null) + continue; + if (!templateData.isEnabled() && templateItems[j].getForeground() != fgcDisabled) + templateItems[j].setForeground(fgcDisabled); + else if (templateData.isEnabled() && templateItems[j].getForeground() != fgcEnabled) + templateItems[j].setForeground(fgcEnabled); + } + } + } + + private Font getBoldFont(Font font) { + FontData[] fontData = font.getFontData(); + for (int i = 0; i < fontData.length; i++) { + fontData[i].setStyle(fontData[i].getStyle() | SWT.BOLD | SWT.ITALIC); + } + return new Font(font.getDevice(), fontData); + } + + /** + * Update the selected template list, type and pattern viewer + */ + private void updateSelectedItems() { + IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); + + fSelectedTemplateList.clear(); + fSelectedType = null; + + if (selection.size() == 1) { + Object item = selection.getFirstElement(); + if (item instanceof TemplateContextType) + fSelectedType = (TemplateContextType) item; + else + fSelectedTemplateList.add(item); + } else if (selection.size() > 1) { + for (Iterator iterator = selection.iterator(); iterator.hasNext();) { + Object item = iterator.next(); + if (item instanceof TemplateContextType) { + fSelectedTemplateList.clear(); + break; + } + fSelectedTemplateList.add(item); + } + } + if (!fSelectedTemplateList.isEmpty()) { + String contextTypeId = ((TemplatePersistenceData) fSelectedTemplateList.get(0)) + .getTemplate().getContextTypeId(); + fSelectedType = fContextTypeRegistry.getContextType(contextTypeId); + for (Iterator iterator = fSelectedTemplateList.iterator(); iterator.hasNext();) { + TemplatePersistenceData template = (TemplatePersistenceData) iterator.next(); + if (!contextTypeId.equals(template.getTemplate().getContextTypeId())) { + fSelectedType = null; + break; + } + } + } + if (isSingleTemplateSelected()) { + updateViewerInput(getSelectedTemplate()); + } else + fPatternViewer.getDocument().set(""); //$NON-NLS-1$ + } + + /** + * Checks whether only one template is selected in the tree + * + * @return true if only single template is selected + */ + private boolean isSingleTemplateSelected() { + return fSelectedTemplateList.size() == 1; + } + + /** + * Get the selected template. Note: should always precede with a check for + * isSingleTemplateSelected + * + * @return the template (Not the data) + */ + private Template getSelectedTemplate() { + return ((TemplatePersistenceData) fSelectedTemplateList.get(0)).getTemplate(); + } + + /** + * Show the preference templates preference page + */ + private void showPreferencePage() { + PreferencesUtil.createPreferenceDialogOn(getShell(), getPreferencePageId(), null, null) + .open(); + } + + /** + * Get the preference page ID for the templates for the given editor. + * Subclasses should override. + * + * @return id of the preference page + */ + protected String getPreferencePageId() { + return null; + } + + /** + * Get the shell + * + * @return the shell for this view site + */ + protected Shell getShell() { + return getSite().getShell(); + } + + /** + * Creates, configures and returns a source viewer to present the template + * pattern on the preference page. Clients may override to provide a custom + * source viewer featuring e.g. syntax coloring. + * + * @param parent + * the parent control + * @return a configured source viewer + */ + protected SourceViewer createViewer(Composite parent) { + SourceViewer viewer = new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL + | SWT.H_SCROLL); + SourceViewerConfiguration configuration = new SourceViewerConfiguration(); + viewer.configure(configuration); + IDocument document = new Document(); + viewer.setDocument(document); + return viewer; + } + + /** + * Updates the pattern viewer. + * + * @param template + */ + protected void updateViewerInput(Template template) { + if (template != null) + fPatternViewer.getDocument().set(template.getPattern()); + else + fPatternViewer.getDocument().set(""); //$NON-NLS-1$ + } + + /** + * Updates the buttons. + */ + private void updateButtons() { + fCopyAction.setEnabled(isSingleTemplateSelected()); + fInsertAction.setEnabled(isSingleTemplateSelected()); + fEditAction.setEnabled(isSingleTemplateSelected()); + fRemoveAction.setEnabled(fSelectedTemplateList.size() != 0); + } + + /** + * Add a template + */ + private void addTemplate() { + String id = getContextTypeId(); + if (id != null) { + Template template = new Template("", "", id, "", true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + addTemplate(template, SHOW_DIALOG); + } + } + + /** + * Get the selected or the first context type from the registry. + * + * @return id of the context type + */ + private String getContextTypeId() { + if (fSelectedType != null) + return fSelectedType.getId(); + Iterator it = fContextTypeRegistry.contextTypes(); + if (it.hasNext()) + return ((TemplateContextType) it.next()).getId(); + return null; + } + + /** + * Add a template + * + * Setting ui to SHOW_DIALOG will force a New dialog. Setting it to + * MAY_HIDE_DIALOG will respect the show new dialog on drop option. + * + * @param template + * @param ui + */ + private void addTemplate(Template template, int ui) { + Template newTemplate; + if (ui == SHOW_DIALOG || fShowNewDialogOnDrop) + newTemplate = editTemplate(template, false, true); + else + newTemplate = template; + if (newTemplate != null) { + TemplatePersistenceData data = new TemplatePersistenceData(newTemplate, true); + fTemplateStore.add(data); + saveTemplateStore(); + fSelectedTemplateList.clear(); + fSelectedTemplateList.add(data); + changeSelection(); + } + } + + /** + * Save the template store + */ + private void saveTemplateStore() { + try { + fTemplateStore.save(); + } catch (IOException e) { + e.printStackTrace(); + MessageDialog.openError(getShell(), + TextEditorTemplateMessages.TemplatesPage_save_error_message, e.getMessage()); + } + } + + /** + * Change selection in the viewer. oldData will contain the earlier selected + * template and fCurrentTemplateData will hold the current selection. Either + * can be null. + * + */ + private void changeSelection() { + fTreeViewer.refresh(); + if (isSingleTemplateSelected()) + fTreeViewer.setSelection(new StructuredSelection(fSelectedTemplateList.get(0)), true); + else + fTreeViewer.setSelection(new StructuredSelection()); + updateSelectedItems(); + } + + /** + * Creates the edit dialog. Subclasses may override this method to provide a + * custom dialog. + * + * @param template + * the template being edited + * @param edit + * whether the dialog should be editable + * @param isNameModifiable + * whether the template name may be modified + * @return the created or modified template, or null if the + * edition failed + * @since 3.1 + */ + protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) { + EditTemplateDialog dialog = new EditTemplateDialog(getShell(), template, edit, + isNameModifiable, fContextTypeRegistry); + if (dialog.open() == Window.OK) { + return dialog.getTemplate(); + } + return null; + } + + /** + * Edit the current template + */ + private void editTemplate() { + Template oldTemplate = getSelectedTemplate(); + Template newTemplate = editTemplate(new Template(oldTemplate), true, true); + if (newTemplate != null) { + if (!newTemplate.getName().equals(oldTemplate.getName()) + && MessageDialog.openQuestion(getShell(), + TextEditorTemplateMessages.TemplatesPage_question_create_new_title, + TextEditorTemplateMessages.TemplatesPage_question_create_new_message)) { + fSelectedTemplateList.clear(); + TemplatePersistenceData templateData = new TemplatePersistenceData(newTemplate, + true); + fSelectedTemplateList.add(templateData); + fTemplateStore.add(templateData); + } else { + ((TemplatePersistenceData) fSelectedTemplateList.get(0)).setTemplate(newTemplate); + } + changeSelection(); + } + saveTemplateStore(); + } + + /** + * Remove the currently selected templates + */ + private void removeTemplate() { + if (!MessageDialog.openQuestion(getShell(), + TextEditorTemplateMessages.TemplatesPage_remove_title, + TextEditorTemplateMessages.TemplatesPage_remove_message)) + return; + for (Iterator iterator = fSelectedTemplateList.iterator(); iterator.hasNext();) { + TemplatePersistenceData data = (TemplatePersistenceData) iterator.next(); + fTemplateStore.delete(data); + } + saveTemplateStore(); + fSelectedTemplateList.clear(); + changeSelection(); + } + + /** + * Get the pattern viewer. Subclass can override + * + * @return the viewer + */ + protected SourceViewer getViewer() { + return fPatternViewer; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.Page#getControl() + */ + public Control getControl() { + return fControl; + } + + /** + * Subclasses should override and facilitate inserting the template code + * into the active editor. + * + * @param template + */ + public void insertTemplate(Template template) { + } + + /** + * The caret position in the editor has moved into a new context type. It is + * the subclasses responsibility to see that this is called only when needed + * by keeping track of editor contents (eg. partitions). + * + * @param ids + */ + protected void contextTypeChanged(String[] ids) { + fActiveTypes = Arrays.asList(ids); + if (fLinkWithEditorAction != null && fLinkWithEditor) + refresh(); + } + + /** + * Initialize drag and drop the the template items + */ + private void initializeDND() { + DragSourceAdapter dragListener = new DragSourceAdapter() { + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DragSourceAdapter#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) + */ + public void dragSetData(DragSourceEvent event) { + if (isSingleTemplateSelected() + && TemplateTransfer.getInstance().isSupportedType(event.dataType)) { + event.data = new Template[] { getSelectedTemplate() }; + } + } + }; + fTreeViewer.addDragSupport(DND.DROP_COPY, + new Transfer[] { TemplateTransfer.getInstance() }, dragListener); + DropTargetAdapter dropListener = new DropTargetAdapter() { + TextTransfer textTransfer = TextTransfer.getInstance(); + TemplateTransfer templateTransfer = TemplateTransfer.getInstance(); + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void dragEnter(DropTargetEvent event) { + if (event.detail == DND.DROP_DEFAULT) + event.detail = DND.DROP_COPY; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void dragOperationChanged(DropTargetEvent event) { + if (event.detail == DND.DROP_DEFAULT) + event.detail = DND.DROP_COPY; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void dragOver(DropTargetEvent event) { + event.detail = DND.DROP_NONE; + if (event.item == null) + return; + int index = 0; + while (index < event.dataTypes.length) { + if (textTransfer.isSupportedType(event.dataTypes[index])) + break; + if (templateTransfer.isSupportedType(event.dataTypes[index])) + break; + index++; + } + if (index < event.dataTypes.length) { + event.currentDataType = event.dataTypes[index]; + event.detail = DND.DROP_COPY; + return; + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void drop(DropTargetEvent event) { + if (event.item == null) + return; + Object object = ((TreeItem) event.item).getData(); + String contextId; + if (object instanceof TemplateContextType) + contextId = ((TemplateContextType) object).getId(); + else + contextId = ((TemplatePersistenceData) object).getTemplate().getContextTypeId(); + if (textTransfer.isSupportedType(event.currentDataType)) { + String text = (String) event.data; + final Template template = new Template( + TextEditorTemplateMessages.TemplatesPage_snippet, + TextEditorTemplateMessages.TemplatesPage_paste_description, contextId, + text.replaceAll("\\$", "\\$\\$"), true); //$NON-NLS-1$//$NON-NLS-2$ + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + addTemplate(template, MAY_HIDE_DIALOG); + } + }); + } else if (templateTransfer.isSupportedType(event.currentDataType)) { + Template[] templates = (Template[]) event.data; + Template t = templates[0]; + final Template template = new Template(t.getName(), t.getDescription(), + contextId, t.getPattern(), true); + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + addTemplate(template, MAY_HIDE_DIALOG); + } + }); + } + } + + }; + fTreeViewer.addDropSupport(DND.DROP_COPY, new Transfer[] { TemplateTransfer.getInstance(), + TextTransfer.getInstance() }, dropListener); + } + + /** + * Setup the editor site as a drop target. Should be invoked by the + * subclasses for the D&D to work with the editor. + * + * @param site + * @param viewer + */ + protected void setupEditorDropTarget(IWorkbenchPartSite site, Control viewer) { + IDragAndDropService dndService = (IDragAndDropService) site + .getService(IDragAndDropService.class); + EditorDropTarget editorDropTarget = new EditorDropTarget(); + dndService.addMergedDropTarget(viewer, DND.DROP_COPY, new Transfer[] { TemplateTransfer + .getInstance() }, editorDropTarget); + } + + /** + * Refresh the template tree contents + */ + private void refresh() { + fTreeViewer.refresh(); + fTreeViewer.expandAll(); + decorateTemplates(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.Page#setFocus() + */ + public void setFocus() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.Page#dispose() + */ + public void dispose() { + if (fContextMenu != null && !fContextMenu.isDisposed()) + fContextMenu.dispose(); + fTemplatePreferenceStore.removePropertyChangeListener(fTemplateChangeListener); + savePreferences(); + super.dispose(); + } + + /** + * Save the preferences + */ + private void savePreferences() { + fPreferenceStore.setValue(SASH_SIZE_PREF_ID, fSashSize); + fPreferenceStore.setValue(LINK_ACTION_PREF_ID, fLinkWithEditor); + fPreferenceStore.setValue(SHOW_DISABLED_ACTION_PREF_ID, fShowDisabled); + fPreferenceStore.setValue(SHOW_NEW_DIALOG_ACTION_PREF_ID, fShowNewDialogOnDrop); + fPreferenceStore.setValue(COLUMN_NAME_WIDTH_PREF_ID, fNameWidth); + fPreferenceStore.setValue(COLUMN_DESCRIPTION_WIDTH_PREF_ID, fDescriptionWidth); + } +} Index: src/org/eclipse/ui/texteditor/templates/ITemplateViewImageConstants.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/templates/ITemplateViewImageConstants.java diff -N src/org/eclipse/ui/texteditor/templates/ITemplateViewImageConstants.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/templates/ITemplateViewImageConstants.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.templates; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; + +/** + * Image constants for the template page + * + * @author kd + * + * @since 3.4 + */ +public interface ITemplateViewImageConstants { + public static final String PREFIX_ELCL = TextEditorPlugin.PLUGIN_ID + ".elcl."; //$NON-NLS-1$ + public static final String PREFIX_DLCL = TextEditorPlugin.PLUGIN_ID + ".dlcl."; //$NON-NLS-1$ + public static final String PREFIX_OBJ = TextEditorPlugin.PLUGIN_ID + ".obj."; //$NON-NLS-1$ + + public final static String IMG_ELCL_TEMPLATE_NEW = PREFIX_ELCL + "new_template.gif"; //$NON-NLS-1$ + public static final String IMG_ELCL_TEMPLATE_DELETE = PREFIX_ELCL + "delete_template.gif"; //$NON-NLS-1$ + public final static String IMG_ELCL_TEMPLATE_EDIT = PREFIX_ELCL + "edit_template.gif"; //$NON-NLS-1$ + public static final String IMG_ELCL_TEMPLATE_LINK = PREFIX_ELCL + "link_to_editor.gif"; //$NON-NLS-1$ + public static final String IMG_ELCL_TEMPLATE_COLLAPSE_EXPAND = PREFIX_ELCL + "collapse_expand_all.gif"; //$NON-NLS-1$ + public static final String IMG_DLCL_TEMPLATE_DELETE = PREFIX_DLCL + "delete_template.gif"; //$NON-NLS-1$ + public final static String IMG_DLCL_TEMPLATE_EDIT = PREFIX_DLCL + "edit_template.gif"; //$NON-NLS-1$ + + public final static String IMG_OBJ_PREVIEW = PREFIX_OBJ + "preview.gif"; //$NON-NLS-1$ +} Index: src/org/eclipse/ui/texteditor/templates/TemplatesViewImages.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/templates/TemplatesViewImages.java diff -N src/org/eclipse/ui/texteditor/templates/TemplatesViewImages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/templates/TemplatesViewImages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.templates; + +import java.net.URL; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; +import org.osgi.framework.Bundle; + +/** + * The images provided by the texteditor plugin + * @since 3.4 + */ +public class TemplatesViewImages { + + /** + * The image registry containing Images. + */ + private static ImageRegistry imageRegistry; + + private static String ICONS_PATH = "$nl$/icons/full/"; //$NON-NLS-1$ + + // Use IPath and toOSString to build the names to ensure they have the + // slashes correct + private final static String ELCL = ICONS_PATH + "elcl16/"; //$NON-NLS-1$ + private final static String DLCL = ICONS_PATH + "dlcl16/"; //$NON-NLS-1$ + private final static String OBJ = ICONS_PATH + "obj16/"; //$NON-NLS-1$ + + /** + * Declare all images + */ + private static void declareImages() { + // Ant Editor images + declareRegistryImage(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_NEW, ELCL + + "new_template.gif"); //$NON-NLS-1$ + declareRegistryImage(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_DELETE, ELCL + + "delete_template.gif"); //$NON-NLS-1$ + declareRegistryImage(ITemplateViewImageConstants.IMG_DLCL_TEMPLATE_DELETE, DLCL + + "delete_template.gif"); //$NON-NLS-1$ + declareRegistryImage(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_EDIT, ELCL + + "edit_template.gif"); //$NON-NLS-1$ + declareRegistryImage(ITemplateViewImageConstants.IMG_DLCL_TEMPLATE_EDIT, DLCL + + "edit_template.gif"); //$NON-NLS-1$ + declareRegistryImage(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_LINK, ELCL + + "link_to_editor.gif"); //$NON-NLS-1$ + declareRegistryImage(ITemplateViewImageConstants.IMG_ELCL_TEMPLATE_COLLAPSE_EXPAND, ELCL + + "collapse_expand_all.gif"); //$NON-NLS-1$ + + declareRegistryImage(ITemplateViewImageConstants.IMG_OBJ_PREVIEW, OBJ + "preview.gif"); //$NON-NLS-1$ + } + + /** + * Declare an Image in the registry table. + * + * @param key + * The key to use when registering the image + * @param path + * The path where the image can be found. This path is relative + * to where this plugin class is found (i.e. typically the + * packages directory) + */ + private final static void declareRegistryImage(String key, String path) { + ImageDescriptor desc = ImageDescriptor.getMissingImageDescriptor(); + Bundle bundle = Platform.getBundle(TextEditorPlugin.PLUGIN_ID); + URL url = null; + if (bundle != null) { + url = FileLocator.find(bundle, new Path(path), null); + desc = ImageDescriptor.createFromURL(url); + } + imageRegistry.put(key, desc); + } + + /** + * Returns the ImageRegistry. + * + * @return image registry + */ + public static ImageRegistry getImageRegistry() { + if (imageRegistry == null) { + initializeImageRegistry(); + } + return imageRegistry; + } + + /** + * Initialize the image registry by declaring all of the required graphics. + * This involves creating JFace image descriptors describing how to + * create/find the image should it be needed. The image is not actually + * allocated until requested. + * + * Prefix conventions Wizard Banners WIZBAN_ Preference Banners PREF_BAN_ + * Property Page Banners PROPBAN_ Color toolbar CTOOL_ Enable toolbar ETOOL_ + * Disable toolbar DTOOL_ Local enabled toolbar ELCL_ Local Disable toolbar + * DLCL_ Object large OBJL_ Object small OBJS_ View VIEW_ Product images + * PROD_ Misc images MISC_ + * + * Where are the images? The images (typically gifs) are found in the same + * location as this plugin class. This may mean the same package directory + * as the package holding this class. The images are declared using + * this.getClass() to ensure they are looked up via this plugin class. + * + * @return the image registry + * @see org.eclipse.jface.resource.ImageRegistry + */ + public static ImageRegistry initializeImageRegistry() { + imageRegistry = new ImageRegistry(getStandardDisplay()); + declareImages(); + return imageRegistry; + } + + /** + * Returns the standard display to be used. The method first checks, if the + * thread calling this method has an associated display. If so, this display + * is returned. Otherwise the method returns the default display. + * + * @return the display + */ + public static Display getStandardDisplay() { + Display display = Display.getCurrent(); + if (display == null) { + display = Display.getDefault(); + } + return display; + } + + /** + * Returns the Image identified by the given key, + * or null if it does not exist. + * @param key + * @return the image + */ + public static Image getImage(String key) { + return getImageRegistry().get(key); + } + + /** + * Returns the ImageDescriptor identified by the given key, + * or null if it does not exist. + * @param key + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String key) { + return getImageRegistry().getDescriptor(key); + } + +} Index: src/org/eclipse/ui/texteditor/templates/TemplateTransfer.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/templates/TemplateTransfer.java diff -N src/org/eclipse/ui/texteditor/templates/TemplateTransfer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/templates/TemplateTransfer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 Dakshinamurthy Karra and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Dakshinamurthy Karra - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.templates; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.jface.text.templates.Template; +import org.eclipse.swt.dnd.ByteArrayTransfer; +import org.eclipse.swt.dnd.TransferData; + +/** + * Transfer type used for clip board and DnD operations for template objects + * + * @see TemplatesPage + * + * @since 3.4 + */ +public class TemplateTransfer extends ByteArrayTransfer { + + private static TemplateTransfer instance; + + private static final String LOCAL_NAME = TemplateTransfer.class.getName() + + System.currentTimeMillis(); + private static final int LOCAL_TYPE = registerType(LOCAL_NAME); + + private static String[] names = null; + private static int types[] = null; + + /** + * @return the registered Transfer instance + */ + public static TemplateTransfer getInstance() { + if (instance == null) { + instance = new TemplateTransfer(); + types = new int[] { LOCAL_TYPE }; + names = new String[] { LOCAL_NAME }; + } + return instance; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.Transfer#getTypeIds() + */ + protected int[] getTypeIds() { + return types; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.Transfer#getTypeNames() + */ + protected String[] getTypeNames() { + return names; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.ByteArrayTransfer#javaToNative(java.lang.Object, + * org.eclipse.swt.dnd.TransferData) + */ + protected void javaToNative(Object object, TransferData transferData) { + if (object == null || !(object instanceof Template[]) + || !isSupportedType(transferData)) + return; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + DataOutputStream dataOut = new DataOutputStream(out); + Template[] templates = (Template[]) object; + for (int i = 0; i < templates.length; i++) { + writeTemplate(dataOut, templates[i]); + } + byte[] byteArray = out.toByteArray(); + try { + dataOut.close(); + } catch (IOException e) { + } + super.javaToNative(byteArray, transferData); + } + + /** + * Write a template to the output stream + * + * @param dataOut + * @param template + */ + private void writeTemplate(DataOutputStream dataOut, Template template) { + try { + writeString(dataOut, template.getName()); + writeString(dataOut, template.getDescription()); + writeString(dataOut, template.getContextTypeId()); + writeString(dataOut, template.getPattern()); + dataOut.writeBoolean(template.isAutoInsertable()); + } catch (IOException e) { + } + } + + /** + * Write a string to the output stream + * + * @param dataOut + * @param name + * @throws IOException + */ + private void writeString(DataOutputStream dataOut, String name) + throws IOException { + byte[] bytes = name.getBytes(); + dataOut.writeInt(bytes.length); + dataOut.write(bytes); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(org.eclipse.swt.dnd.TransferData) + */ + protected Object nativeToJava(TransferData transferData) { + byte[] bytes = (byte[]) super.nativeToJava(transferData); + if (bytes == null) + return null; + ArrayList listTemplates = new ArrayList(); + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + DataInputStream dataIn = new DataInputStream(in); + try { + while (dataIn.available() > 0) { + Template template = readTempate(dataIn); + if (template == null) + break; + listTemplates.add(template); + } + } catch (IOException e) { + } finally { + try { + dataIn.close(); + } catch (IOException e) { + } + } + return listTemplates.toArray(new Template[listTemplates.size()]); + } + + /** + * Read a template from the data input stream. + * + * @param dataIn + * @return the template + * @throws IOException + */ + private Template readTempate(DataInputStream dataIn) throws IOException { + return new Template(readString(dataIn), readString(dataIn), + readString(dataIn), readString(dataIn), dataIn.readBoolean()); + } + + /** + * Read a string from the data input stream + * + * @param dataIn + * @return the string + * @throws IOException + */ + private String readString(DataInputStream dataIn) throws IOException { + byte[] bytes = new byte[dataIn.readInt()]; + dataIn.read(bytes); + return new String(bytes); + } +}