### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.ui 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.435 diff -u -r1.435 JavaEditor.java --- ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java 20 Sep 2007 14:52:25 -0000 1.435 +++ ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java 25 Sep 2007 13:06:50 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Dakshinamurthy Karra (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 *******************************************************************************/ package org.eclipse.jdt.internal.ui.javaeditor; @@ -135,6 +136,7 @@ import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.TextNavigationAction; import org.eclipse.ui.texteditor.TextOperationAction; +import org.eclipse.ui.texteditor.templates.view.ITemplatesPage; import org.eclipse.ui.editors.text.DefaultEncodingSupport; import org.eclipse.ui.editors.text.EditorsUI; @@ -197,6 +199,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; @@ -1336,6 +1339,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. * @@ -1798,6 +1807,10 @@ return fOutlinePage; } + if (required.equals(ITemplatesPage.class)) { + return getTemplatesPage(); + } + if (IEncodingSupport.class.equals(required)) return fEncodingSupport; @@ -1853,6 +1866,17 @@ } /** + * @since 3.4 + */ + private JavaTemplatesPage getTemplatesPage() { + if (fTemplatesPage == null) { + fTemplatesPage= new JavaTemplatesPage(this); + + } + return fTemplatesPage; + } + + /** * React to changed selection. * * @since 3.0 Index: ui/org/eclipse/jdt/internal/ui/JavaPerspectiveFactory.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaPerspectiveFactory.java,v retrieving revision 1.44 diff -u -r1.44 JavaPerspectiveFactory.java --- ui/org/eclipse/jdt/internal/ui/JavaPerspectiveFactory.java 29 May 2007 18:41:36 -0000 1.44 +++ ui/org/eclipse/jdt/internal/ui/JavaPerspectiveFactory.java 25 Sep 2007 13:06:33 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Dakshinamurthy Karra (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 *******************************************************************************/ package org.eclipse.jdt.internal.ui; @@ -45,7 +46,9 @@ outputfolder.addPlaceholder(IPageLayout.ID_BOOKMARKS); outputfolder.addPlaceholder(IProgressConstants.PROGRESS_VIEW_ID); - layout.addView(IPageLayout.ID_OUTLINE, IPageLayout.RIGHT, (float)0.75, editorArea); + IFolderLayout outlineFolder = layout.createFolder("right", IPageLayout.RIGHT, (float)0.75, editorArea); //$NON-NLS-1$ + outlineFolder.addView(IPageLayout.ID_OUTLINE); + outlineFolder.addView(IPageLayout.ID_TEMPLATES); layout.addActionSet(IDebugUIConstants.LAUNCH_ACTION_SET); layout.addActionSet(JavaUI.ID_ACTION_SET); @@ -66,6 +69,7 @@ // views - standard workbench layout.addShowViewShortcut(IPageLayout.ID_OUTLINE); + layout.addShowViewShortcut(IPageLayout.ID_TEMPLATES); layout.addShowViewShortcut(IPageLayout.ID_PROBLEM_VIEW); layout.addShowViewShortcut(IPageLayout.ID_RES_NAV); layout.addShowViewShortcut(IPageLayout.ID_TASK_LIST); 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,387 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.jdt.internal.ui.preferences; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +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.ITextViewerExtension; +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.DocumentTemplateContext; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.jface.text.templates.persistence.TemplateStore; + +import org.eclipse.ui.texteditor.templates.view.TemplatesPage; + +import org.eclipse.jdt.core.ICompilationUnit; + +import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContextType; +import org.eclipse.jdt.internal.corext.template.java.JavaContext; +import org.eclipse.jdt.internal.corext.template.java.JavaContextType; +import org.eclipse.jdt.internal.corext.template.java.JavaDocContext; +import org.eclipse.jdt.internal.corext.template.java.JavaDocContextType; +import org.eclipse.jdt.internal.corext.template.java.SWTContextType; + +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.JavaPluginImages; +import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; +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; + +/** + * An implementation of TemplatesPage for JavaEditor + */ +public class JavaTemplatesPage extends TemplatesPage { + + private static final String PREFERENCE_PAGE_ID= "org.eclipse.jdt.ui.preferences.JavaTemplatePreferencePage"; //$NON-NLS-1$ + private static final TemplateStore TEMPLATE_STORE= JavaPlugin.getDefault().getTemplateStore(); + private static final IPreferenceStore PREFERENCE_STORE= JavaPlugin.getDefault().getPreferenceStore(); + private static final ContextTypeRegistry TEMPLATE_CONTEXT_REGISTRY= JavaPlugin.getDefault().getTemplateContextRegistry(); + + private TemplateVariableProcessor fTemplateProcessor; + + /** + * Create a new TemplatesPage for the JavaEditor + * + * @param javaEditor + */ + public JavaTemplatesPage(JavaEditor javaEditor) { + super(javaEditor, javaEditor.getViewer()); + fTemplateProcessor= new TemplateVariableProcessor(); + updateContextTypes(getContextTypes()); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#insertTemplate(org.eclipse.jface.text.templates.Template, org.eclipse.swt.graphics.Point) + */ + protected void insertTemplate(Template template, Point dropPosition) { + if (!getJavaEditor().validateEditorInputState()) + return; + ISourceViewer contextViewer= getJavaEditor().getViewer(); + ITextSelection textSelection= (ITextSelection) contextViewer.getSelectionProvider().getSelection(); + IDocument document= getJavaEditor().getDocumentProvider().getDocument(getJavaEditor().getEditorInput()); + if (!isValidTemplate(document, template, textSelection.getOffset(), textSelection.getLength())) + return; + beginCompoundChange(contextViewer); + /* + * 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. + * Another advantage by this method is that the template replaces the selected text provided the + * selection by itself is not used in the template pattern. + */ + String savedText; + try { + savedText= document.get(textSelection.getOffset(), textSelection.getLength()); + if (savedText.length() == 0) { + String prefix= getIdentifierPart(document, template, textSelection.getOffset(), textSelection.getLength()); + 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) { + endCompoundChange(contextViewer); + 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= (ICompilationUnit) EditorUtility.getEditorInputJavaElement(getJavaEditor(), true); + + TemplateContextType type= getContextTypeRegistry().getContextType(template.getContextTypeId()); + DocumentTemplateContext 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) { + endCompoundChange(contextViewer); + return; + } + } + TemplateProposal proposal= new TemplateProposal(template, context, region, null); + getJavaEditor().getSite().getPage().activate(getJavaEditor()); + proposal.apply(getJavaEditor().getViewer(), ' ', 0, region.getOffset()); + endCompoundChange(contextViewer); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#getContextTypeRegistry() + */ + protected ContextTypeRegistry getContextTypeRegistry() { + return TEMPLATE_CONTEXT_REGISTRY; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#getTemplatePreferenceStore() + */ + protected IPreferenceStore getTemplatePreferenceStore() { + return PREFERENCE_STORE; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#getTemplateStore() + */ + protected TemplateStore getTemplateStore() { + return TEMPLATE_STORE; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#isValidTemplate(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.templates.Template, int, int) + */ + protected boolean isValidTemplate(IDocument document, Template template, int offset, int length) { + try { + String[] contextIds= getContextIds(document, offset); + for (int i= 0; i < contextIds.length; i++) { + if (contextIds[i].equals(template.getContextTypeId())) { + DocumentTemplateContext context= getContext(document, template, offset, length); + return context.canEvaluate(template) || isTemplateAllowed(context, template); + } + } + } catch (BadLocationException e) { + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#createPatternViewer(org.eclipse.swt.widgets.Composite) + */ + protected SourceViewer createPatternViewer(Composite parent) { + IDocument document= new Document(); + JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools(); + tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING); + IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore(); + JavaSourceViewer 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); + + viewer.setEditable(false); + return viewer; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#getImageForTemplate(org.eclipse.jface.text.templates.Template) + */ + protected Image getImageForTemplate(Template template) { + if (template.getContextTypeId().equals(SWTContextType.ID)) + return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_SWT_TEMPLATE); + return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_TEMPLATE); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#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, getContextTypeRegistry()); + if (dialog.open() == Window.OK) { + return dialog.getTemplate(); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#getContextTypes() + */ + protected String[] getContextTypes() { + Point selectedRange= getJavaEditor().getViewer().getSelectedRange(); + int offset= selectedRange.x + selectedRange.y; + try { + IDocument document= getJavaEditor().getDocumentProvider().getDocument(getJavaEditor().getEditorInput()); + return getContextIds(document, offset); + } catch (BadLocationException e) { + return new String[0]; + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#updatePatternViewer(org.eclipse.jface.text.templates.Template) + */ + protected void updatePatternViewer(Template template) { + if (template == null) { + getPatternViewer().getDocument().set(""); //$NON-NLS-1$ + return ; + } + String contextId= template.getContextTypeId(); + TemplateContextType type= getContextTypeRegistry().getContextType(contextId); + fTemplateProcessor.setContextType(type); + + IDocument doc= getPatternViewer().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(); + getPatternViewer().setDocument(doc, startLen, doc.getLength() - startLen); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.templates.TemplatesPage#getPreferencePageId() + */ + protected String getPreferencePageId() { + return PREFERENCE_PAGE_ID; + } + + /** + * Helper function to return the JavaEditor + * + * @return the editor + */ + private JavaEditor getJavaEditor() { + return (JavaEditor)getEditor() ; + } + + /** + * Undomanager - end compound change + * @param viewer + */ + private void endCompoundChange(ISourceViewer viewer) { + if (viewer instanceof ITextViewerExtension) + ((ITextViewerExtension) viewer).getRewriteTarget().endCompoundChange(); + } + + /** + * Undomanager - begin a compound change + * @param viewer + */ + private void beginCompoundChange(ISourceViewer viewer) { + if (viewer instanceof ITextViewerExtension) + ((ITextViewerExtension) viewer).getRewriteTarget().beginCompoundChange(); + } + + /** + * Check whether the template is allowed eventhough the context can't evaluate it. This is needed because + * the Dropping of a template is more lenient than ctl-space invoked code assist. + * + * @param context + * @param template + * @return true if the template is allowed + */ + private boolean isTemplateAllowed(DocumentTemplateContext context, Template template) { + int offset; + try { + if (template.getContextTypeId().equals(JavaDocContextType.ID)) { + return (offset= context.getCompletionOffset()) > 0 && Character.isWhitespace(context.getDocument().getChar(offset - 1)); + } else { + return ((offset= context.getCompletionOffset()) > 0 && !isTemplateNamePart(context.getDocument().getChar(offset - 1))); + } + } catch (BadLocationException e) { + } + return false; + } + + /** + * Checks whether the character is a valid character in Java template names + * + * @param ch + * @return true or false + */ + private boolean isTemplateNamePart(char ch) { + return !Character.isWhitespace(ch) && ch != '(' && ch != ')' && ch != '{' && ch != '}' && ch != ';'; + } + + /** + * Get context + * + * @param document + * @param template + * @param offset + * @param length + * @return the context + */ + private DocumentTemplateContext getContext(IDocument document, Template template, final int offset, int length) { + DocumentTemplateContext context; + if (template.getContextTypeId().equals(JavaDocContextType.ID)) { + context= new JavaDocContext(getContextTypeRegistry().getContextType(template.getContextTypeId()), document, new Position(offset, length), (ICompilationUnit) EditorUtility + .getEditorInputJavaElement(getJavaEditor(), true)); + } else { + context= new JavaContext(getContextTypeRegistry().getContextType(template.getContextTypeId()), document, new Position(offset, length), (ICompilationUnit) EditorUtility.getEditorInputJavaElement( + getJavaEditor(), true)); + } + return context; + } + + /** + * Get the active contexts for the given position in the document + * + * @param document + * @param offset + * @return an array of valid context id + * @throws BadLocationException + */ + private String[] getContextIds(IDocument document, int offset) throws BadLocationException { + String partition= TextUtilities.getContentType(document, IJavaPartitions.JAVA_PARTITIONING, offset, true); + String[] ids= new String[] { JavaContextType.ID, SWTContextType.ID }; + if (partition.equals(IJavaPartitions.JAVA_DOC)) + ids= new String[] { JavaDocContextType.ID }; + return ids; + } + + /** + * Get the java identifier terminated at the given offset + * + * @param document + * @param template + * @param offset + * @param length + * @return the identifier part + * @throws BadLocationException + */ + private String getIdentifierPart(IDocument document, Template template, int offset, int length) throws BadLocationException { + return getContext(document, template, offset, length).getKey(); + } +} #P org.eclipse.ui.workbench.texteditor Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/plugin.xml,v retrieving revision 1.91 diff -u -r1.91 plugin.xml --- plugin.xml 2 May 2007 20:23:35 -0000 1.91 +++ plugin.xml 25 Sep 2007 13:07:05 -0000 @@ -1102,4 +1102,15 @@ + + + + + Index: plugin.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/plugin.properties,v retrieving revision 1.47 diff -u -r1.47 plugin.properties --- plugin.properties 15 Mar 2007 10:25:00 -0000 1.47 +++ plugin.properties 25 Sep 2007 13:06:58 -0000 @@ -7,6 +7,7 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Dakshinamurthy Karra (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 ############################################################################### pluginName= Text Editor Framework providerName= Eclipse.org @@ -169,3 +170,5 @@ SpellingEngine= Spelling Engine +Views.Templates = Templates + Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF,v retrieving revision 1.19 diff -u -r1.19 MANIFEST.MF --- META-INF/MANIFEST.MF 6 Aug 2007 13:19:00 -0000 1.19 +++ META-INF/MANIFEST.MF 25 Sep 2007 13:07:05 -0000 @@ -14,12 +14,14 @@ org.eclipse.ui.internal.texteditor.quickdiff.compare.rangedifferencer;x-internal:=true, org.eclipse.ui.internal.texteditor.rulers;x-internal:=true, org.eclipse.ui.internal.texteditor.spelling;x-internal:=true, + org.eclipse.ui.internal.texteditor.templates.view, org.eclipse.ui.texteditor, org.eclipse.ui.texteditor.link, org.eclipse.ui.texteditor.quickdiff, org.eclipse.ui.texteditor.rulers, org.eclipse.ui.texteditor.spelling, - org.eclipse.ui.texteditor.templates + org.eclipse.ui.texteditor.templates, + org.eclipse.ui.texteditor.templates.view Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)", 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.56 diff -u -r1.56 TemplatePreferencePage.java --- src/org/eclipse/ui/texteditor/templates/TemplatePreferencePage.java 12 Sep 2007 08:20:10 -0000 1.56 +++ src/org/eclipse/ui/texteditor/templates/TemplatePreferencePage.java 25 Sep 2007 13:07:11 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Dakshinamurthy Karra (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 *******************************************************************************/ package org.eclipse.ui.texteditor.templates; @@ -136,7 +137,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/internal/texteditor/templates/view/TemplatesPageImages.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageImages.java diff -N src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageImages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageImages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.templates.view; + +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.ui.internal.texteditor.TextEditorPlugin; +import org.osgi.framework.Bundle; + +/** + * The images used by TemplatesPage + * + * @since 3.4 + */ +public class TemplatesPageImages { + + static final String PREFIX_ELCL = TextEditorPlugin.PLUGIN_ID + ".elcl."; //$NON-NLS-1$ + static final String PREFIX_DLCL = TextEditorPlugin.PLUGIN_ID + ".dlcl."; //$NON-NLS-1$ + static final String PREFIX_OBJ = TextEditorPlugin.PLUGIN_ID + ".obj."; //$NON-NLS-1$ + + public static final 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 static final String IMG_ELCL_TEMPLATE_EDIT = PREFIX_ELCL + "edit_template.gif"; //$NON-NLS-1$ + public static final String IMG_ELCL_TEMPLATE_INSERT = PREFIX_ELCL + "insert_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_ALL = PREFIX_ELCL + "collapseall.gif"; //$NON-NLS-1$ + public static final String IMG_DLCL_TEMPLATE_DELETE = PREFIX_DLCL + "delete_template.gif"; //$NON-NLS-1$ + public static final String IMG_DLCL_TEMPLATE_EDIT = PREFIX_DLCL + "edit_template.gif"; //$NON-NLS-1$ + public static final String IMG_DLCL_TEMPLATE_INSERT = PREFIX_DLCL + "insert_template.gif"; //$NON-NLS-1$ + + public static final String IMG_OBJ_PREVIEW = PREFIX_OBJ + "preview.gif"; //$NON-NLS-1$ + public static final String IMG_OBJ_CONTEXT = PREFIX_OBJ + "context.gif"; //$NON-NLS-1$ + public static final String IMG_OBJ_TEMPLATE = PREFIX_OBJ + "template_obj.gif"; //$NON-NLS-1$ + + /** + * 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(IMG_ELCL_TEMPLATE_NEW, ELCL + "new_template.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_ELCL_TEMPLATE_INSERT, ELCL + "insert_template.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_DLCL_TEMPLATE_INSERT, DLCL + "insert_template.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_ELCL_TEMPLATE_DELETE, ELCL + "delete_template.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_DLCL_TEMPLATE_DELETE, DLCL + "delete_template.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_ELCL_TEMPLATE_EDIT, ELCL + "edit_template.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_DLCL_TEMPLATE_EDIT, DLCL + "edit_template.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_ELCL_TEMPLATE_LINK, ELCL + "link_to_editor.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_ELCL_TEMPLATE_COLLAPSE_ALL, ELCL + "collapseall.gif"); //$NON-NLS-1$ + + declareRegistryImage(IMG_OBJ_PREVIEW, OBJ + "preview.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_OBJ_CONTEXT, OBJ + "context.gif"); //$NON-NLS-1$ + declareRegistryImage(IMG_OBJ_TEMPLATE, OBJ + "template_obj.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 = TextEditorPlugin.getDefault().getImageRegistry(); + declareImages(); + return imageRegistry; + } + + /** + * 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/internal/texteditor/templates/view/TemplatesViewMessages.properties =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesViewMessages.properties diff -N src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesViewMessages.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesViewMessages.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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 +############################################################################### +Templates_defaultMessage=Templates are not available. Index: src/org/eclipse/ui/texteditor/templates/view/TemplatesView.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/templates/view/TemplatesView.java diff -N src/org/eclipse/ui/texteditor/templates/view/TemplatesView.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/templates/view/TemplatesView.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,247 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.ui.texteditor.templates.view; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.PlatformObject; +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.texteditor.templates.view.TemplatesViewMessages; +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 are not available. 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 templates 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 TemplatesView extends PageBookView { + /** + * The plugin prefix. + */ + public static final String PREFIX = PlatformUI.PLUGIN_ID + "."; //$NON-NLS-1$ + + /** + * Help context id used for the templates view + */ + public static final String TEMPLATES_VIEW_HELP_CONTEXT_ID = PREFIX + + "templates_view_context";//$NON-NLS-1$ + + /** + * Message to show on the default page. + */ + private static final String DEFAULT_TEXT = TemplatesViewMessages.Templates_defaultMessage; + + /** + * Creates a templates view + */ + public TemplatesView() { + super(); + } + + /* (non-Javadoc) + * Method declared on PageBookView. + */ + protected IPage createDefaultPage(PageBook book) { + MessagePage page = new MessagePage(); + initPage(page); + page.createControl(book); + page.setMessage(DEFAULT_TEXT); + return page; + } + + /** + * The PageBookView implementation of this IWorkbenchPart + * method creates a PageBook control with its default page showing. + * @param parent + */ + 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 = 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); + } + + /** + * If it is possible to adapt the given object to the given type, this + * returns the adapter. Performs the following checks: + * + *
    + *
  1. Returns sourceObject if it is an instance of the + * adapter type.
  2. + *
  3. If sourceObject implements IAdaptable, it is queried for adapters.
  4. + *
  5. If sourceObject is not an instance of PlatformObject (which would have + * already done so), the adapter manager is queried for adapters
  6. + *
+ * + * Otherwise returns null. + * + * @param sourceObject + * object to adapt, or null + * @param adapter + * type to adapt to + * @param activatePlugins + * true if IAdapterManager.loadAdapter should be used (may trigger plugin activation) + * @return a representation of sourceObject that is assignable to the + * adapter type, or null if no such representation exists + */ + private Object getAdapter(Object sourceObject, Class adapter, boolean activatePlugins) { + Assert.isNotNull(adapter); + if (sourceObject == null) { + return null; + } + if (adapter.isInstance(sourceObject)) { + return sourceObject; + } + + if (sourceObject instanceof IAdaptable) { + IAdaptable adaptable = (IAdaptable) sourceObject; + + Object result = adaptable.getAdapter(adapter); + if (result != null) { + // Sanity-check + Assert.isTrue(adapter.isInstance(result)); + return result; + } + } + + if (!(sourceObject instanceof PlatformObject)) { + Object result; + if (activatePlugins) { + result = Platform.getAdapterManager().loadAdapter(sourceObject, adapter.getName()); + } else { + result = Platform.getAdapterManager().getAdapter(sourceObject, adapter); + } + if (result != null) { + return result; + } + } + + return null; + } + +} Index: src/org/eclipse/ui/internal/texteditor/templates/view/TemplateTransfer.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/templates/view/TemplateTransfer.java diff -N src/org/eclipse/ui/internal/texteditor/templates/view/TemplateTransfer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/templates/view/TemplateTransfer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.templates.view; + +import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; +import org.eclipse.swt.dnd.ByteArrayTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.ui.texteditor.templates.view.TemplatesPage; + +/** + * 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; + + private TemplatePersistenceData[] fObject ; + + /** + * @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 TemplatePersistenceData[]) + || !isSupportedType(transferData)) { + fObject = null ; + return; + } + fObject = (TemplatePersistenceData[]) object ; + super.javaToNative(LOCAL_NAME.getBytes(), transferData); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(org.eclipse.swt.dnd.TransferData) + */ + protected Object nativeToJava(TransferData transferData) { + Object result = super.nativeToJava(transferData); + if (!(result instanceof byte[]) + || !LOCAL_NAME.equals(new String((byte[]) result))) + return null ; + return fObject ; + } +} Index: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.java diff -N src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.templates.view; + +import org.eclipse.osgi.util.NLS; + +/** + * Helper class to get NLSed messages. + * + * @since 3.4 + */ +public final class TemplatesPageMessages extends NLS { + + private static final String BUNDLE_NAME= TemplatesPageMessages.class.getName(); + private TemplatesPageMessages() { + // 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_copy; + public static String TemplatesPage_paste; + public static String TemplatesPage_preference_page; + public static String TemplatesPage_link_to_editor; + public static String TemplatesPage_collapse_all; + public static String TemplatesPage_new; + public static String TemplatesPage_remove; + 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_all_tooltip; + public static String TemplatesPage_new_tooltip; + public static String TemplatesPage_remove_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_remove_message_single; + public static String TemplatesPage_remove_message_multi; + public static String TemplatesPage_remove_title_single; + public static String TemplatesPage_remove_title_multi; + + static { + NLS.initializeMessages(BUNDLE_NAME, TemplatesPageMessages.class); + } + +} Index: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.properties =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.properties diff -N src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesPageMessages.properties 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,41 @@ +############################################################################### +# Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 +############################################################################### + +# templates page (view) +TemplatesPage_collapse_all=Collapse All +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_copy=Copy +TemplatesPage_paste=Paste +TemplatesPage_preference_page=&Preferences... +TemplatesPage_paste_description=Pasted from editor +TemplatesPage_link_to_editor=Link with 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_remove_title_single=Removing Template +TemplatesPage_remove_title_multi=Removing Templates +TemplatesPage_remove_message_single=Are you sure you want to remove the selected template? +TemplatesPage_remove_message_multi=Are you sure you want to remove {0} selected templates? +TemplatesPage_question_create_new_title= Edit Template +TemplatesPage_remove=&Remove +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_all_tooltip=Collapse All +TemplatesPage_new_tooltip=Create a New Template +TemplatesPage_remove_tooltip=Remove the Template Index: src/org/eclipse/ui/texteditor/templates/view/ITemplatesPage.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/templates/view/ITemplatesPage.java diff -N src/org/eclipse/ui/texteditor/templates/view/ITemplatesPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/templates/view/ITemplatesPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.ui.texteditor.templates.view; + +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 in a pagebook + * view. (implement IPageBookViewPage). + * + * @see TemplatesView + * @since 3.4 + */ +public interface ITemplatesPage extends IPageBookViewPage { +} Index: src/org/eclipse/ui/texteditor/templates/view/TemplatesPage.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/templates/view/TemplatesPage.java diff -N src/org/eclipse/ui/texteditor/templates/view/TemplatesPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/templates/view/TemplatesPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1610 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.ui.texteditor.templates.view; + +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.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewerExtension5; +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.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.AbstractTreeViewer; +import org.eclipse.jface.viewers.ColumnPixelData; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IPostSelectionProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +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.StyledText; +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.Image; +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.swt.widgets.Event; +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.actions.ActionFactory; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.dnd.IDragAndDropService; +import org.eclipse.ui.internal.texteditor.NLSUtility; +import org.eclipse.ui.internal.texteditor.PixelConverter; +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; +import org.eclipse.ui.internal.texteditor.templates.view.TemplateTransfer; +import org.eclipse.ui.internal.texteditor.templates.view.TemplatesPageImages; +import org.eclipse.ui.internal.texteditor.templates.view.TemplatesPageMessages; +import org.eclipse.ui.part.Page; +import org.eclipse.ui.texteditor.AbstractTextEditor; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; +import org.eclipse.ui.texteditor.templates.TemplatePreferencePage.EditTemplateDialog; + +import com.ibm.icu.text.Collator; + +/** + * An abstract base class for template pages. + *

+ * 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 by + * clients. + *

+ *

+ * 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 implements ITemplatesPage { + + /** + * 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$ + + /** + * Context expand/collapse setting prefix + */ + private static final String CONTEXT_COLLAPSE_PREF_ID = TextEditorPlugin.PLUGIN_ID + + "templates.templatesPage.context.expand."; //$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$ + + /** + * Default image for a template + */ + private static final Image DEFAULT_TEMPLATE_IMAGE = TemplatesPageImages + .getImage(TemplatesPageImages.IMG_OBJ_TEMPLATE); + /** + * Image for the context + */ + private static final Image CONTEXT_IMAGE = TemplatesPageImages + .getImage(TemplatesPageImages.IMG_OBJ_CONTEXT); + + /** + * A post selection changed listener for the editor. Depending on the caret + * position updates the templates + */ + private final class SelectionChangedListener implements ISelectionChangedListener { + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + String[] contextTypes = getContextTypes(); + if (needUpdate(contextTypes)) { + fCurrentContextTypes = contextTypes; + updateContextTypes(fCurrentContextTypes); + return; + } + } + + /** + * Check whether an update of the TemplatesPage is needed + * + * @param contextTypes + * @return true if update is needed + */ + private boolean needUpdate(String[] contextTypes) { + return fCurrentContextTypes == null + || fCurrentContextTypes.length != contextTypes.length + || contextTypeChanged(contextTypes); + } + + /** + * Check whether there is any change in the context types needed + * + * @param contextTypes + * @return true if any of the context types changed + */ + private boolean contextTypeChanged(String[] contextTypes) { + for (int i = 0; i < contextTypes.length; i++) { + if (!contextTypes[i].equals(fCurrentContextTypes[i])) + return false; + } + return true; + } + } + + /** + * 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) { + event.detail = DND.DROP_COPY; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void dragOperationChanged(DropTargetEvent event) { + 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; + event.detail = DND.DROP_NONE; + TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); + if (fEditor.isEditorInputModifiable() + && selectedTemplates.length == 1 + && isValidTemplateForPosition(selectedTemplates[0].getTemplate(), new Point( + event.x, event.y))) + event.detail = DND.DROP_COPY; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent) + */ + public void drop(DropTargetEvent event) { + TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); + insertTemplate(selectedTemplates[0].getTemplate(), new Point(event.x, event.y)); + // The highlight of the item is removed once the drop happens - + // restore it + fTreeViewer.setSelection(new StructuredSelection(selectedTemplates), true); + } + } + + /** + * 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 = Collator.getInstance().compare(left.getName(), right.getName()); + if (result != 0) + return result; + return Collator.getInstance() + .compare(left.getDescription(), right.getDescription()); + } + if ((object1 instanceof TemplateContextType) + && (object2 instanceof TemplateContextType)) { + return Collator.getInstance().compare(((TemplateContextType) object1).getName(), + ((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 false; + } + } + + /** + * Label provider for templates. + */ + private final class TemplateLabelProvider extends LabelProvider implements ITableLabelProvider { + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, + * int) + */ + public Image getColumnImage(Object element, int columnIndex) { + if (columnIndex != 0) + return null; + if (element instanceof TemplateContextType) + return CONTEXT_IMAGE; + return getImageForTemplate(((TemplatePersistenceData) element).getTemplate()); + } + + /* + * (non-Javadoc) + * + * @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, columnIndex); + return getContextColumnText((TemplateContextType) element, columnIndex); + } + + private String getTemplateColumnText(TemplatePersistenceData data, int columnIndex) { + switch (columnIndex) { + case 0: + return data.getTemplate().getName(); + case 1: + return data.getTemplate().getDescription(); + default: + return ""; //$NON-NLS-1$ + } + } + + private String getContextColumnText(TemplateContextType contextType, int columnIndex) { + switch (columnIndex) { + case 0: + return contextType.getName(); + default: + return ""; //$NON-NLS-1$ + } + } + } + + /** + * Content provider for templates. Provides all the enabled templates + * defined for this editor. + */ + private final 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; + } + + private TemplatePersistenceData[] getTemplates(String contextId) { + List templateList = new ArrayList(); + TemplatePersistenceData[] datas = getTemplateStore().getTemplateData(false); + for (int i = 0; i < datas.length; i++) { + if (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 getContextTypeRegistry().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 = getContextTypeRegistry().contextTypes(); iterator.hasNext();) { + TemplateContextType contextType = (TemplateContextType) iterator.next(); + if (!fLinkWithEditorAction.isChecked() || isActiveContext(contextType)) + contextTypes.add(contextType); + } + return contextTypes.toArray(new TemplateContextType[contextTypes.size()]); + } + + 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) { + } + } + + /* The editor */ + private final AbstractTextEditor fEditor; + /* The SourceViewer attached to this editor */ + private final ISourceViewer fViewer; + + /* Listener to monitor changes to template store */ + private IPropertyChangeListener fTemplateChangeListener; + + /* Control for this pagebook view */ + private SashForm fControl; + + /* Actions */ + private Action fInsertAction; + private Action fAddAction; + private Action fEditAction; + private Action fRemoveAction; + private Action fLinkWithEditorAction; + private Action fCollapseAllAction; + private Action fPreferencePageAction; + + /* Clipboard actions */ + private Action fPasteAction; + private Action fCopyAction; + + /* Current active context types for the editor */ + private List fActiveTypes; + + /* Preference stores */ + private IPreferenceStore fPreferenceStore; + + /* Controls */ + private Tree fTemplatesTree; + private TreeViewer fTreeViewer; + private Menu fContextMenu; + + /* Current selection */ + private TemplatePersistenceData[] fSelectedTemplates = new TemplatePersistenceData[0]; + + /* The pattern viewer to be used with this view */ + private SourceViewer fPatternViewer; + + /* Cached results for avoiding processing while drag-over the editor */ + private int fCachedOffset; + private boolean fCachedResult; + private Point fCachedPosition; + + /* The current context types */ + protected String[] fCurrentContextTypes; + + /* The selection changed listener to monitor the editor selections */ + private SelectionChangedListener fSelectionChangedListener; + + /* Paste action support for the editor */ + private IAction fEditorOldPasteAction; + private IAction fEditorPasteAction; + + /** + * Creates a new template view page. + * + * @param editor + * @param viewer + */ + protected TemplatesPage(AbstractTextEditor editor, ISourceViewer viewer) { + super(); + fEditor = editor; + fViewer = viewer; + setupPreferenceStore(); + setupEditorDropTarget(); + setupSelectionProvider(); + setupPasteOperation(); + } + + /* + * (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(fControl); + createPatternForm(fControl); + + hookContextMenu(); + initializeDND(); + updateButtons(); + + int sashSize = fPreferenceStore.getInt(SASH_SIZE_PREF_ID); + fControl.setWeights(new int[] { sashSize, 100 - sashSize }); + fTemplateChangeListener = new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + refresh(); + } + }); + } + }; + getTemplatePreferenceStore().addPropertyChangeListener(fTemplateChangeListener); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.Page#setFocus() + */ + public void setFocus() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.Page#getControl() + */ + public Control getControl() { + return fControl; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.Page#dispose() + */ + public void dispose() { + ISelectionProvider selectionProvider = fViewer.getSelectionProvider(); + if (selectionProvider instanceof IPostSelectionProvider) + ((IPostSelectionProvider) selectionProvider) + .removePostSelectionChangedListener(fSelectionChangedListener); + else + selectionProvider.removeSelectionChangedListener(fSelectionChangedListener); + fEditor.setAction(ITextEditorActionConstants.PASTE, fEditorOldPasteAction); + if (fContextMenu != null && !fContextMenu.isDisposed()) + fContextMenu.dispose(); + if (fTemplateChangeListener != null) + getTemplatePreferenceStore().removePropertyChangeListener(fTemplateChangeListener); + super.dispose(); + } + + /** + * Get the shell + * + * @return the shell for this view site + */ + protected Shell getShell() { + return getSite().getShell(); + } + + /** + * Get the image to be used for the given template. Clients can override to + * provide a different image. + * + * @param template + * @return handle to the image + */ + protected Image getImageForTemplate(Template template) { + return DEFAULT_TEMPLATE_IMAGE; + } + + /** + * 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 + * editing failed + */ + protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) { + EditTemplateDialog dialog = new EditTemplateDialog(getShell(), template, edit, + isNameModifiable, getContextTypeRegistry()); + if (dialog.open() == Window.OK) { + return dialog.getTemplate(); + } + return null; + } + + /** + * Update the pattern viewer to show the current template. + * + * @param template + */ + protected void updatePatternViewer(Template template) { + if (template != null) + fPatternViewer.getDocument().set(template.getPattern()); + else + fPatternViewer.getDocument().set(""); //$NON-NLS-1$ + } + + /** + * Creates, configures and returns a source viewer to present the template + * pattern on the templates 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 createPatternViewer(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); + viewer.setEditable(false); + return viewer; + } + + /** + * Get the pattern viewer created by createPatternViewer() + * + * @return the pattern viewer + */ + protected final SourceViewer getPatternViewer() { + return fPatternViewer; + } + + /** + * Get the editor associated with this view + * + * @return the editor + */ + protected final AbstractTextEditor getEditor() { + return fEditor; + } + + /** + * 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 final void updateContextTypes(String[] ids) { + fActiveTypes = Arrays.asList(ids); + if (fLinkWithEditorAction != null && fLinkWithEditorAction.isChecked()) + refresh(); + } + + /** + * Subclasses should override and facilitate inserting the template code + * into the active editor. + * + * @param template + * @param position + */ + abstract protected void insertTemplate(Template template, Point position); + + /** + * Get the context type registry for the associated editor. + * + * @return the contextTypeRegistry + */ + abstract protected ContextTypeRegistry getContextTypeRegistry(); + + /** + * Get the template store for the associated editor + * + * @return the template store + */ + abstract protected TemplateStore getTemplateStore(); + + /** + * Get the preference store used to create the template store returned by + * {@link TemplatesPage#getTemplateStore()}. + * + * @return the preference store + */ + abstract protected IPreferenceStore getTemplatePreferenceStore(); + + /** + * Get the preference page ID for the templates for the given editor. + * + * @return id of the preference page, null if none exists + */ + abstract protected String getPreferencePageId(); + + /** + * Get the context types supported at the current caret position of the + * editor + * + * @return the ids of the context types + */ + protected abstract String[] getContextTypes(); + + /** + * Check whether the given template is valid for the document at the given + * position + * + * @param document + * @param template + * @param offset + * @param length + * @return true if the template is valid + */ + protected abstract boolean isValidTemplate(IDocument document, Template template, int offset, + int length); + + /** + * Setup the preference store + */ + private void setupPreferenceStore() { + fPreferenceStore = TextEditorPlugin.getDefault().getPreferenceStore(); + fPreferenceStore.setDefault(LINK_ACTION_PREF_ID, true); + fPreferenceStore.setDefault(SASH_SIZE_PREF_ID, 80); + } + + /** + * Setup the paste operation + * + * We get the editors Paste operation and sets up a new operation that + * checks for the clipboard contents for TemplateTransfer data. + */ + private void setupPasteOperation() { + fEditorOldPasteAction = fEditor.getAction(ITextEditorActionConstants.PASTE); + fEditorPasteAction = new Action(TemplatesPageMessages.TemplatesPage_paste) { + public void run() { + Clipboard clipBoard = new Clipboard(getShell().getDisplay()); + Template template = getTemplateFromClipboard(clipBoard); + if (template != null) + insertTemplate(template, null); + else + fEditorOldPasteAction.run(); + } + + public void runWithEvent(Event event) { + Clipboard clipBoard = new Clipboard(getShell().getDisplay()); + Template template = getTemplateFromClipboard(clipBoard); + if (template != null) + insertTemplate(template, null); + else + fEditorOldPasteAction.runWithEvent(event); + } + + /** + * Convert the clipboard contents into a template + * + * @param clipBoard + * @return the template or null if contents are not valid + */ + private Template getTemplateFromClipboard(Clipboard clipBoard) { + TemplatePersistenceData[] contents = (TemplatePersistenceData[]) clipBoard + .getContents(TemplateTransfer.getInstance()); + if (contents != null && contents.length == 1) + return contents[0].getTemplate(); + return null; + } + }; + fEditorPasteAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE); + fEditor.setAction(ITextEditorActionConstants.PASTE, fEditorPasteAction); + } + + /** + * Setup a selection listener to monitor the editor + */ + private void setupSelectionProvider() { + ISelectionProvider selectionProvider = fViewer.getSelectionProvider(); + fSelectionChangedListener = new SelectionChangedListener(); + if (selectionProvider instanceof IPostSelectionProvider) + ((IPostSelectionProvider) selectionProvider) + .addPostSelectionChangedListener(fSelectionChangedListener); + else + selectionProvider.addSelectionChangedListener(fSelectionChangedListener); + } + + /** + * Setup the editor site as a drop target. + */ + private void setupEditorDropTarget() { + IDragAndDropService dndService = (IDragAndDropService) fEditor.getSite().getService( + IDragAndDropService.class); + EditorDropTarget editorDropTarget = new EditorDropTarget(); + dndService.addMergedDropTarget((Control) fEditor.getAdapter(Control.class), DND.DROP_COPY, + new Transfer[] { TemplateTransfer.getInstance() }, editorDropTarget); + } + + /** + * Setup the menu, context menu and toolbar actions. + */ + private void setupActions() { + createActions(); + IActionBars actionBars = getSite().getActionBars(); + + actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), fPasteAction); + fPasteAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE); + fPasteAction.setText(TemplatesPageMessages.TemplatesPage_paste); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction); + fCopyAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY); + fCopyAction.setText(TemplatesPageMessages.TemplatesPage_copy); + fillToolbar(actionBars); + fillMenu(actionBars); + } + + /** + * Create all the actions + */ + private void createActions() { + fInsertAction = new Action(TemplatesPageMessages.TemplatesPage_insert) { + public void run() { + TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); + insertTemplate(selectedTemplates[0].getTemplate(), null); + } + }; + fInsertAction.setImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_INSERT)); + fInsertAction.setDisabledImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_INSERT)); + fInsertAction.setToolTipText(TemplatesPageMessages.TemplatesPage_insert_tooltip); + + fAddAction = new Action(TemplatesPageMessages.TemplatesPage_new) { + public void run() { + addTemplate(); + } + }; + fAddAction.setImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_NEW)); + fAddAction.setToolTipText(TemplatesPageMessages.TemplatesPage_new_tooltip); + + fEditAction = new Action(TemplatesPageMessages.TemplatesPage_edit) { + public void run() { + editTemplate(); + } + }; + fEditAction.setImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_EDIT)); + fEditAction.setDisabledImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_EDIT)); + fEditAction.setToolTipText(TemplatesPageMessages.TemplatesPage_edit_tooltip); + + fRemoveAction = new Action(TemplatesPageMessages.TemplatesPage_remove) { + public void run() { + removeTemplates(); + } + }; + fRemoveAction.setImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_DLCL_TEMPLATE_DELETE)); + fRemoveAction.setImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_DELETE)); + fRemoveAction.setToolTipText(TemplatesPageMessages.TemplatesPage_remove_tooltip); + + fLinkWithEditorAction = new Action(TemplatesPageMessages.TemplatesPage_link_to_editor, + IAction.AS_CHECK_BOX) { + public void run() { + fPreferenceStore.setValue(LINK_ACTION_PREF_ID, fLinkWithEditorAction.isChecked()); + refresh(); + } + }; + fLinkWithEditorAction.setImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_LINK)); + fLinkWithEditorAction.setChecked(fPreferenceStore.getBoolean(LINK_ACTION_PREF_ID)); + fLinkWithEditorAction + .setToolTipText(TemplatesPageMessages.TemplatesPage_link_to_editor_tooltip); + fCollapseAllAction = new Action(TemplatesPageMessages.TemplatesPage_collapse_all) { + public void run() { + fTreeViewer.collapseAll(); + } + }; + fCollapseAllAction.setImageDescriptor(TemplatesPageImages + .getImageDescriptor(TemplatesPageImages.IMG_ELCL_TEMPLATE_COLLAPSE_ALL)); + fCollapseAllAction.setToolTipText(TemplatesPageMessages.TemplatesPage_collapse_all_tooltip); + + if (getPreferencePageId() != null) { + fPreferencePageAction = new Action(TemplatesPageMessages.TemplatesPage_preference_page) { + public void run() { + showPreferencePage(); + } + }; + fPreferencePageAction + .setToolTipText(TemplatesPageMessages.TemplatesPage_preference_page_tooltip); + } + + fPasteAction = new Action() { + public void run() { + Clipboard clipBoard = new Clipboard(getShell().getDisplay()); + String pattern = ((String) clipBoard.getContents(TextTransfer.getInstance())); + if (pattern != null) { + final Template template = new Template(createTemplateName(), + TemplatesPageMessages.TemplatesPage_paste_description, + getContextTypeId(), pattern.replaceAll("\\$", "\\$\\$"), true); //$NON-NLS-1$//$NON-NLS-2$ + if (template != null) + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + addTemplate(template); + } + }); + return ; + } + TemplatePersistenceData[] templates = (TemplatePersistenceData[]) clipBoard + .getContents(TemplateTransfer.getInstance()); + if (templates != null) + copyTemplates(templates, getContextTypeId()); + } + }; + + fCopyAction = new Action() { + public void run() { + Clipboard clipBoard = new Clipboard(getShell().getDisplay()); + clipBoard.setContents(new Object[] { getSelectedTemplates() }, + new Transfer[] { TemplateTransfer.getInstance() }); + } + }; + } + + /** + * Fill the toolbar + * + * @param actionBars + */ + private void fillToolbar(IActionBars actionBars) { + IToolBarManager toolBarManager = actionBars.getToolBarManager(); + toolBarManager.add(fInsertAction); + toolBarManager.add(fAddAction); + toolBarManager.add(fEditAction); + toolBarManager.add(fRemoveAction); + + toolBarManager.add(new Separator()); + + toolBarManager.add(fLinkWithEditorAction); + toolBarManager.add(fCollapseAllAction); + } + + /** + * Fill the view menu + * + * @param actionBars + */ + private void fillMenu(IActionBars actionBars) { + IMenuManager menuManager = actionBars.getMenuManager(); + + if (fPreferencePageAction != null) { + menuManager.add(fPreferencePageAction); + menuManager.add(new Separator()); + } + + menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + + /** + * Fill the context menu items + * + * @param manager + */ + private void fillContextMenu(IMenuManager manager) { + manager.add(fInsertAction); + manager.add(new Separator()); + manager.add(fAddAction); + manager.add(fEditAction); + manager.add(fRemoveAction); + manager.add(new Separator()); + manager.add(fCopyAction); + manager.add(fPasteAction); + // Other plug-ins can contribute there actions here + manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + + /** + * Create the tree to display templates + * + * @param parent + */ + private void createTemplateTree(Composite parent) { + Composite treeComposite = new Composite(parent, 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); + + PixelConverter pixelConverter = new PixelConverter(fTemplatesTree); + + TreeColumn columnName = new TreeColumn(fTemplatesTree, SWT.NONE); + columnName.setText(TemplatesPageMessages.TemplatesPage_column_name); + int minWidth = fPreferenceStore.getInt(COLUMN_NAME_WIDTH_PREF_ID); + if (minWidth == 0) { + minWidth = pixelConverter.convertWidthInCharsToPixels(30); + } + columnLayout.setColumnData(columnName, new ColumnPixelData(minWidth, true)); + columnName.addControlListener(new ControlListener() { + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + int nameWidth = ((TreeColumn) e.getSource()).getWidth(); + fPreferenceStore.setValue(COLUMN_NAME_WIDTH_PREF_ID, nameWidth); + } + }); + + TreeColumn columnDescription = new TreeColumn(fTemplatesTree, SWT.NONE); + columnDescription.setText(TemplatesPageMessages.TemplatesPage_column_description); + minWidth = fPreferenceStore.getInt(COLUMN_DESCRIPTION_WIDTH_PREF_ID); + if (minWidth == 0) { + minWidth = pixelConverter.convertWidthInCharsToPixels(45); + } + columnLayout.setColumnData(columnDescription, new ColumnPixelData(minWidth, false)); + columnDescription.addControlListener(new ControlListener() { + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + int descriptionWidth = ((TreeColumn) e.getSource()).getWidth(); + fPreferenceStore.setValue(COLUMN_DESCRIPTION_WIDTH_PREF_ID, descriptionWidth); + } + }); + + createTreeViewer(fTemplatesTree); + } + + /** + * Create the tree viewer and setup the providers + * + * @param templatesTree + */ + private void createTreeViewer(Tree templatesTree) { + fTreeViewer = new TreeViewer(fTemplatesTree); + fTreeViewer.setLabelProvider(new TemplateLabelProvider()); + fTreeViewer.setContentProvider(new TemplatesContentProvider()); + + fTreeViewer.setComparator(new TemplateViewerComparator()); + fTreeViewer.setInput(getTemplatePreferenceStore()); + fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent e) { + updateSelectedItems(); + TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); + insertTemplate(selectedTemplates[0].getTemplate(), null); + } + }); + + fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent e) { + updateSelectedItems(); + updateButtons(); + } + }); + fTreeViewer.expandAll(); + } + + /** + * Setup the pattern viewer + * + * @param parent + */ + private void createPatternForm(Composite parent) { + ViewForm viewForm = new ViewForm(parent, SWT.NONE); + viewForm.setBorderVisible(false); + CLabel previewLabel = new CLabel(viewForm, SWT.NONE); + previewLabel.setText(TemplatesPageMessages.TemplatesPage_preview); + previewLabel.setImage(TemplatesPageImages.getImage(TemplatesPageImages.IMG_OBJ_PREVIEW)); + viewForm.setTopLeft(previewLabel); + + fPatternViewer = createPatternViewer(viewForm); + viewForm.setContent(fPatternViewer.getControl()); + viewForm.addControlListener(new ControlListener() { + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + int[] weights = fControl.getWeights(); + int sashSize = (int) (weights[0] * 100.0 / (weights[0] + weights[1])); + fPreferenceStore.setValue(SASH_SIZE_PREF_ID, sashSize); + } + }); + } + + /** + * Hookup the context menu + */ + 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); + } + + /** + * Check whether the template is valid for the given drop position + * + * @param template + * @param position + * @return true if the template is valid + */ + private boolean isValidTemplateForPosition(Template template, Point position) { + StyledText textWidget = (StyledText) fEditor.getAdapter(Control.class); + IDocument document = fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); + try { + if (position.equals(fCachedPosition)) + return fCachedResult; + fCachedPosition = position; + int offset = getOffset(document, textWidget, textWidget.toControl(position.x, + position.y)); + if (fCachedOffset == offset) + return fCachedResult; + fCachedOffset = offset; + if (isValidTemplate(document, template, offset, 0)) + return fCachedResult = true; + } catch (BadLocationException e) { + } + return fCachedResult = false; + } + + /** + * Update the selected items. + */ + private void updateSelectedItems() { + setSelectedTemplates(); + TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); + + if (selectedTemplates.length == 1) + updatePatternViewer(selectedTemplates[0].getTemplate()); + else + updatePatternViewer(null); + } + + /** + * Show the preference page. The action is enabled only if + * getPreferencePageId() returns non-null. + */ + private void showPreferencePage() { + PreferencesUtil.createPreferenceDialogOn(getShell(), getPreferencePageId(), null, null) + .open(); + } + + /** + * Update the state of the buttons + */ + private void updateButtons() { + TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); + fCopyAction.setEnabled(selectedTemplates.length > 0); + fInsertAction.setEnabled(selectedTemplates.length == 1); + fEditAction.setEnabled(selectedTemplates.length == 1); + fRemoveAction.setEnabled(selectedTemplates.length > 0); + } + + /** + * Set the selected templates + */ + private void setSelectedTemplates() { + IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); + + Iterator it = selection.iterator(); + TemplatePersistenceData[] data = new TemplatePersistenceData[selection.size()]; + int i = 0; + while (it.hasNext()) { + Object o = it.next(); + if (o instanceof TemplatePersistenceData) + data[i++] = (TemplatePersistenceData) o; + else { + fSelectedTemplates = new TemplatePersistenceData[0]; + return; + } + } + fSelectedTemplates = data; + } + + /** + * Get the currently selected templates + * + * @return selected tempaltes + */ + private TemplatePersistenceData[] getSelectedTemplates() { + return fSelectedTemplates; + } + + /** + * 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); + } + } + + /** + * Get contextType of the selected template + * + * @return contextType of the selected template or the first from the + * registry if no templates are selected + */ + private String getContextTypeId() { + IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); + Object item; + + if (selection.size() == 0) + return ((TemplateContextType) getContextTypeRegistry().contextTypes().next()).getId(); + + if (selection.size() == 1) { + item = selection.getFirstElement(); + if (item instanceof TemplatePersistenceData) + return ((TemplatePersistenceData) item).getTemplate().getContextTypeId(); + return ((TemplateContextType) item).getId(); + } + Iterator it = selection.iterator(); + String contextId = null; + while (it.hasNext()) { + item = it.next(); + if (contextId == null) + contextId = getContextId(item); + else if (!contextId.equals(getContextId(item))) + return ((TemplateContextType) getContextTypeRegistry().contextTypes().next()) + .getId(); + } + return contextId; + } + + /** + * Get the context id for the given item which is either a template or a + * context type. + * + * @param item + * @return the context type id + */ + private String getContextId(Object item) { + String contextId; + if (item instanceof TemplatePersistenceData) + contextId = ((TemplatePersistenceData) item).getTemplate().getContextTypeId(); + else + contextId = ((TemplateContextType) item).getId(); + return contextId; + } + + /** + * Add a template. The dialog is filled with the values from the given + * template. + * + * @param template + */ + private void addTemplate(Template template) { + Template newTemplate; + newTemplate = editTemplate(template, false, true); + if (newTemplate != null) { + TemplatePersistenceData data = new TemplatePersistenceData(newTemplate, true); + getTemplateStore().add(data); + saveTemplateStore(); + refresh(); + fTreeViewer.setSelection(new StructuredSelection(data), true); + } + } + + /** + * Save the template store + */ + private void saveTemplateStore() { + try { + getTemplateStore().save(); + } catch (IOException e) { + e.printStackTrace(); + MessageDialog.openError(getShell(), + TemplatesPageMessages.TemplatesPage_save_error_message, e.getMessage()); + } + } + + /** + * Edit the selected template + */ + private void editTemplate() { + Template oldTemplate = getSelectedTemplates()[0].getTemplate(); + Template newTemplate = editTemplate(new Template(oldTemplate), true, true); + if (newTemplate != null) { + if (!newTemplate.getName().equals(oldTemplate.getName()) + && MessageDialog.openQuestion(getShell(), + TemplatesPageMessages.TemplatesPage_question_create_new_title, + TemplatesPageMessages.TemplatesPage_question_create_new_message)) { + TemplatePersistenceData templateData = new TemplatePersistenceData(newTemplate, + true); + getTemplateStore().add(templateData); + refresh(); + fTreeViewer.setSelection(new StructuredSelection(templateData), true); + } else { + getSelectedTemplates()[0].setTemplate(newTemplate); + } + } + saveTemplateStore(); + } + + /** + * Move the selected template from one context to another + * + * @param templates + * @param contextId + * + */ + private void moveTemplates(TemplatePersistenceData[] templates, String contextId) { + for (int i = 0; i < templates.length; i++) { + Template t = templates[i].getTemplate(); + templates[i].setTemplate(new Template(t.getName(), t.getDescription(), contextId, t + .getPattern(), t.isAutoInsertable())); + } + saveTemplateStore(); + fTreeViewer.setSelection(new StructuredSelection(templates), true); + } + + /** + * Copy the selected templates to another context + * + * @param templates + * @param contextId + * + */ + private void copyTemplates(TemplatePersistenceData[] templates, String contextId) { + TemplatePersistenceData[] newTemplates = new TemplatePersistenceData[templates.length]; + for (int i = 0; i < templates.length; i++) { + Template t = templates[i].getTemplate(); + newTemplates[i] = new TemplatePersistenceData(new Template(t.getName(), t + .getDescription(), contextId, t.getPattern(), t.isAutoInsertable()), true); + getTemplateStore().add(newTemplates[i]); + } + saveTemplateStore(); + refresh(); + fTreeViewer.setSelection(new StructuredSelection(newTemplates), true); + } + + /** + * Remove one or more selected templates + */ + private void removeTemplates() { + String title; + TemplatePersistenceData[] selectedTemplates = getSelectedTemplates(); + if (selectedTemplates.length == 1) + title = TemplatesPageMessages.TemplatesPage_remove_title_single; + else + title = TemplatesPageMessages.TemplatesPage_remove_title_multi; + String message; + if (selectedTemplates.length == 1) + message = TemplatesPageMessages.TemplatesPage_remove_message_single; + else + message = NLSUtility.format(TemplatesPageMessages.TemplatesPage_remove_message_multi, + new Object[] { new Integer(selectedTemplates.length) }); + if (!MessageDialog.openQuestion(getShell(), title, message)) + return; + for (int i = 0; i < selectedTemplates.length; i++) { + getTemplateStore().delete(selectedTemplates[i]); + } + saveTemplateStore(); + fTreeViewer.setSelection(new StructuredSelection(new Object[] {}), true); + } + + /** + * Initialize drag and drop the template items + */ + private void initializeDND() { + DragSourceAdapter dragListener = new DragSourceAdapter() { + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DragSourceAdapter#dragStart(org.eclipse.swt.dnd.DragSourceEvent) + */ + public void dragStart(DragSourceEvent event) { + if (getSelectedTemplates().length == 0) { + event.doit = false; + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.dnd.DragSourceAdapter#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) + */ + public void dragSetData(DragSourceEvent event) { + if (TemplateTransfer.getInstance().isSupportedType(event.dataType)) { + event.data = getSelectedTemplates(); + } + } + }; + fTreeViewer.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] { TemplateTransfer + .getInstance() }, dragListener); + DropTargetAdapter dropListener = new DropTargetAdapter() { + Transfer textTransfer = TextTransfer.getInstance(); + Transfer 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.feedback |= DND.FEEDBACK_SCROLL; + if (event.item == null) { + event.detail = DND.DROP_NONE; + return; + } + int index = 0; + boolean isTemplateTransfer = false; + while (index < event.dataTypes.length) { + if (textTransfer.isSupportedType(event.dataTypes[index])) { + break; + } + if (templateTransfer.isSupportedType(event.dataTypes[index])) { + isTemplateTransfer = true; + break; + } + index++; + } + if (index < event.dataTypes.length) { + event.currentDataType = event.dataTypes[index]; + if (event.detail == DND.DROP_DEFAULT || !isTemplateTransfer) + 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(); + final 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).replaceAll("\\$", "\\$\\$"); //$NON-NLS-1$ //$NON-NLS-2$ + final Template template = new Template(createTemplateName(), + TemplatesPageMessages.TemplatesPage_paste_description, contextId, text, + true); + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + addTemplate(template); + } + }); + return; + } + if (templateTransfer.isSupportedType(event.currentDataType)) { + final TemplatePersistenceData[] templates = (TemplatePersistenceData[]) event.data; + final int dropType = event.detail; + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + if (dropType == DND.DROP_COPY) + copyTemplates(templates, contextId); + else + moveTemplates(templates, contextId); + } + }); + } + } + }; + Transfer[] transfers = new Transfer[] { TextTransfer.getInstance(), + TemplateTransfer.getInstance() }; + fTreeViewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, transfers, dropListener); + } + + /** + * Create a template name + * + * @return a new template name + */ + private String createTemplateName() { + for (int i = 1; i < Integer.MAX_VALUE; i++) { + String name = TemplatesPageMessages.TemplatesPage_snippet + i; + if (getTemplateStore().findTemplate(name) == null) + return name; + } + return null; + } + + /** + * Store the collapse state of a context + */ + private void storeCollapseState() { + TreeItem[] items = fTreeViewer.getTree().getItems(); + for (int i = 0; i < items.length; i++) { + fPreferenceStore.setValue(CONTEXT_COLLAPSE_PREF_ID + + ((TemplateContextType) items[i].getData()).getId(), !items[i].getExpanded()); + } + } + + /** + * Refresh the template tree contents + */ + private void refresh() { + storeCollapseState(); + fTreeViewer.getTree().setRedraw(false); + try { + fTreeViewer.refresh(); + TreeItem[] items = fTreeViewer.getTree().getItems(); + for (int i = 0; i < items.length; i++) { + boolean isExpanded = !fPreferenceStore.getBoolean(CONTEXT_COLLAPSE_PREF_ID + + ((TemplateContextType) items[i].getData()).getId()); + if (isExpanded) + fTreeViewer.expandToLevel(items[i].getData(), AbstractTreeViewer.ALL_LEVELS); + else + fTreeViewer.collapseToLevel(items[i].getData(), AbstractTreeViewer.ALL_LEVELS); + } + } finally { + fTreeViewer.getTree().setRedraw(true); + } + } + + /** + * Get the document relative offset from the textwidget relative point + * + * @param document + * @param textWidget + * @param point + * @return the offset + * @throws BadLocationException + */ + private int getOffset(IDocument document, StyledText textWidget, Point point) + throws BadLocationException { + int widgetCaret = fViewer.getTextWidget().getCaretOffset(); + if (fViewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 ext = (ITextViewerExtension5) fViewer; + try { + return ext.widgetOffset2ModelOffset(textWidget.getOffsetAtLocation(point)); + } catch (IllegalArgumentException e) { + int docLineIndex = ext.widgetLine2ModelLine(textWidget.getLineIndex(point.y)); + String lineDelimiter = document.getLineDelimiter(docLineIndex); + int delimLength = lineDelimiter == null ? 0 : lineDelimiter.length(); + return document.getLineOffset(docLineIndex) + document.getLineLength(docLineIndex) + - delimLength; + } + } + IRegion visible = fViewer.getVisibleRegion(); + return widgetCaret + visible.getOffset(); + } +} Index: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesViewMessages.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesViewMessages.java diff -N src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesViewMessages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/templates/view/TemplatesViewMessages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 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 (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.templates.view; + +import org.eclipse.osgi.util.NLS; + +/** + * TemplatesMessages is the message class for the messages used in the templates view. + * @since 3.4 + */ +public class TemplatesViewMessages extends NLS { + private static final String BUNDLE_NAME = TemplatesViewMessages.class.getName(); + + /** + * Default message for an empty templates view + */ + public static String Templates_defaultMessage; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, TemplatesViewMessages.class); + } + + private TemplatesViewMessages() { + } +} #P org.eclipse.ui.workbench Index: Eclipse UI/org/eclipse/ui/IPageLayout.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/IPageLayout.java,v retrieving revision 1.33 diff -u -r1.33 IPageLayout.java --- Eclipse UI/org/eclipse/ui/IPageLayout.java 26 Jun 2007 17:35:10 -0000 1.33 +++ Eclipse UI/org/eclipse/ui/IPageLayout.java 25 Sep 2007 13:07:20 -0000 @@ -10,6 +10,7 @@ * Chris Gross * - Fix for 99155 - allow standalone view placeholders * Chris Gross chris.gross@us.ibm.com Bug 107443 + * Dakshinamurthy Karra (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581 *******************************************************************************/ package org.eclipse.ui; @@ -92,6 +93,12 @@ public static String ID_OUTLINE = "org.eclipse.ui.views.ContentOutline"; //$NON-NLS-1$ /** + * The view id for the workbench's Templates standard component. + * @since 3.4 + */ + public static String ID_TEMPLATES = "org.eclipse.ui.texteditor.templates.view.TemplatesView"; //$NON-NLS-1$ + + /** * The view id for the workbench's Bookmark Navigator standard component. */ public static String ID_BOOKMARKS = "org.eclipse.ui.views.BookmarkView"; //$NON-NLS-1$