diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java index 161b83acef9..1ba10b31de7 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java @@ -44,9 +44,14 @@ public abstract class CodeFormatter { public static final int K_CLASS_BODY_DECLARATIONS = 0x04; /** - * Kind used to format a compilation unit + * Kind used to format a compilation unit. + * @deprecated Use #K_TRANSLATION_UNIT */ public static final int K_COMPILATION_UNIT = 0x08; + /** + * Kind used to format a translation unit. + */ + public static final int K_TRANSLATION_UNIT = 0x08; /** * Kind used to format a single-line comment diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/IndentManipulation.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/IndentManipulation.java new file mode 100644 index 00000000000..11cc8ac7ccb --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/IndentManipulation.java @@ -0,0 +1,428 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.core.formatter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultLineTracker; +import org.eclipse.jface.text.ILineTracker; +import org.eclipse.jface.text.IRegion; + +import org.eclipse.text.edits.ReplaceEdit; + +/** + * Helper class to provide String manipulation functions dealing with indentations. + * + * @since 5.0 + */ +public final class IndentManipulation { + + private static final String EMPTY_STRING= ""; //$NON-NLS-1$ + + private IndentManipulation() { + // don't instantiate + } + + /** + * Returns true if the given character is an indentation character. Indentation character are all whitespace characters + * except the line delimiter characters. + * + * @param ch the given character + * @return Returns true if this the character is a indent character, false otherwise + */ + public static boolean isIndentChar(char ch) { + return Character.isWhitespace(ch) && !isLineDelimiterChar(ch); + } + + /** + * Returns true if the given character is a line delimiter character. + * + * @param ch the given character + * @return Returns true if this the character is a line delimiter character, false otherwise + */ + public static boolean isLineDelimiterChar(char ch) { + return ch == '\n' || ch == '\r'; + } + + /** + * Returns the indentation of the given line in indentation units. Odd spaces are + * not counted. This method only analyzes the content of line up to the first + * non-whitespace character. + * + * @param line the string to measure the indent of + * @param tabWidth the width of one tab character in space equivalents + * @param indentWidth the width of one indentation unit in space equivalents + * @return the number of indentation units that line is indented by + * @exception IllegalArgumentException if: + * + */ + public static int measureIndentUnits(CharSequence line, int tabWidth, int indentWidth) { + if (indentWidth <= 0 || tabWidth < 0 || line == null) { + throw new IllegalArgumentException(); + } + + int visualLength= measureIndentInSpaces(line, tabWidth); + return visualLength / indentWidth; + } + + /** + * Returns the indentation of the given line in space equivalents. + * + *

Tab characters are counted using the given tabWidth and every other indent + * character as one. This method analyzes the content of line up to the first + * non-whitespace character.

+ * + * @param line the string to measure the indent of + * @param tabWidth the width of one tab in space equivalents + * @return the measured indent width in space equivalents + * @exception IllegalArgumentException if: + * + */ + public static int measureIndentInSpaces(CharSequence line, int tabWidth) { + if (tabWidth < 0 || line == null) { + throw new IllegalArgumentException(); + } + + int length= 0; + int max= line.length(); + for (int i= 0; i < max; i++) { + char ch= line.charAt(i); + if (ch == '\t') { + int reminder= length % tabWidth; + length += tabWidth - reminder; + } else if (isIndentChar(ch)) { + length++; + } else { + return length; + } + } + return length; + } + + /** + * Returns the leading indentation string of the given line. Note that the returned string + * need not be equal to the leading whitespace as odd spaces are not considered part of the + * indentation. + * + * @param line the line to scan + * @param tabWidth the size of one tab in space equivalents + * @param indentWidth the width of one indentation unit in space equivalents + * @return the indent part of line, but no odd spaces + * @exception IllegalArgumentException if: + * + */ + public static String extractIndentString(String line, int tabWidth, int indentWidth) { + if (tabWidth < 0 || indentWidth <= 0 || line == null) { + throw new IllegalArgumentException(); + } + + int size= line.length(); + int end= 0; + + int spaceEquivs= 0; + int characters= 0; + for (int i= 0; i < size; i++) { + char c= line.charAt(i); + if (c == '\t') { + int remainder= spaceEquivs % tabWidth; + spaceEquivs += tabWidth - remainder; + characters++; + } else if (isIndentChar(c)) { + spaceEquivs++; + characters++; + } else { + break; + } + if (spaceEquivs >= indentWidth) { + end += characters; + characters= 0; + spaceEquivs= spaceEquivs % indentWidth; + } + } + if (end == 0) { + return EMPTY_STRING; + } else if (end == size) { + return line; + } else { + return line.substring(0, end); + } + } + + + /** + * Removes the given number of indentation units from a given line. If the line + * has less than the given indent, all the available indentation is removed. + * If indentsToRemove <= 0 the line is returned. + * + * @param line the line to trim + * @param tabWidth the width of one tab in space equivalents + * @param indentWidth the width of one indentation unit in space equivalents + * @return the trimmed string + * @exception IllegalArgumentException if: + * + */ + public static String trimIndent(String line, int indentUnitsToRemove, int tabWidth, int indentWidth) { + if (tabWidth < 0 || indentWidth <= 0 || line == null) { + throw new IllegalArgumentException(); + } + + if (indentUnitsToRemove <= 0) + return line; + + final int spaceEquivalentsToRemove= indentUnitsToRemove * indentWidth; + + int start= 0; + int spaceEquivalents= 0; + int size= line.length(); + String prefix= null; + for (int i= 0; i < size; i++) { + char c= line.charAt(i); + if (c == '\t') { + int remainder= spaceEquivalents % tabWidth; + spaceEquivalents += tabWidth - remainder; + } else if (isIndentChar(c)) { + spaceEquivalents++; + } else { + // Assert.isTrue(false, "Line does not have requested number of indents"); + start= i; + break; + } + if (spaceEquivalents == spaceEquivalentsToRemove) { + start= i + 1; + break; + } + if (spaceEquivalents > spaceEquivalentsToRemove) { + // can happen if tabSize > indentSize, e.g tabsize==8, indent==4, indentsToRemove==1, line prefixed with one tab + // this implements the third option + start= i + 1; // remove the tab + // and add the missing spaces + char[] missing= new char[spaceEquivalents - spaceEquivalentsToRemove]; + Arrays.fill(missing, ' '); + prefix= new String(missing); + break; + } + } + String trimmed; + if (start == size) + trimmed= EMPTY_STRING; + else + trimmed= line.substring(start); + + if (prefix == null) + return trimmed; + return prefix + trimmed; + } + + /** + * Change the indent of a, possible multiple line, code string. The given number of indent units is removed, + * and a new indent string is added. + *

The first line of the code will not be changed (It is considered to have no indent as it might start in + * the middle of a line).

+ * + * @param code the code to change the indent of + * @param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code + * @param tabWidth the size of one tab in space equivalents + * @param indentWidth the width of one indentation unit in space equivalents + * @param newIndentString the new indent string to be added to all lines (except the first) + * @param lineDelim the new line delimiter to be used. The returned code will contain only this line delimiter. + * @return the newly indent code, containing only the given line delimiters. + * @exception IllegalArgumentException if: + * + */ + public static String changeIndent(String code, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString, String lineDelim) { + if (tabWidth < 0 || indentWidth <= 0 || code == null || indentUnitsToRemove < 0 || newIndentString == null || lineDelim == null) { + throw new IllegalArgumentException(); + } + + try { + ILineTracker tracker= new DefaultLineTracker(); + tracker.set(code); + int nLines= tracker.getNumberOfLines(); + if (nLines == 1) { + return code; + } + + StringBuffer buf= new StringBuffer(); + + for (int i= 0; i < nLines; i++) { + IRegion region= tracker.getLineInformation(i); + int start= region.getOffset(); + int end= start + region.getLength(); + String line= code.substring(start, end); + + if (i == 0) { // no indent for first line (contained in the formatted string) + buf.append(line); + } else { // no new line after last line + buf.append(lineDelim); + buf.append(newIndentString); + buf.append(trimIndent(line, indentUnitsToRemove, tabWidth, indentWidth)); + } + } + return buf.toString(); + } catch (BadLocationException e) { + // can not happen + return code; + } + } + + /** + * Returns the text edits retrieved after changing the indentation of a, possible multi-line, code string. + * + *

The given number of indent units is removed, and a new indent string is added.

+ *

The first line of the code will not be changed (It is considered to have no indent as it might start in + * the middle of a line).

+ * + * @param source The code to change the indent of + * @param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code + * @param tabWidth the size of one tab in space equivalents + * @param indentWidth the width of one indentation unit in space equivalents + * @param newIndentString the new indent string to be added to all lines (except the first) + * @return returns the resulting text edits + * @exception IllegalArgumentException if: + * + */ + public static ReplaceEdit[] getChangeIndentEdits(String source, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString) { + if (tabWidth < 0 || indentWidth <= 0 || source == null || indentUnitsToRemove < 0 || newIndentString == null) { + throw new IllegalArgumentException(); + } + + ArrayList result= new ArrayList(); + try { + ILineTracker tracker= new DefaultLineTracker(); + tracker.set(source); + int nLines= tracker.getNumberOfLines(); + if (nLines == 1) + return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]); + for (int i= 1; i < nLines; i++) { + IRegion region= tracker.getLineInformation(i); + int offset= region.getOffset(); + String line= source.substring(offset, offset + region.getLength()); + int length= indexOfIndent(line, indentUnitsToRemove, tabWidth, indentWidth); + if (length >= 0) { + result.add(new ReplaceEdit(offset, length, newIndentString)); + } else { + length= measureIndentUnits(line, tabWidth, indentWidth); + result.add(new ReplaceEdit(offset, length, "")); //$NON-NLS-1$ + } + } + } catch (BadLocationException cannotHappen) { + // can not happen + } + return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]); + } + + /* + * Returns the index where the indent of the given size ends. + * Returns -1 if the line isn't prefixed with an indent of + * the given number of indents. + */ + private static int indexOfIndent(CharSequence line, int numberOfIndentUnits, int tabWidth, int indentWidth) { + + int spaceEquivalents= numberOfIndentUnits * indentWidth; + + int size= line.length(); + int result= -1; + int blanks= 0; + for (int i= 0; i < size && blanks < spaceEquivalents; i++) { + char c= line.charAt(i); + if (c == '\t') { + int remainder= blanks % tabWidth; + blanks += tabWidth - remainder; + } else if (isIndentChar(c)) { + blanks++; + } else { + break; + } + result= i; + } + if (blanks < spaceEquivalents) + return -1; + return result + 1; + } + + /** + * Returns the tab width as configured in the given map. + *

Use {@link org.eclipse.jdt.core.IJavaProject#getOptions(boolean)} to get the most current project options.

+ * + * @param options the map to get the formatter settings from. + * + * @return the tab width + * @exception IllegalArgumentException if the given options is null + */ + public static int getTabWidth(Map options) { + if (options == null) { + throw new IllegalArgumentException(); + } + return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 4); + } + + /** + * Returns the tab width as configured in the given map. + *

Use {@link org.eclipse.jdt.core.IJavaProject#getOptions(boolean)} to get the most current project options.

+ * + * @param options the map to get the formatter settings from + * + * @return the indent width + * @exception IllegalArgumentException if the given options is null + */ + public static int getIndentWidth(Map options) { + if (options == null) { + throw new IllegalArgumentException(); + } + int tabWidth=getTabWidth(options); + boolean isMixedMode= DefaultCodeFormatterConstants.MIXED.equals(options.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR)); + if (isMixedMode) { + return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, tabWidth); + } + return tabWidth; + } + + private static int getIntValue(Map options, String key, int def) { + try { + return Integer.parseInt((String) options.get(key)); + } catch (NumberFormatException e) { + return def; + } + } +} + diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index 3933b5e3e22..3d2f2b10557 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -7,6 +7,7 @@ Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, + org.eclipse.cdt.internal.corext.codemanipulation, org.eclipse.cdt.internal.corext.template.c;x-internal:=true, org.eclipse.cdt.internal.corext.util;x-internal:=true, org.eclipse.cdt.internal.ui, @@ -14,7 +15,6 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.internal.ui.browser.opentype;x-internal:=true, org.eclipse.cdt.internal.ui.buildconsole;x-internal:=true, org.eclipse.cdt.internal.ui.callhierarchy;x-internal:=true, - org.eclipse.cdt.internal.ui.codemanipulation;x-internal:=true, org.eclipse.cdt.internal.ui.compare;x-internal:=true, org.eclipse.cdt.internal.ui.cview;x-internal:=true, org.eclipse.cdt.internal.ui.dialogs;x-internal:=true, @@ -65,7 +65,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.utils.ui.controls Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.3.0,4.0.0)", org.eclipse.ui.views;bundle-version="[3.2.0,4.0.0)", - org.eclipse.jface.text;bundle-version="[3.3.0,4.0.0)", + org.eclipse.jface.text;bundle-version="[3.4.0,4.0.0)", org.eclipse.ui.workbench.texteditor;bundle-version="[3.3.0,4.0.0)", org.eclipse.ui.editors;bundle-version="[3.3.0,4.0.0)", org.eclipse.ui;bundle-version="[3.3.0,4.0.0)", diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index cc6f39b613a..fb51b89932c 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -66,8 +66,8 @@ NewWizards.sourceFile = Source File NewWizards.sourceFile.description = Create a new source file NewWizards.headerFile = Header File NewWizards.headerFile.description = Create a new header file -NewWizards.file = File -NewWizards.file.description = Create a new file resource +NewWizards.file = File from Template +NewWizards.file.description = Create a new file resource based on a file template NewTypeDropDownAction.label=&Class... NewTypeDropDownAction.tooltip=New C++ Class @@ -136,6 +136,7 @@ CPluginTemplatePreferencePage.name=Templates CPluginBuildConsolePreferencePage.name=Build Console CPluginFileTypesPreferencePage.name=File Types CodeFormatterPreferencePage.name=Code Style +codeTemplatePreferencePageName=Code Templates CodeAssistPreferencePage.name=Content Assist CodeAssistAdvancedPreferencePage.name=Advanced SmartTypingPreferencePage.name=Typing diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index e8557aa1ef6..2d3d956a5ea 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -319,7 +319,7 @@ category="org.eclipse.cdt.ui.newCWizards" finalPerspective="org.eclipse.cdt.ui.CPerspective" id="org.eclipse.cdt.ui.wizards.NewFileCreationWizard"> - + @@ -403,7 +403,7 @@ category="org.eclipse.cdt.ui.newCCWizards" finalPerspective="org.eclipse.cdt.ui.CPerspective" id="org.eclipse.cdt.ui.wizards.NewFileCreationWizard"> - + @@ -708,6 +708,11 @@ class="org.eclipse.cdt.internal.ui.preferences.TodoTaskPreferencePage" id="org.eclipse.cdt.ui.preferences.TodoTaskPreferencePage" name="%todoTaskPrefName"/> + FOO_H_ + StringBuffer buf = new StringBuffer(); + // Do not do this, leading underscores are discourage by the std. + //buf.append('_'); + for (int i = 0; i < name.length(); ++i) { + char ch = name.charAt(i); + if (Character.isLetterOrDigit(ch)) { + buf.append(Character.toUpperCase(ch)); + } else if (ch == '.' || ch == '_') { + buf.append('_'); + } + } + buf.append('_'); + return buf.toString(); + } + return null; + } + + /** + * Get a set of file templates for the given content types. + * + * @param contentTypes the list of content types + * @param project the project or null + * @return an array of templates + */ + public static Template[] getFileTemplatesForContentTypes(String[] contentTypes, IProject project) { + if (contentTypes == null || contentTypes.length == 0) { + return new Template[0]; + } + TemplatePersistenceData[] templateDatas; + if (project == null) { + templateDatas= CUIPlugin.getDefault().getCodeTemplateStore().getTemplateData(true); + } else { + ProjectTemplateStore projectStore= new ProjectTemplateStore(project.getProject()); + try { + projectStore.load(); + } catch (IOException e) { + CUIPlugin.getDefault().log(e); + } + templateDatas= projectStore.getTemplateData(); + } + List result= new ArrayList(); + for (int j = 0; j < contentTypes.length; j++) { + for (int i = 0; i < templateDatas.length; i++) { + Template template = templateDatas[i].getTemplate(); + final String contextTypeId = template.getContextTypeId(); + if (FileTemplateContextType.isContextTypeForContentType(contextTypeId, contentTypes[j])) { + result.add(template); + } + } + } + return (Template[]) result.toArray(new Template[result.size()]); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java index b18cc4b595b..1b2b16d5a6d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java @@ -118,7 +118,7 @@ public class CFormatter { if (fUseCodeFormatter) { // try to format and fall back to indenting try { - format(document, (TranslationUnitContext) context); + format(document); return; } catch (BadLocationException e) { } catch (MalformedTreeException e) { @@ -214,7 +214,7 @@ public class CFormatter { return false; } - private void format(IDocument doc, TranslationUnitContext context) throws BadLocationException { + private void format(IDocument doc) throws BadLocationException { Map options; if (fProject != null) options= fProject.getOptions(true); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContext.java new file mode 100644 index 00000000000..30eb9d8c1c3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContext.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.corext.template.c; + +import org.eclipse.core.resources.IFile; + +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ITranslationUnit; + +/** + * A template context for C/C++ code and comment. + * + * @since 5.0 + */ +public class CodeTemplateContext extends FileTemplateContext { + + private ICProject fProject; + + public CodeTemplateContext(String contextTypeId, ICProject project, String lineDelimiter) { + super(contextTypeId, lineDelimiter); + fProject= project; + } + + public ICProject getCProject() { + return fProject; + } + + public void setTranslationUnitVariables(ITranslationUnit tu) { + IFile file= (IFile)tu.getResource(); + if (file != null) { + super.setResourceVariables(file); + } + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java new file mode 100644 index 00000000000..a971ee624eb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java @@ -0,0 +1,241 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.corext.template.c; + +import org.eclipse.jface.text.templates.ContextTypeRegistry; +import org.eclipse.jface.text.templates.TemplateContext; +import org.eclipse.jface.text.templates.TemplateException; +import org.eclipse.jface.text.templates.TemplateVariableResolver; + +import org.eclipse.cdt.core.CCorePlugin; + +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + +/** + */ +public class CodeTemplateContextType extends FileTemplateContextType { + + /* context types */ + private static final String CONTEXTTYPE_PREFIX= "org.eclipse.cdt.ui.text.codetemplates."; //$NON-NLS-1$ + + public static final String CPPSOURCEFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CXXSOURCE + FileTemplateContextType.CONTEXTTYPE_SUFFIX; + public static final String CPPHEADERFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CXXHEADER + FileTemplateContextType.CONTEXTTYPE_SUFFIX; + public static final String CSOURCEFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CSOURCE + FileTemplateContextType.CONTEXTTYPE_SUFFIX; + public static final String CHEADERFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CHEADER + FileTemplateContextType.CONTEXTTYPE_SUFFIX; + public static final String ASMSOURCEFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_ASMSOURCE + FileTemplateContextType.CONTEXTTYPE_SUFFIX; + + public static final String METHODBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "methodbody_context"; //$NON-NLS-1$ + public static final String CONSTRUCTORBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "constructorbody_context"; //$NON-NLS-1$ + public static final String DESTRUCTORBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "destructorbody_context"; //$NON-NLS-1$ + public static final String FILECOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "filecomment_context"; //$NON-NLS-1$ + public static final String TYPECOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "typecomment_context"; //$NON-NLS-1$ + public static final String FIELDCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "fieldcomment_context"; //$NON-NLS-1$ + public static final String METHODCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "methodcomment_context"; //$NON-NLS-1$ + public static final String CONSTRUCTORCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "constructorcomment_context"; //$NON-NLS-1$ + public static final String DESTRUCTORCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "destructorcomment_context"; //$NON-NLS-1$ + + /* templates */ + private static final String CODETEMPLATES_PREFIX= "org.eclipse.cdt.ui.text.codetemplates."; //$NON-NLS-1$ + public static final String COMMENT_SUFFIX= "comment"; //$NON-NLS-1$ + + public static final String ASM_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "asmsourcefile"; //$NON-NLS-1$ + public static final String CPP_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "cppsourcefile"; //$NON-NLS-1$ + public static final String CPP_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cppheaderfile"; //$NON-NLS-1$ + public static final String C_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "csourcefile"; //$NON-NLS-1$ + public static final String C_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cheaderfile"; //$NON-NLS-1$ + public static final String METHODSTUB_ID= CODETEMPLATES_PREFIX + "methodbody"; //$NON-NLS-1$ + public static final String CONSTRUCTORSTUB_ID= CODETEMPLATES_PREFIX + "constructorbody"; //$NON-NLS-1$ + public static final String DESTRUCTORSTUB_ID= CODETEMPLATES_PREFIX + "destructorbody"; //$NON-NLS-1$ + public static final String FILECOMMENT_ID= CODETEMPLATES_PREFIX + "file" + COMMENT_SUFFIX; //$NON-NLS-1$ + public static final String TYPECOMMENT_ID= CODETEMPLATES_PREFIX + "type" + COMMENT_SUFFIX; //$NON-NLS-1$ + public static final String FIELDCOMMENT_ID= CODETEMPLATES_PREFIX + "field" + COMMENT_SUFFIX; //$NON-NLS-1$ + public static final String METHODCOMMENT_ID= CODETEMPLATES_PREFIX + "method" + COMMENT_SUFFIX; //$NON-NLS-1$ + public static final String CONSTRUCTORCOMMENT_ID= CODETEMPLATES_PREFIX + "constructor" + COMMENT_SUFFIX; //$NON-NLS-1$ + public static final String DESTRUCTORCOMMENT_ID= CODETEMPLATES_PREFIX + "destructor" + COMMENT_SUFFIX; //$NON-NLS-1$ + + /* resolver types */ + public static final String ENCLOSING_METHOD= "enclosing_method"; //$NON-NLS-1$ + public static final String ENCLOSING_TYPE= "enclosing_type"; //$NON-NLS-1$ + public static final String BODY_STATEMENT= "body_statement"; //$NON-NLS-1$ + public static final String FIELD= "field"; //$NON-NLS-1$ + public static final String FIELD_TYPE= "field_type"; //$NON-NLS-1$ + + public static final String RETURN_TYPE= "return_type"; //$NON-NLS-1$ + + public static final String TYPENAME= "type_name"; //$NON-NLS-1$ + public static final String INCLUDE_GUARD_SYMBOL= "include_guard_symbol"; //$NON-NLS-1$ + + public static final String DECLARATIONS= "declarations"; //$NON-NLS-1$ + public static final String TYPE_COMMENT= "typecomment"; //$NON-NLS-1$ + public static final String FILE_COMMENT= "filecomment"; //$NON-NLS-1$ + + + /** + * Resolver that resolves to the variable defined in the context. + */ + public static class CodeTemplateVariableResolver extends FileTemplateVariableResolver { + public CodeTemplateVariableResolver(String type, String description) { + super(type, description); + } + } + + /** + * Resolver for task tags. + */ + protected static class Todo extends TemplateVariableResolver { + + public Todo() { + super("todo", TemplateMessages.CodeTemplateContextType_variable_description_todo); //$NON-NLS-1$ + } + + protected String resolve(TemplateContext context) { + String todoTaskTag= StubUtility.getTodoTaskTag(((CodeTemplateContext) context).getCProject()); + if (todoTaskTag == null) + return "XXX"; //$NON-NLS-1$ + + return todoTaskTag; + } + } + + private boolean fIsComment; + + public CodeTemplateContextType(String contextTypeId) { + this(contextTypeId, contextTypeId); + } + + public CodeTemplateContextType(String contextTypeId, String contextName) { + super(contextTypeId, contextName); + + fIsComment= false; + + // global + addResolver(new Todo()); + + if (CPPSOURCEFILE_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); + addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); + addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addTranslationUnitVariables(); + } else if (CPPHEADERFILE_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); + addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); + addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); + addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addTranslationUnitVariables(); + } else if (CSOURCEFILE_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); + addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addTranslationUnitVariables(); + } else if (CHEADERFILE_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); + addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); + addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + addTranslationUnitVariables(); + } else if (METHODBODY_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + addResolver(new CodeTemplateVariableResolver(ENCLOSING_METHOD, TemplateMessages.CodeTemplateContextType_variable_description_enclosingmethod)); + addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); + } else if (CONSTRUCTORBODY_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); + } else if (DESTRUCTORBODY_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); + } else if (TYPECOMMENT_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(TYPENAME, TemplateMessages.CodeTemplateContextType_variable_description_typename)); + addTranslationUnitVariables(); + fIsComment= true; + } else if (FILECOMMENT_CONTEXTTYPE.equals(contextTypeId)) { + addTranslationUnitVariables(); + fIsComment= true; + } else if (FIELDCOMMENT_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(FIELD_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_fieldtype)); + addResolver(new CodeTemplateVariableResolver(FIELD, TemplateMessages.CodeTemplateContextType_variable_description_fieldname)); + addTranslationUnitVariables(); + fIsComment= true; + } else if (METHODCOMMENT_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + addResolver(new CodeTemplateVariableResolver(ENCLOSING_METHOD, TemplateMessages.CodeTemplateContextType_variable_description_enclosingmethod)); + addResolver(new CodeTemplateVariableResolver(RETURN_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_returntype)); + addTranslationUnitVariables(); + fIsComment= true; + } else if (CONSTRUCTORCOMMENT_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + addTranslationUnitVariables(); + fIsComment= true; + } else if (DESTRUCTORCOMMENT_CONTEXTTYPE.equals(contextTypeId)) { + addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); + addTranslationUnitVariables(); + fIsComment= true; + } else { + addTranslationUnitVariables(); + } + } + + /* + * @see org.eclipse.cdt.internal.corext.template.c.FileTemplateContextType#addResourceVariables() + */ + protected void addResourceVariables() { + // don't add resource variables by default + } + + private void addTranslationUnitVariables() { + super.addResourceVariables(); + } + + public static void registerContextTypes(ContextTypeRegistry registry) { + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CPPSOURCEFILE_CONTEXTTYPE, TemplateMessages.CodeTemplateContextType_cppsource_name)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CPPHEADERFILE_CONTEXTTYPE, TemplateMessages.CodeTemplateContextType_cppheader_name)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CSOURCEFILE_CONTEXTTYPE, TemplateMessages.CodeTemplateContextType_csource_name)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CHEADERFILE_CONTEXTTYPE, TemplateMessages.CodeTemplateContextType_cheader_name)); + FileTemplateContextType asmContextType= new FileTemplateContextType(CodeTemplateContextType.ASMSOURCEFILE_CONTEXTTYPE, TemplateMessages.CodeTemplateContextType_asmsource_name); + asmContextType.addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); + registry.addContextType(asmContextType); + + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.METHODBODY_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CONSTRUCTORBODY_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.DESTRUCTORBODY_CONTEXTTYPE)); + + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.FILECOMMENT_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.TYPECOMMENT_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.FIELDCOMMENT_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.METHODCOMMENT_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CONSTRUCTORCOMMENT_CONTEXTTYPE)); + registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.DESTRUCTORCOMMENT_CONTEXTTYPE)); + } + + public void validate(String pattern) throws TemplateException { + super.validate(pattern); + if (fIsComment) { + if (!isValidComment(pattern)) { + throw new TemplateException(TemplateMessages.CodeTemplateContextType_validate_invalidcomment); + } + } + } + + + private boolean isValidComment(String template) { +// IScanner scanner= ToolFactory.createScanner(true, false, false, false); +// scanner.setSource(template.toCharArray()); +// try { +// int next= scanner.getNextToken(); +// while (TokenScanner.isComment(next)) { +// next= scanner.getNextToken(); +// } +// return next == ITerminalSymbols.TokenNameEOF; +// } catch (InvalidInputException e) { +// } +// return false; + return true; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/FileTemplateContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/FileTemplateContext.java new file mode 100644 index 00000000000..7817902b4d7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/FileTemplateContext.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. 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: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.corext.template.c; + +import java.util.Iterator; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultLineTracker; +import org.eclipse.jface.text.ILineTracker; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateBuffer; +import org.eclipse.jface.text.templates.TemplateContext; +import org.eclipse.jface.text.templates.TemplateException; +import org.eclipse.jface.text.templates.TemplateTranslator; +import org.eclipse.jface.text.templates.TemplateVariableResolver; + +import org.eclipse.cdt.ui.CUIPlugin; + +/** + * A template context for plain file resources. + * + * @since 5.0 + */ +public class FileTemplateContext extends TemplateContext { + + private String fLineDelimiter; + + public FileTemplateContext(String contextTypeId, String lineDelimiter) { + super(CUIPlugin.getDefault().getCodeTemplateContextRegistry().getContextType(contextTypeId)); + fLineDelimiter= lineDelimiter; + } + + /* + * @see org.eclipse.jface.text.templates.TemplateContext#evaluate(org.eclipse.jface.text.templates.Template) + */ + public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException { + // test that all variables are defined + Iterator iterator= getContextType().resolvers(); + while (iterator.hasNext()) { + TemplateVariableResolver var= (TemplateVariableResolver) iterator.next(); + if (var.getClass() == FileTemplateContextType.FileTemplateVariableResolver.class) { + Assert.isNotNull(getVariable(var.getType()), "Variable " + var.getType() + " not defined"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + if (!canEvaluate(template)) + return null; + + String pattern= changeLineDelimiter(template.getPattern(), fLineDelimiter); + + TemplateTranslator translator= new TemplateTranslator(); + TemplateBuffer buffer= translator.translate(pattern); + getContextType().resolve(buffer, this); + return buffer; + } + + private static String changeLineDelimiter(String code, String lineDelim) { + try { + ILineTracker tracker= new DefaultLineTracker(); + tracker.set(code); + int nLines= tracker.getNumberOfLines(); + if (nLines == 1) { + return code; + } + + StringBuffer buf= new StringBuffer(); + for (int i= 0; i < nLines; i++) { + if (i != 0) { + buf.append(lineDelim); + } + IRegion region = tracker.getLineInformation(i); + String line= code.substring(region.getOffset(), region.getOffset() + region.getLength()); + buf.append(line); + } + return buf.toString(); + } catch (BadLocationException e) { + // can not happen + return code; + } + } + + /* + * @see org.eclipse.jface.text.templates.TemplateContext#canEvaluate(org.eclipse.jface.text.templates.Template) + */ + public boolean canEvaluate(Template template) { + return true; + } + + public void setResourceVariables(IFile file) { + setVariable(FileTemplateContextType.FILENAME, file.getName()); + setVariable(FileTemplateContextType.FILEBASE, new Path(file.getName()).removeFileExtension().lastSegment()); + IPath location= file.getLocation(); + setVariable(FileTemplateContextType.FILELOCATION, location != null ? location.toOSString() : ""); //$NON-NLS-1$ + setVariable(FileTemplateContextType.FILEPATH, file.getFullPath().toString()); + setVariable(FileTemplateContextType.PROJECTNAME, file.getProject().getName()); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/FileTemplateContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/FileTemplateContextType.java new file mode 100644 index 00000000000..86001872e17 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/FileTemplateContextType.java @@ -0,0 +1,244 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. 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: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.corext.template.c; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.core.variables.IStringVariableManager; +import org.eclipse.core.variables.VariablesPlugin; +import org.eclipse.jface.text.templates.ContextTypeRegistry; +import org.eclipse.jface.text.templates.GlobalTemplateVariables; +import org.eclipse.jface.text.templates.SimpleTemplateVariableResolver; +import org.eclipse.jface.text.templates.TemplateContext; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.jface.text.templates.TemplateException; +import org.eclipse.jface.text.templates.TemplateVariable; +import org.eclipse.jface.text.templates.TemplateVariableResolver; +import org.eclipse.jface.text.templates.TemplateVariableType; + +import org.eclipse.cdt.internal.corext.util.Messages; + +/** + * A generic template context type for file resources based on content-type. + * + * @since 5.0 + */ +public class FileTemplateContextType extends TemplateContextType { + + public static final String CONTEXTTYPE_SUFFIX= ".contenttype_context"; //$NON-NLS-1$ + + public static final String CONTENTTYPE_TEXT= "org.eclipse.core.runtime.text"; //$NON-NLS-1$ + public static final String TEXTFILE_CONTEXTTYPE= CONTENTTYPE_TEXT + CONTEXTTYPE_SUFFIX; + + /* resolver types */ + public static final String FILENAME= "file_name"; //$NON-NLS-1$ + public static final String FILEBASE= "file_base"; //$NON-NLS-1$ + public static final String FILELOCATION= "file_loc"; //$NON-NLS-1$ + public static final String FILEPATH= "file_path"; //$NON-NLS-1$ + public static final String PROJECTNAME= "project_name"; //$NON-NLS-1$ + + /** + * Resolver that resolves to the variable defined in the context. + */ + static class FileTemplateVariableResolver extends SimpleTemplateVariableResolver { + public FileTemplateVariableResolver(String type, String description) { + super(type, description); + } + + protected String resolve(TemplateContext context) { + String value= context.getVariable(getType()); + return value != null ? value : ""; //$NON-NLS-1$ + } + } + + /** + * This date variable evaluates to the current date in a specific format. + */ + static class DateVariableResolver extends SimpleTemplateVariableResolver { + private String fFormat; + + public DateVariableResolver() { + super("date", TemplateMessages.FileTemplateContextType_variable_description_date); //$NON-NLS-1$ + } + + /* + * @see org.eclipse.jface.text.templates.TemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateVariable, org.eclipse.jface.text.templates.TemplateContext) + */ + public void resolve(TemplateVariable variable, TemplateContext context) { + fFormat= null; + TemplateVariableType type= variable.getVariableType(); + List params= type.getParams(); + if (params.size() == 1) { + fFormat= params.get(0).toString(); + } + super.resolve(variable, context); + } + + /* + * @see org.eclipse.jface.text.templates.SimpleTemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateContext) + */ + protected String resolve(TemplateContext context) { + DateFormat f; + if (fFormat == null) { + f= DateFormat.getDateInstance(); + } else { + f= new SimpleDateFormat(fFormat); + } + return f.format(new java.util.Date()); + } + } + + /** + * Resolver that resolves to the value of a core variable. + */ + static class CoreVariableResolver extends SimpleTemplateVariableResolver { + private String fVariableName; + private String[] fArguments; + + public CoreVariableResolver(String type) { + super(type, TemplateMessages.FileTemplateContextType__variable_description_eclipse); + } + + /* + * @see org.eclipse.jface.text.templates.TemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateVariable, org.eclipse.jface.text.templates.TemplateContext) + */ + public void resolve(TemplateVariable variable, TemplateContext context) { + fVariableName= variable.getName(); + TemplateVariableType type= variable.getVariableType(); + List params= type.getParams(); + fArguments= (String[]) params.toArray(new String[params.size()]); + super.resolve(variable, context); + } + + /* + * @see org.eclipse.jface.text.templates.SimpleTemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateContext) + */ + protected String resolve(TemplateContext context) { + StringBuffer expr= new StringBuffer("${"); //$NON-NLS-1$ + expr.append(fVariableName); + for (int i = 0; i < fArguments.length; i++) { + expr.append(':').append(fArguments[i]); + } + expr.append('}'); + IStringVariableManager mgr= VariablesPlugin.getDefault().getStringVariableManager(); + try { + return mgr.performStringSubstitution(expr.toString(), false); + } catch (CoreException exc) { + return expr.toString(); + } + } + + } + + public FileTemplateContextType(String contextTypeId) { + this(contextTypeId, contextTypeId); + } + + public FileTemplateContextType(String contextTypeId, String contextName) { + super(contextTypeId, contextName); + + // global + addResolver(new GlobalTemplateVariables.Dollar()); + addResolver(new DateVariableResolver()); + addResolver(new GlobalTemplateVariables.Year()); + addResolver(new GlobalTemplateVariables.Time()); + addResolver(new GlobalTemplateVariables.User()); + +// addResolver(new CoreVariableResolver("eclipse")); //$NON-NLS-1$ + + addResourceVariables(); + } + + protected void addResourceVariables() { + addResolver(new FileTemplateVariableResolver(FILENAME, TemplateMessages.FileTemplateContextType_variable_description_filename)); + addResolver(new FileTemplateVariableResolver(FILEBASE, TemplateMessages.FileTemplateContextType_variable_description_filebase)); + addResolver(new FileTemplateVariableResolver(FILELOCATION, TemplateMessages.FileTemplateContextType_variable_description_fileloc)); + addResolver(new FileTemplateVariableResolver(FILEPATH, TemplateMessages.FileTemplateContextType_variable_description_filepath)); + addResolver(new FileTemplateVariableResolver(PROJECTNAME, TemplateMessages.FileTemplateContextType_variable_description_projectname)); + } + + protected void validateVariables(TemplateVariable[] variables) throws TemplateException { + ArrayList required= new ArrayList(5); + for (int i= 0; i < variables.length; i++) { + String type= variables[i].getType(); + if (getResolver(type) == null) { + throw new TemplateException(Messages.format(TemplateMessages.FileTemplateContextType_validate_unknownvariable, type)); + } + required.remove(type); + } + if (!required.isEmpty()) { + String missing= (String) required.get(0); + throw new TemplateException(Messages.format(TemplateMessages.FileTemplateContextType_validate_missingvariable, missing)); + } + super.validateVariables(variables); + } + + /* + * @see org.eclipse.jface.text.templates.TemplateContextType#resolve(org.eclipse.jface.text.templates.TemplateVariable, org.eclipse.jface.text.templates.TemplateContext) + */ + public void resolve(TemplateVariable variable, TemplateContext context) { + String type= variable.getType(); + TemplateVariableResolver resolver= getResolver(type); + if (resolver == null) { + resolver= new FileTemplateVariableResolver(type, ""); //$NON-NLS-1$ + } + resolver.resolve(variable, context); + } + + public static void registerContextTypes(ContextTypeRegistry registry) { + IContentTypeManager contentTypeMgr= Platform.getContentTypeManager(); + IContentType[] contentTypes= contentTypeMgr.getAllContentTypes(); + for (int i = 0; i < contentTypes.length; i++) { + IContentType contentType = contentTypes[i]; + if (isTextContentType(contentType) && contentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC).length > 0) { + final String contextTypeId= contextTypeIdForContentType(contentType); + if (registry.getContextType(contextTypeId) == null) { + registry.addContextType(new FileTemplateContextType(contextTypeId, contentType.getName())); + } + } + } + } + + public static String contextTypeIdForContentType(IContentType contentType) { + return contentType.getId() + CONTEXTTYPE_SUFFIX; + } + public static boolean isFileTemplateContextType(String contextTypeId) { + return contextTypeId.endsWith(CONTEXTTYPE_SUFFIX); + } + public static boolean isContextTypeForContentType(String contextTypeId, String contentTypeId) { + return contextTypeId.endsWith(CONTEXTTYPE_SUFFIX) && contextTypeId.startsWith(contentTypeId); + } + public static String contentTypeIdForContextType(String contextTypeId) { + return contextTypeId.substring(0, contextTypeId.length() - CONTEXTTYPE_SUFFIX.length()); + } + + private static boolean isTextContentType(IContentType contentType) { + if (contentType == null) { + return false; + } + String id= contentType.getId(); + if (id.equals(CONTENTTYPE_TEXT)) { + return true; + } + if (id.indexOf(".pde.") != -1 || id.indexOf(".jdt.") != -1) { //$NON-NLS-1$ //$NON-NLS-2$ + return false; + } + return isTextContentType(contentType.getBaseType()); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java index c01d3a70cb1..321cae8ad45 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005 IBM Corporation and others. + * Copyright (c) 2005, 2007 IBM Corporation 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 @@ -8,53 +8,65 @@ * Contributors: * IBM Corporation - initial API and implementation * QnX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.corext.template.c; -import java.text.MessageFormat; -import java.util.MissingResourceException; -import java.util.ResourceBundle; +import org.eclipse.osgi.util.NLS; -public class TemplateMessages { +public final class TemplateMessages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.corext.template.c.TemplateMessages";//$NON-NLS-1$ - private static final String RESOURCE_BUNDLE= TemplateMessages.class.getName(); - private static ResourceBundle fgResourceBundle; - static { - try { - fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE); - } catch (MissingResourceException x) { - fgResourceBundle = null; - } - } private TemplateMessages() { + // Do not instantiate } - public static String getString(String key) { - try { - return fgResourceBundle.getString(key); - } catch (MissingResourceException e) { - return '!' + key + '!'; - } catch (NullPointerException e) { - return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$ - } - } + public static String CContextType_variable_description_file; + public static String CContextType_variable_description_array; + public static String CContextType_variable_description_array_type; + public static String CContextType_variable_description_array_element; + public static String CContextType_variable_description_index; + public static String CContextType_variable_description_collector; + public static String CContextType_variable_description_iterator; + public static String CContextType_variable_description_arguments; + public static String CContextType_variable_description_enclosing_method; + public static String CContextType_variable_description_enclosing_type; + public static String CContextType_variable_description_enclosing_project; + public static String CContextType_variable_description_enclosing_method_arguments; + public static String CContextType_variable_description_return_type; + public static String CContextType_variable_description_todo; - /** - * Gets a string from the resource bundle and formats it with the argument - * - * @param key the string used to get the bundle value, must not be null - */ - public static String getFormattedString(String key, Object arg) { - return MessageFormat.format(getString(key), new Object[] { arg }); + public static String CodeTemplateContextType_variable_description_todo; + public static String CodeTemplateContextType_variable_description_typedeclaration; + public static String CodeTemplateContextType_variable_description_fieldname; + public static String CodeTemplateContextType_variable_description_fieldtype; + public static String CodeTemplateContextType_variable_description_typecomment; + public static String CodeTemplateContextType_variable_description_enclosingtype; + public static String CodeTemplateContextType_variable_description_typename; + public static String CodeTemplateContextType_variable_description_include_guard_symbol; + public static String CodeTemplateContextType_variable_description_enclosingmethod; + public static String CodeTemplateContextType_variable_description_bodystatement; + public static String CodeTemplateContextType_variable_description_returntype; + public static String CodeTemplateContextType_variable_description_filecomment; + public static String CodeTemplateContextType_validate_invalidcomment; + public static String CodeTemplateContextType_csource_name; + public static String CodeTemplateContextType_cheader_name; + public static String CodeTemplateContextType_cppsource_name; + public static String CodeTemplateContextType_cppheader_name; + public static String CodeTemplateContextType_asmsource_name; + + public static String FileTemplateContextType__variable_description_eclipse; + public static String FileTemplateContextType_validate_unknownvariable; + public static String FileTemplateContextType_validate_missingvariable; + public static String FileTemplateContextType_variable_description_date; + public static String FileTemplateContextType_variable_description_filename; + public static String FileTemplateContextType_variable_description_filebase; + public static String FileTemplateContextType_variable_description_fileloc; + public static String FileTemplateContextType_variable_description_filepath; + public static String FileTemplateContextType_variable_description_projectname; + + static { + NLS.initializeMessages(BUNDLE_NAME, TemplateMessages.class); } - - - /** - * Gets a string from the resource bundle and formats it with arguments - */ - public static String getFormattedString(String key, Object[] args) { - return MessageFormat.format(getString(key), args); - } -} - - +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties index 48e4f271229..8692d790f6f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties @@ -11,28 +11,48 @@ # Anton Leherbauer (Wind River Systems) ######################################### -GlobalVariables.variable.description.dollar=The dollar symbol -GlobalVariables.variable.description.cursor=The cursor position after editing template variables +CContextType_variable_description_file=Filename of translation unit +CContextType_variable_description_array=A proposal for an array +CContextType_variable_description_array_type=A proposal for the element type of an array +CContextType_variable_description_array_element=A proposal for the element name of an array +CContextType_variable_description_index=A proposal for an index (int) +CContextType_variable_description_collector=A proposal for a collector +CContextType_variable_description_iterator=A proposal for an iterator +CContextType_variable_description_arguments=Method arguments (evaluates to empty string) +CContextType_variable_description_enclosing_method=Enclosing method name +CContextType_variable_description_enclosing_type=Enclosing type name +CContextType_variable_description_enclosing_project=Enclosing project name +CContextType_variable_description_enclosing_method_arguments=Argument names of enclosing method +CContextType_variable_description_return_type=Enclosing method return type +CContextType_variable_description_todo=Todo task tag -GlobalVariables.variable.description.line=Current line number -GlobalVariables.variable.description.date=Current date -GlobalVariables.variable.description.time=Current time -GlobalVariables.variable.description.user=User name +CodeTemplateContextType_variable_description_todo=Todo task tag +CodeTemplateContextType_variable_description_typedeclaration=Generated type declaration +CodeTemplateContextType_variable_description_fieldname=The name of field +CodeTemplateContextType_variable_description_fieldtype=The type of the field +CodeTemplateContextType_variable_description_typecomment=Content of code template 'Comments > Types' +CodeTemplateContextType_variable_description_enclosingtype=The enclosing type +CodeTemplateContextType_variable_description_typename=Name of the current type +CodeTemplateContextType_variable_description_include_guard_symbol=Include guard symbol +CodeTemplateContextType_variable_description_enclosingmethod=The enclosing method +CodeTemplateContextType_variable_description_bodystatement=Return statement or super call +CodeTemplateContextType_variable_description_returntype=Return type of the enclosing method +CodeTemplateContextType_variable_description_filecomment=Content of code template 'Comments > Files' -#JavaDocContextType.variable.description.file=Filename of translation unit +CodeTemplateContextType_validate_invalidcomment=Pattern is not a valid C/C++ comment. -CContextType.variable.description.file=Filename of translation unit -CContextType.variable.description.array=A proposal for an array -CContextType.variable.description.array.type=A proposal for the element type of an array -CContextType.variable.description.array.element=A proposal for the element name of an array -CContextType.variable.description.index=A proposal for an index (int) -CContextType.variable.description.collector=A proposal for a collector -CContextType.variable.description.iterator=A proposal for an iterator -CContextType.variable.description.arguments=Method arguments (evaluates to empty string) -CContextType.variable.description.enclosing.method=Enclosing method name -CContextType.variable.description.enclosing.type=Enclosing type name -#CContextType.variable.description.enclosing.package=Enclosing package name -CContextType.variable.description.enclosing.project=Enclosing project name -CContextType.variable.description.enclosing.method.arguments=Argument names of enclosing method -CContextType.variable.description.return.type=Enclosing method return type -CContextType.variable.description.todo=Todo task tag +CodeTemplateContextType_csource_name=C Source File +CodeTemplateContextType_cheader_name=C Header File +CodeTemplateContextType_cppsource_name=C++ Source File +CodeTemplateContextType_cppheader_name=C++ Header File +CodeTemplateContextType_asmsource_name=Assembly Source File + +FileTemplateContextType__variable_description_eclipse=Resolve Eclipse core variables +FileTemplateContextType_validate_unknownvariable=Variable ''{0}'' is unknown. +FileTemplateContextType_validate_missingvariable=Variable ''{0}'' is required. +FileTemplateContextType_variable_description_date= Current date +FileTemplateContextType_variable_description_filename=Name of the file +FileTemplateContextType_variable_description_filebase=Name of the file without extension +FileTemplateContextType_variable_description_fileloc=File system location of the file +FileTemplateContextType_variable_description_filepath=Workspace path of the file +FileTemplateContextType_variable_description_projectname=Name of the enclosing project diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContext.java index 6c8ea8b70c0..eea31001e00 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContext.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContext.java @@ -27,8 +27,7 @@ import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil; - -import org.eclipse.cdt.internal.ui.util.Strings; +import org.eclipse.cdt.internal.corext.util.Strings; /** * A translation unit context. @@ -88,7 +87,7 @@ public abstract class TranslationUnitContext extends DocumentTemplateContext { /* - * @see org.eclipse.jdt.internal.corext.template.DocumentTemplateContext#getKey() + * @see org.eclipse.cdt.internal.corext.template.DocumentTemplateContext#getKey() */ public String getKey() { if (getCompletionLength() == 0) @@ -166,7 +165,7 @@ public abstract class TranslationUnitContext extends DocumentTemplateContext { IRegion region= document.getLineInformationOfOffset(start); String lineContent= document.get(region.getOffset(), region.getLength()); ICProject project= getCProject(); - return Strings.computeIndent(lineContent, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project)); + return Strings.computeIndentUnits(lineContent, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project)); } catch (BadLocationException e) { return 0; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContextType.java index e911cf6ce05..1b202d1c0af 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContextType.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TranslationUnitContextType.java @@ -25,7 +25,8 @@ import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.IFunctionDeclaration; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.internal.ui.codemanipulation.StubUtility; +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + /** * A context type for translation units. @@ -34,7 +35,7 @@ public abstract class TranslationUnitContextType extends TemplateContextType { protected static class ReturnType extends TemplateVariableResolver { public ReturnType() { - super("return_type", TemplateMessages.getString("CContextType.variable.description.return.type")); //$NON-NLS-1$ //$NON-NLS-2$ + super("return_type", TemplateMessages.CContextType_variable_description_return_type); //$NON-NLS-1$ } public String resolve(TemplateContext context) { ICElement element= ((TranslationUnitContext) context).findEnclosingElement(ICElement.C_METHOD); @@ -54,7 +55,7 @@ public abstract class TranslationUnitContextType extends TemplateContextType { protected static class File extends TemplateVariableResolver { public File() { - super("file", TemplateMessages.getString("CContextType.variable.description.file")); //$NON-NLS-1$ //$NON-NLS-2$ + super("file", TemplateMessages.CContextType_variable_description_file); //$NON-NLS-1$ } public String resolve(TemplateContext context) { ITranslationUnit unit= ((TranslationUnitContext) context).getTranslationUnit(); @@ -78,37 +79,13 @@ public abstract class TranslationUnitContextType extends TemplateContextType { protected static class Method extends EnclosingCElement { public Method() { - super("enclosing_method", TemplateMessages.getString("CContextType.variable.description.enclosing.method"), ICElement.C_METHOD); //$NON-NLS-1$ //$NON-NLS-2$ + super("enclosing_method", TemplateMessages.CContextType_variable_description_enclosing_method, ICElement.C_METHOD); //$NON-NLS-1$ } } - /* - protected static class Type extends EnclosingCElement { - public Type() { - super("enclosing_type", TemplateMessages.getString("CContextType.variable.description.enclosing.type"), 0); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - protected static class SuperClass extends EnclosingCElement { - public Type() { - super("super_class", TemplateMessages.getString("CContextType.variable.description.type"), IJavaElement.TYPE); - } - } - - protected static class Package extends EnclosingCElement { - public Package() { - super("enclosing_package", TemplateMessages.getString("CContextType.variable.description.enclosing.package"), 0); //$NON-NLS-1$ //$NON-NLS-2$ - } - } -*/ -// protected static class Project extends EnclosingCElement { -// public Project() { -// super("enclosing_project", TemplateMessages.getString("CContextType.variable.description.enclosing.project"), ICElement.C_PROJECT); //$NON-NLS-1$ //$NON-NLS-2$ -// } -// } - protected static class Project extends TemplateVariableResolver { public Project() { - super("enclosing_project", TemplateMessages.getString("CContextType.variable.description.enclosing.project")); //$NON-NLS-1$ //$NON-NLS-2$ + super("enclosing_project", TemplateMessages.CContextType_variable_description_enclosing_project); //$NON-NLS-1$ } public String resolve(TemplateContext context) { ITranslationUnit unit= ((TranslationUnitContext) context).getTranslationUnit(); @@ -118,7 +95,7 @@ public abstract class TranslationUnitContextType extends TemplateContextType { protected static class Arguments extends TemplateVariableResolver { public Arguments() { - super("enclosing_method_arguments", TemplateMessages.getString("CContextType.variable.description.enclosing.method.arguments")); //$NON-NLS-1$ //$NON-NLS-2$ + super("enclosing_method_arguments", TemplateMessages.CContextType_variable_description_enclosing_method_arguments); //$NON-NLS-1$ } public String resolve(TemplateContext context) { ICElement element= ((TranslationUnitContext) context).findEnclosingElement(ICElement.C_FUNCTION); @@ -151,7 +128,7 @@ public abstract class TranslationUnitContextType extends TemplateContextType { protected static class Todo extends TemplateVariableResolver { public Todo() { - super("todo", TemplateMessages.getString("CContextType.variable.description.todo")); //$NON-NLS-1$ //$NON-NLS-2$ + super("todo", TemplateMessages.CContextType_variable_description_todo); //$NON-NLS-1$ } protected String resolve(TemplateContext context) { TranslationUnitContext cContext= (TranslationUnitContext) context; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java new file mode 100644 index 00000000000..e3f442ba197 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java @@ -0,0 +1,428 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.corext.util; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.action.LegacyActionTools; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultLineTracker; +import org.eclipse.jface.text.ILineTracker; +import org.eclipse.jface.text.IRegion; + +import org.eclipse.cdt.core.formatter.IndentManipulation; +import org.eclipse.cdt.core.model.ICProject; + + +/** + * Helper class to provide String manipulation functions not available in standard JDK. + */ +public class Strings { + + private Strings(){} + + public static boolean startsWithIgnoreCase(String text, String prefix) { + int textLength= text.length(); + int prefixLength= prefix.length(); + if (textLength < prefixLength) + return false; + for (int i= prefixLength - 1; i >= 0; i--) { + if (Character.toLowerCase(prefix.charAt(i)) != Character.toLowerCase(text.charAt(i))) + return false; + } + return true; + } + + public static String removeNewLine(String message) { + StringBuffer result= new StringBuffer(); + int current= 0; + int index= message.indexOf('\n', 0); + while (index != -1) { + result.append(message.substring(current, index)); + if (current < index && index != 0) + result.append(' '); + current= index + 1; + index= message.indexOf('\n', current); + } + result.append(message.substring(current)); + return result.toString(); + } + + /** + * Converts the given string into an array of lines. The lines + * don't contain any line delimiter characters. + * + * @return the string converted into an array of strings. Returns + * null if the input string can't be converted in an array of lines. + */ + public static String[] convertIntoLines(String input) { + try { + ILineTracker tracker= new DefaultLineTracker(); + tracker.set(input); + int size= tracker.getNumberOfLines(); + String result[]= new String[size]; + for (int i= 0; i < size; i++) { + IRegion region= tracker.getLineInformation(i); + int offset= region.getOffset(); + result[i]= input.substring(offset, offset + region.getLength()); + } + return result; + } catch (BadLocationException e) { + return null; + } + } + + /** + * Returns true if the given string only consists of + * white spaces according to Java. If the string is empty, true + * is returned. + * + * @return true if the string only consists of white + * spaces; otherwise false is returned + * + * @see java.lang.Character#isWhitespace(char) + */ + public static boolean containsOnlyWhitespaces(String s) { + int size= s.length(); + for (int i= 0; i < size; i++) { + if (!Character.isWhitespace(s.charAt(i))) + return false; + } + return true; + } + + /** + * Removes leading tabs and spaces from the given string. If the string + * doesn't contain any leading tabs or spaces then the string itself is + * returned. + */ + public static String trimLeadingTabsAndSpaces(String line) { + int size= line.length(); + int start= size; + for (int i= 0; i < size; i++) { + char c= line.charAt(i); + if (!IndentManipulation.isIndentChar(c)) { + start= i; + break; + } + } + if (start == 0) + return line; + else if (start == size) + return ""; //$NON-NLS-1$ + else + return line.substring(start); + } + + public static String trimTrailingTabsAndSpaces(String line) { + int size= line.length(); + int end= size; + for (int i= size - 1; i >= 0; i--) { + char c= line.charAt(i); + if (IndentManipulation.isIndentChar(c)) { + end= i; + } else { + break; + } + } + if (end == size) + return line; + else if (end == 0) + return ""; //$NON-NLS-1$ + else + return line.substring(0, end); + } + + /** + * Returns the indent of the given string in indentation units. Odd spaces + * are not counted. + * + * @param line the text line + * @param project the project from which to get the formatter + * preferences, or null for global preferences + * @since 5.0 + */ + public static int computeIndentUnits(String line, ICProject project) { + return IndentManipulation.measureIndentUnits(line, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project)); + } + + /** + * Returns the indent of the given string in indentation units. Odd spaces + * are not counted. + * + * @param line the text line + * @param tabWidth the width of the '\t' character in space equivalents + * @param indentWidth the width of one indentation unit in space equivalents + * @since 5.0 + */ + public static int computeIndentUnits(String line, int tabWidth, int indentWidth) { + return IndentManipulation.measureIndentUnits(line, tabWidth, indentWidth); + } + + /** + * Computes the visual length of the indentation of a + * CharSequence, counting a tab character as the size until + * the next tab stop and every other whitespace character as one. + * + * @param line the string to measure the indent of + * @param tabSize the visual size of a tab in space equivalents + * @return the visual length of the indentation of line + * @since 5.0 + */ + public static int measureIndentLength(CharSequence line, int tabSize) { + return IndentManipulation.measureIndentInSpaces(line, tabSize); + } + + /** + * Removes the given number of indents from the line. Asserts that the given line + * has the requested number of indents. If indentsToRemove <= 0 + * the line is returned. + * + * @param project the project from which to get the formatter + * preferences, or null for global preferences + * @since 5.0 + */ + public static String trimIndent(String line, int indentsToRemove, ICProject project) { + return IndentManipulation.trimIndent(line, indentsToRemove, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project)); + } + + /** + * Removes the given number of indents from the line. Asserts that the given line + * has the requested number of indents. If indentsToRemove <= 0 + * the line is returned. + * + * @since 5.0 + */ + public static String trimIndent(String line, int indentsToRemove, int tabWidth, int indentWidth) { + return IndentManipulation.trimIndent(line, indentsToRemove, tabWidth, indentWidth); + } + + /** + * Removes the common number of indents from all lines. If a line + * only consists out of white space it is ignored. + + * @param project the project from which to get the formatter + * preferences, or null for global preferences + * @since 5.0 + */ + public static void trimIndentation(String[] lines, ICProject project) { + trimIndentation(lines, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project), true); + } + /** + * Removes the common number of indents from all lines. If a line + * only consists out of white space it is ignored. + * + * @since 5.0 + */ + public static void trimIndentation(String[] lines, int tabWidth, int indentWidth) { + trimIndentation(lines, tabWidth, indentWidth, true); + } + + /** + * Removes the common number of indents from all lines. If a line + * only consists out of white space it is ignored. If + * considerFirstLine is false the first line will be ignored. + * + * @param project the project from which to get the formatter + * preferences, or null for global preferences + * @since 5.0 + */ + public static void trimIndentation(String[] lines, ICProject project, boolean considerFirstLine) { + trimIndentation(lines, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project), considerFirstLine); + } + + /** + * Removes the common number of indents from all lines. If a line + * only consists out of white space it is ignored. If + * considerFirstLine is false the first line will be ignored. + * @since 5.0 + */ + public static void trimIndentation(String[] lines, int tabWidth, int indentWidth, boolean considerFirstLine) { + String[] toDo= new String[lines.length]; + // find indentation common to all lines + int minIndent= Integer.MAX_VALUE; // very large + for (int i= considerFirstLine ? 0 : 1; i < lines.length; i++) { + String line= lines[i]; + if (containsOnlyWhitespaces(line)) + continue; + toDo[i]= line; + int indent= computeIndentUnits(line, tabWidth, indentWidth); + if (indent < minIndent) { + minIndent= indent; + } + } + + if (minIndent > 0) { + // remove this indent from all lines + for (int i= considerFirstLine ? 0 : 1; i < toDo.length; i++) { + String s= toDo[i]; + if (s != null) + lines[i]= trimIndent(s, minIndent, tabWidth, indentWidth); + else { + String line= lines[i]; + int indent= computeIndentUnits(line, tabWidth, indentWidth); + if (indent > minIndent) + lines[i]= trimIndent(line, minIndent, tabWidth, indentWidth); + else + lines[i]= trimLeadingTabsAndSpaces(line); + } + } + } + } + + /** + * Returns that part of the indentation of line that makes up + * a multiple of indentation units. + * + * @param line the line to scan + * @param project the project from which to get the formatter + * preferences, or null for global preferences + * @return the indent part of line, but no odd spaces + * @since 5.0 + */ + public static String getIndentString(String line, ICProject project) { + return IndentManipulation.extractIndentString(line, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project)); + } + + /** + * Returns that part of the indentation of line that makes up + * a multiple of indentation units. + * + * @param line the line to scan + * @param tabWidth the size of one tab in space equivalents + * @param indentWidth the size of the indent in space equivalents + * @return the indent part of line, but no odd spaces + * @since 5.0 + */ + public static String getIndentString(String line, int tabWidth, int indentWidth) { + return IndentManipulation.extractIndentString(line, tabWidth, indentWidth); + } + + public static String[] removeTrailingEmptyLines(String[] sourceLines) { + int lastNonEmpty= findLastNonEmptyLineIndex(sourceLines); + String[] result= new String[lastNonEmpty + 1]; + for (int i= 0; i < result.length; i++) { + result[i]= sourceLines[i]; + } + return result; + } + + private static int findLastNonEmptyLineIndex(String[] sourceLines) { + for (int i= sourceLines.length - 1; i >= 0; i--) { + if (! sourceLines[i].trim().equals(""))//$NON-NLS-1$ + return i; + } + return -1; + } + + /** + * Change the indent of, possible muti-line, code range. The current indent is removed, a new indent added. + * The first line of the code will not be changed. (It is considered to have no indent as it might start in + * the middle of a line) + * + * @param project the project from which to get the formatter + * preferences, or null for global preferences + * @since 5.0 + */ + public static String changeIndent(String code, int codeIndentLevel, ICProject project, String newIndent, String lineDelim) { + return IndentManipulation.changeIndent(code, codeIndentLevel, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project), newIndent, lineDelim); + } + + /** + * Change the indent of, possible muti-line, code range. The current indent is removed, a new indent added. + * The first line of the code will not be changed. (It is considered to have no indent as it might start in + * the middle of a line) + * @since 5.0 + */ + public static String changeIndent(String code, int codeIndentLevel, int tabWidth, int indentWidth, String newIndent, String lineDelim) { + return IndentManipulation.changeIndent(code, codeIndentLevel, tabWidth, indentWidth, newIndent, lineDelim); + } + + public static String trimIndentation(String source, ICProject project, boolean considerFirstLine) { + return trimIndentation(source, CodeFormatterUtil.getTabWidth(project), CodeFormatterUtil.getIndentWidth(project), considerFirstLine); + } + + public static String trimIndentation(String source, int tabWidth, int indentWidth, boolean considerFirstLine) { + try { + ILineTracker tracker= new DefaultLineTracker(); + tracker.set(source); + int size= tracker.getNumberOfLines(); + if (size == 1) + return source; + String lines[]= new String[size]; + for (int i= 0; i < size; i++) { + IRegion region= tracker.getLineInformation(i); + int offset= region.getOffset(); + lines[i]= source.substring(offset, offset + region.getLength()); + } + Strings.trimIndentation(lines, tabWidth, indentWidth, considerFirstLine); + StringBuffer result= new StringBuffer(); + int last= size - 1; + for (int i= 0; i < size; i++) { + result.append(lines[i]); + if (i < last) + result.append(tracker.getLineDelimiter(i)); + } + return result.toString(); + } catch (BadLocationException e) { + Assert.isTrue(false,"Can not happend"); //$NON-NLS-1$ + return null; + } + } + + + /** + * Concatenate the given strings into one strings using the passed line delimiter as a + * delimiter. No delimiter is added to the last line. + */ + public static String concatenate(String[] lines, String delimiter) { + StringBuffer buffer= new StringBuffer(); + for (int i= 0; i < lines.length; i++) { + if (i > 0) + buffer.append(delimiter); + buffer.append(lines[i]); + } + return buffer.toString(); + } + + public static boolean equals(String s, char[] c) { + if (s.length() != c.length) + return false; + + for (int i = c.length; --i >= 0;) + if (s.charAt(i) != c[i]) + return false; + return true; + } + + public static String removeTrailingCharacters(String text, char toRemove) { + int size= text.length(); + int end= size; + for (int i= size - 1; i >= 0; i--) { + char c= text.charAt(i); + if (c == toRemove) { + end= i; + } else { + break; + } + } + if (end == size) + return text; + else if (end == 0) + return ""; //$NON-NLS-1$ + else + return text.substring(0, end); + } + + public static String removeMnemonicIndicator(String string) { + return LegacyActionTools.removeMnemonics(string); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java index 8c6fc2eb056..7cb4d43cf4b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * QNX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui; @@ -82,6 +83,7 @@ public interface ICHelpContextIds { public static final String APPEARANCE_PREFERENCE_PAGE = PREFIX + "appearance_preference_page_context"; //$NON-NLS-1$ public static final String SPELLING_CONFIGURATION_BLOCK= PREFIX + "spelling_configuration_block_context"; //$NON-NLS-1$ + public static final String CODE_TEMPLATES_PREFERENCE_PAGE = PREFIX + "code_templates_preference_context"; //$NON-NLS-1$ // Console view public static final String CLEAR_CONSOLE_ACTION = PREFIX + "clear_console_action_context"; //$NON-NLS-1$ @@ -119,6 +121,9 @@ public interface ICHelpContextIds { public static final String CLEAR_WORKING_SET_ACTION= PREFIX + "clear_working_set_action"; //$NON-NLS-1$ public static final String SELECT_WORKING_SET_ACTION= PREFIX + "select_working_set_action"; //$NON-NLS-1$ + // Dialogs + public static final String EDIT_TEMPLATE_DIALOG = PREFIX + "edit_template_dialog_context"; //$NON-NLS-1$ + // view parts public static final String TYPE_HIERARCHY_VIEW= PREFIX + "type_hierarchy_view_context"; //$NON-NLS-1$ public static final String PACKAGES_VIEW= PREFIX + "package_view_context"; //$NON-NLS-1$ @@ -163,5 +168,5 @@ public interface ICHelpContextIds { public static final String C_SEARCH_VIEW = PREFIX + "search_view"; //$NON-NLS-1$ public static final String PATHENTRY_VARIABLES_PREFERENCE_PAGE= PREFIX + "pathentry_variables_preference_page_context"; //$NON-NLS-1$ - + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/codemanipulation/StubUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/codemanipulation/StubUtility.java deleted file mode 100644 index 052a90c257a..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/codemanipulation/StubUtility.java +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2007 IBM Corporation 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: - * Rational Software - initial implementation - * Anton Leherbauer (Wind River Systems) - *******************************************************************************/ -package org.eclipse.cdt.internal.ui.codemanipulation; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.swt.SWT; - -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.CCorePreferenceConstants; -import org.eclipse.cdt.core.model.CModelException; -import org.eclipse.cdt.core.model.IBuffer; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.model.ITranslationUnit; - -public class StubUtility { - - /** - * Not implemented, returns "". - */ - public static String getHeaderFileContent(ITranslationUnit cu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return ""; //$NON-NLS-1$ - } - /** - * Not implemented, returns "". - */ - public static String getBodyFileContent(ITranslationUnit cu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return ""; //$NON-NLS-1$ - } - /** - * Not implemented, returns "". - */ - public static String getClassComment(ITranslationUnit cu, String typeQualifiedName, String lineDelim) throws CoreException { - return ""; //$NON-NLS-1$ - } - - /** - * Examines a string and returns the first line delimiter found. - */ - public static String getLineDelimiterUsed(ICElement elem) throws CModelException { - if (elem == null) return ""; //$NON-NLS-1$ - - ITranslationUnit cu= (ITranslationUnit) elem.getAncestor(ICElement.C_UNIT); - if (cu != null && cu.exists()) { - IBuffer buf= cu.getBuffer(); - int length= buf.getLength(); - for (int i= 0; i < length; i++) { - char ch= buf.getChar(i); - if (ch == SWT.CR) { - if (i + 1 < length) { - if (buf.getChar(i + 1) == SWT.LF) { - return "\r\n"; //$NON-NLS-1$ - } - } - return "\r"; //$NON-NLS-1$ - } else if (ch == SWT.LF) { - return "\n"; //$NON-NLS-1$ - } - } - } - return System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - /** - * Get the default task tag for the given project. - * - * @param project - * @return the default task tag - */ - public static String getTodoTaskTag(ICProject project) { - String markers= null; - if (project == null) { - markers= CCorePlugin.getOption(CCorePreferenceConstants.TODO_TASK_TAGS); - } else { - markers= project.getOption(CCorePreferenceConstants.TODO_TASK_TAGS, true); - } - - if (markers != null && markers.length() > 0) { - int idx= markers.indexOf(','); - if (idx == -1) { - return markers; - } else { - return markers.substring(0, idx); - } - } - return CCorePreferenceConstants.DEFAULT_TASK_TAG; - } - -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathContainerEntryPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathContainerEntryPage.java index fcd3e230e25..99c636a0820 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathContainerEntryPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathContainerEntryPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.dialogs.cpaths; @@ -73,7 +74,7 @@ public class CPathContainerEntryPage extends CPathBasePage { fContainersList.enableButton(IDX_EXPORT, false); fContainersList.setTreeExpansionLevel(2); - fContainersList.setViewerSorter(new CPElementSorter()); + fContainersList.setViewerComparator(new CPElementSorter()); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathLibraryEntryPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathLibraryEntryPage.java index 972da8ec9d9..1c069155e81 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathLibraryEntryPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathLibraryEntryPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2006 QNX Software Systems and others. + * Copyright (c) 2002, 2007 QNX Software Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.dialogs.cpaths; @@ -95,7 +96,7 @@ public class CPathLibraryEntryPage extends CPathBasePage { fLibrariesList.setDialogFieldListener(adapter); fLibrariesList.setLabelText(CPathEntryMessages.getString("LibrariesEntryPage.libraries.label")); //$NON-NLS-1$ - fLibrariesList.setViewerSorter(new CPElementSorter()); + fLibrariesList.setViewerComparator(new CPElementSorter()); fLibrariesList.enableButton(IDX_EDIT, false); fLibrariesList.enableButton(IDX_REMOVE, false); fLibrariesList.enableButton(IDX_EXPORT, false); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathOutputEntryPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathOutputEntryPage.java index c96af2bf0a8..533058365cd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathOutputEntryPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathOutputEntryPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2006 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.dialogs.cpaths; @@ -88,7 +89,7 @@ public class CPathOutputEntryPage extends CPathBasePage { fOutputList.setDialogFieldListener(adapter); fOutputList.setLabelText(CPathEntryMessages.getString("OutputPathEntryPage.folders.label")); //$NON-NLS-1$ - fOutputList.setViewerSorter(new CPElementSorter()); + fOutputList.setViewerComparator(new CPElementSorter()); fOutputList.enableButton(IDX_EDIT, false); fOutputList.enableButton(IDX_REMOVE, false); fOutputList.setTreeExpansionLevel(2); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathSourceEntryPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathSourceEntryPage.java index fb5cc974b89..f64a591252a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathSourceEntryPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/cpaths/CPathSourceEntryPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2006 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.dialogs.cpaths; @@ -88,7 +89,7 @@ public class CPathSourceEntryPage extends CPathBasePage { fFoldersList.setDialogFieldListener(adapter); fFoldersList.setLabelText(CPathEntryMessages.getString("SourcePathEntryPage.folders.label")); //$NON-NLS-1$ - fFoldersList.setViewerSorter(new CPElementSorter()); + fFoldersList.setViewerComparator(new CPElementSorter()); fFoldersList.enableButton(IDX_EDIT, false); fFoldersList.enableButton(IDX_REMOVE, false); fFoldersList.setTreeExpansionLevel(2); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java index d92521dbe49..cc7f5f52dd7 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java @@ -63,10 +63,11 @@ import org.eclipse.cdt.ui.IRequiredInclude; import org.eclipse.cdt.ui.browser.typeinfo.TypeInfoLabelProvider; import org.eclipse.cdt.ui.text.ICHelpInvocationContext; +import org.eclipse.cdt.internal.corext.codemanipulation.AddIncludesOperation; + import org.eclipse.cdt.internal.ui.CHelpProviderManager; import org.eclipse.cdt.internal.ui.ICHelpContextIds; import org.eclipse.cdt.internal.ui.actions.WorkbenchRunnableAdapter; -import org.eclipse.cdt.internal.ui.codemanipulation.AddIncludesOperation; import org.eclipse.cdt.internal.ui.text.CWordFinder; import org.eclipse.cdt.internal.ui.util.ExceptionHandler; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CSourcePreviewerUpdater.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CSourcePreviewerUpdater.java index aff9280a10a..1466bdbe8a6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CSourcePreviewerUpdater.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CSourcePreviewerUpdater.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 QNX Software Systems and others. + * Copyright (c) 2000, 2007 QNX Software Systems 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 @@ -28,11 +28,19 @@ import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; public class CSourcePreviewerUpdater { - private CSourcePreviewerUpdater() { + /** + * Handles editor font changes for source preview viewers. + * + * @param viewer + * @param configuration + * @param store + */ + public CSourcePreviewerUpdater(SourceViewer viewer, CodeTemplateSourceViewerConfiguration configuration, IPreferenceStore store) { + registerPreviewer(viewer, configuration, store); } /** - * Creates a source preview updater for the given viewer, configuration and preference store. + * Registers a source preview updater for the given viewer, configuration and preference store. * * @param viewer the viewer * @param configuration the configuration diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java index ac1e7aadfc3..f2711eee80b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java @@ -46,6 +46,7 @@ public final class CodeAssistAdvancedPreferencePage extends PropertyAndPreferenc } protected String getPropertyPageID() { + // no project settings supported return null; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeFormatterPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeFormatterPreferencePage.java index 087bdc8789d..959da136de9 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeFormatterPreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeFormatterPreferencePage.java @@ -79,15 +79,15 @@ public class CodeFormatterPreferencePage extends PropertyAndPreferencePage { return fConfigurationBlock.hasProjectSpecificOptions(project); } -// /* (non-Javadoc) -// * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#enableProjectSpecificSettings(boolean) -// */ -// protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { -// super.enableProjectSpecificSettings(useProjectSpecificSettings); -// if (fConfigurationBlock != null) { -// fConfigurationBlock.enableProjectSpecificSettings(useProjectSpecificSettings); -// } -// } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#enableProjectSpecificSettings(boolean) + */ + protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { + super.enableProjectSpecificSettings(useProjectSpecificSettings); + if (fConfigurationBlock != null) { + fConfigurationBlock.enableProjectSpecificSettings(useProjectSpecificSettings); + } + } /* (non-Javadoc) * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#getPreferencePageID() @@ -100,7 +100,9 @@ public class CodeFormatterPreferencePage extends PropertyAndPreferencePage { * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#getPropertyPageID() */ protected String getPropertyPageID() { - return PROP_ID; + return null; + // project specific settings unsupported for now +// return PROP_ID; } /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java new file mode 100644 index 00000000000..afbf58a2d7c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java @@ -0,0 +1,832 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.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.TemplateReaderWriter; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; + +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.corext.template.c.CodeTemplateContextType; +import org.eclipse.cdt.internal.corext.template.c.FileTemplateContextType; +import org.eclipse.cdt.internal.corext.util.Messages; + +import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener; +import org.eclipse.cdt.internal.ui.editor.CSourceViewer; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.text.template.TemplateVariableProcessor; +import org.eclipse.cdt.internal.ui.util.PixelConverter; +import org.eclipse.cdt.internal.ui.viewsupport.ProjectTemplateStore; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.ITreeListAdapter; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.TreeListDialogField; + +/** + */ +public class CodeTemplateBlock extends OptionsConfigurationBlock { + + private class CodeTemplateAdapter extends ViewerComparator implements ITreeListAdapter, IDialogFieldListener { + + private final Object[] NO_CHILDREN= new Object[0]; + + public void customButtonPressed(TreeListDialogField field, int index) { + doButtonPressed(index, field.getSelectedElements()); + } + + public void selectionChanged(TreeListDialogField field) { + List selected= field.getSelectedElements(); + field.enableButton(IDX_ADD, canAdd(selected)); + field.enableButton(IDX_EDIT, canEdit(selected)); + field.enableButton(IDX_REMOVE, canRemove(selected)); + field.enableButton(IDX_EXPORT, !selected.isEmpty()); + + updateSourceViewerInput(selected); + } + + public void doubleClicked(TreeListDialogField field) { + List selected= field.getSelectedElements(); + if (canEdit(selected)) { + doButtonPressed(IDX_EDIT, selected); + } + } + + public Object[] getChildren(TreeListDialogField field, Object element) { + if (element == COMMENT_NODE || element == CODE_NODE) { + return getCodeTemplatesOfCategory(element == COMMENT_NODE); + } else if (element == FILE_NODE) { + return getFileTemplateContextTypes(); + } else if (element instanceof TemplateContextType) { + return getTemplatesOfContextType(((TemplateContextType)element).getId()); + } + return NO_CHILDREN; + } + + public Object getParent(TreeListDialogField field, Object element) { + if (element instanceof TemplatePersistenceData) { + TemplatePersistenceData data= (TemplatePersistenceData) element; + if (data.getTemplate().getName().endsWith(CodeTemplateContextType.COMMENT_SUFFIX)) { + return COMMENT_NODE; + } + if (FileTemplateContextType.isFileTemplateContextType(data.getTemplate().getContextTypeId())) { + return getFileTemplateContextRegistry().getContextType(data.getTemplate().getContextTypeId()); + } + return CODE_NODE; + } else if (element instanceof TemplateContextType) { + return FILE_NODE; + } + return null; + } + + public boolean hasChildren(TreeListDialogField field, Object element) { + return (element == COMMENT_NODE || element == CODE_NODE || element == FILE_NODE || element instanceof TemplateContextType); + } + + public void dialogFieldChanged(DialogField field) { + if (field == fGenerateComments) { + setValue(PREF_GENERATE_COMMENTS, fGenerateComments.isSelected()); + } + } + + public void keyPressed(TreeListDialogField field, KeyEvent event) { + } + + /* + * @see org.eclipse.jface.viewers.ViewerSorter#category(java.lang.Object) + */ + public int category(Object element) { + if (element == COMMENT_NODE) { + return 1; + } else if (element == CODE_NODE) { + return 2; + } else if (element == FILE_NODE) { + return 3; + } else if (element instanceof TemplateContextType) { + TemplateContextType type= (TemplateContextType) element; + String id= type.getId(); + if (CodeTemplateContextType.CPPSOURCEFILE_CONTEXTTYPE.equals(id)) { + return 1; + } else if (CodeTemplateContextType.CPPHEADERFILE_CONTEXTTYPE.equals(id)) { + return 2; + } else if (CodeTemplateContextType.CSOURCEFILE_CONTEXTTYPE.equals(id)) { + return 10; + } else if (CodeTemplateContextType.CHEADERFILE_CONTEXTTYPE.equals(id)) { + return 11; + } else if (CodeTemplateContextType.ASMSOURCEFILE_CONTEXTTYPE.equals(id)) { + return 100; + } else if (id.startsWith("org.eclipse.cdt.")) { //$NON-NLS-1$ + return 101; + } + return 1000; + } + + TemplatePersistenceData data= (TemplatePersistenceData) element; + String id= data.getId(); + + if (CodeTemplateContextType.ASMSOURCEFILE_CONTEXTTYPE.equals(id)) { + return 105; + } else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) { + return 106; + } else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) { + return 107; + } else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) { + return 108; + } else if (CodeTemplateContextType.FILECOMMENT_ID.equals(id)) { + return 1; + } else if (CodeTemplateContextType.TYPECOMMENT_ID.equals(id)) { + return 2; + } else if (CodeTemplateContextType.FIELDCOMMENT_ID.equals(id)) { + return 3; + } else if (CodeTemplateContextType.METHODCOMMENT_ID.equals(id)) { + return 4; + } else if (CodeTemplateContextType.CONSTRUCTORCOMMENT_ID.equals(id)) { + return 5; + } else if (CodeTemplateContextType.DESTRUCTORCOMMENT_ID.equals(id)) { + return 6; + } + return 1000; + } + } + + private static class CodeTemplateLabelProvider extends LabelProvider { + + /* + * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object) + */ + public Image getImage(Object element) { +// if (element == COMMENT_NODE || element == CODE_NODE || element == FILE_NODE) { +// return null; +// } +// if (element instanceof TemplateContextType) { +// String id= ((TemplateContextType)element).getId(); +// if (FileTemplateContextType.isFileTemplateContextType(id)) { +// IContentType contentType= FileTemplateContextType.getContentTypeFromConextType(id); +// if (contentType != null) { +// String dummyFileName; +// String[] fileSpecs= contentType.getFileSpecs(IContentType.FILE_NAME_SPEC); +// if (fileSpecs.length > 0) { +// dummyFileName= fileSpecs[0]; +// } else { +// String[] extSpecs= contentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC); +// if (extSpecs.length > 0) { +// dummyFileName= "dummy" + extSpecs[0]; //$NON-NLS-1$ +// } else { +// dummyFileName= "dummy"; //$NON-NLS-1$ +// } +// } +// IEditorRegistry editorRegistry= PlatformUI.getWorkbench().getEditorRegistry(); +// IEditorDescriptor[] editorDesc= editorRegistry.getEditors(dummyFileName, contentType); +// if (editorDesc.length > 0) { +// ImageDescriptor desc= editorDesc[0].getImageDescriptor(); +// return CUIPlugin.getImageDescriptorRegistry().get(desc); +// } +// } +// } +// } + return null; + + } + + /* + * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + if (element == COMMENT_NODE || element == CODE_NODE || element == FILE_NODE) { + return (String) element; + } + if (element instanceof TemplateContextType) { + return ((TemplateContextType)element).getName(); + } + TemplatePersistenceData data= (TemplatePersistenceData) element; + String id= data.getId(); + if (FileTemplateContextType.isFileTemplateContextType(data.getTemplate().getContextTypeId())) { + return data.getTemplate().getName(); + } else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_methodstub_label; + } else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_constructorstub_label; + } else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_destructorstub_label; + } else if (CodeTemplateContextType.FILECOMMENT_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_filecomment_label; + } else if (CodeTemplateContextType.TYPECOMMENT_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_typecomment_label; + } else if (CodeTemplateContextType.FIELDCOMMENT_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_fieldcomment_label; + } else if (CodeTemplateContextType.METHODCOMMENT_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_methodcomment_label; + } else if (CodeTemplateContextType.CONSTRUCTORCOMMENT_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_constructorcomment_label; + } else if (CodeTemplateContextType.DESTRUCTORCOMMENT_ID.equals(id)) { + return PreferencesMessages.CodeTemplateBlock_destructorcomment_label; + } + return data.getTemplate().getName(); + } + } + + private static final Key PREF_GENERATE_COMMENTS= getCDTUIKey(PreferenceConstants.CODEGEN_ADD_COMMENTS); + + private static Key[] getAllKeys() { + return new Key[] { + PREF_GENERATE_COMMENTS + }; + } + + private final static int IDX_ADD= 0; + private final static int IDX_EDIT= 1; + private final static int IDX_REMOVE= 2; + private final static int IDX_IMPORT= 3; + private final static int IDX_EXPORT= 4; + private final static int IDX_EXPORTALL= 5; + + protected final static Object COMMENT_NODE= PreferencesMessages.CodeTemplateBlock_templates_comment_node; + protected final static Object CODE_NODE= PreferencesMessages.CodeTemplateBlock_templates_code_node; + protected final static Object FILE_NODE= PreferencesMessages.CodeTemplateBlock_templates_file_node; + + private TreeListDialogField fCodeTemplateTree; + private SelectionButtonDialogField fGenerateComments; + + protected ProjectTemplateStore fTemplateStore; + + private PixelConverter fPixelConverter; + private SourceViewer fPatternViewer; + + private TemplateVariableProcessor fTemplateProcessor; + private ContextTypeRegistry fFileTemplateContextTypes; + + public CodeTemplateBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) { + super(context, project, getAllKeys(), container); + + fTemplateStore= new ProjectTemplateStore(project); + try { + fTemplateStore.load(); + } catch (IOException e) { + CUIPlugin.getDefault().log(e); + } + + fTemplateProcessor= new TemplateVariableProcessor(); + + CodeTemplateAdapter adapter= new CodeTemplateAdapter(); + + String[] buttonLabels= new String[] { + PreferencesMessages.CodeTemplateBlock_templates_new_button, + PreferencesMessages.CodeTemplateBlock_templates_edit_button, + PreferencesMessages.CodeTemplateBlock_templates_remove_button, + PreferencesMessages.CodeTemplateBlock_templates_import_button, + PreferencesMessages.CodeTemplateBlock_templates_export_button, + PreferencesMessages.CodeTemplateBlock_templates_exportall_button + + }; + fCodeTemplateTree= new TreeListDialogField(adapter, buttonLabels, new CodeTemplateLabelProvider()); + fCodeTemplateTree.setDialogFieldListener(adapter); + fCodeTemplateTree.setLabelText(PreferencesMessages.CodeTemplateBlock_templates_label); + fCodeTemplateTree.setViewerComparator(adapter); + + fCodeTemplateTree.enableButton(IDX_EXPORT, false); + fCodeTemplateTree.enableButton(IDX_ADD, false); + fCodeTemplateTree.enableButton(IDX_EDIT, false); + fCodeTemplateTree.enableButton(IDX_REMOVE, false); + + fCodeTemplateTree.addElement(COMMENT_NODE); + fCodeTemplateTree.addElement(CODE_NODE); + fCodeTemplateTree.addElement(FILE_NODE); + + fCodeTemplateTree.selectFirstElement(); + + fGenerateComments= new SelectionButtonDialogField(SWT.CHECK | SWT.WRAP); + fGenerateComments.setDialogFieldListener(adapter); + fGenerateComments.setLabelText(PreferencesMessages.CodeTemplateBlock_createcomment_label); + + updateControls(); + } + + public void postSetSelection(Object element) { + fCodeTemplateTree.postSetSelection(new StructuredSelection(element)); + } + + public boolean hasProjectSpecificOptions(IProject project) { + if (super.hasProjectSpecificOptions(project)) + return true; + + if (project != null) { + return ProjectTemplateStore.hasProjectSpecificTempates(project); + } + return false; + } + + protected Control createContents(Composite parent) { + fPixelConverter= new PixelConverter(parent); + + setShell(parent.getShell()); + + Composite composite= new Composite(parent, SWT.NONE); + composite.setFont(parent.getFont()); + + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.numColumns= 2; + composite.setLayout(layout); + + fCodeTemplateTree.doFillIntoGrid(composite, 3); + LayoutUtil.setHorizontalSpan(fCodeTemplateTree.getLabelControl(null), 2); + LayoutUtil.setHorizontalGrabbing(fCodeTemplateTree.getTreeControl(null)); + + fPatternViewer= createViewer(composite, 2); + + fGenerateComments.doFillIntoGrid(composite, 2); + + return composite; + } + + /* + * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls() + */ + protected void updateControls() { + fGenerateComments.setSelection(getBooleanValue(PREF_GENERATE_COMMENTS)); + } + + private SourceViewer createViewer(Composite parent, int nColumns) { + Label label= new Label(parent, SWT.NONE); + label.setText(PreferencesMessages.CodeTemplateBlock_preview); + GridData data= new GridData(); + data.horizontalSpan= nColumns; + label.setLayoutData(data); + + IDocument document= new Document(); + CTextTools tools= CUIPlugin.getDefault().getTextTools(); + tools.setupCDocumentPartitioner(document, ICPartitions.C_PARTITIONING); + IPreferenceStore store= CUIPlugin.getDefault().getCombinedPreferenceStore(); + SourceViewer viewer= new CSourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store); + CodeTemplateSourceViewerConfiguration configuration= new CodeTemplateSourceViewerConfiguration(tools.getColorManager(), store, null, fTemplateProcessor); + viewer.configure(configuration); + viewer.setEditable(false); + viewer.setDocument(document); + + Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT); + viewer.getTextWidget().setFont(font); + new CSourcePreviewerUpdater(viewer, configuration, store); + + Control control= viewer.getControl(); + data= new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL); + data.horizontalSpan= nColumns; + data.heightHint= fPixelConverter.convertHeightInCharsToPixels(5); + control.setLayoutData(data); + + return viewer; + } + + private void reconfigurePatternViewer() { + if (fPatternViewer == null) + return; + CTextTools tools= CUIPlugin.getDefault().getTextTools(); + IPreferenceStore store= CUIPlugin.getDefault().getCombinedPreferenceStore(); + CodeTemplateSourceViewerConfiguration configuration= new CodeTemplateSourceViewerConfiguration(tools.getColorManager(), store, null, fTemplateProcessor); + fPatternViewer.unconfigure(); + fPatternViewer.configure(configuration); + fPatternViewer.invalidateTextPresentation(); + } + + protected TemplatePersistenceData[] getCodeTemplatesOfCategory(boolean isComment) { + ArrayList res= new ArrayList(); + TemplatePersistenceData[] templates= fTemplateStore.getTemplateData(); + for (int i= 0; i < templates.length; i++) { + TemplatePersistenceData curr= templates[i]; + boolean isUserAdded= curr.getId() == null; + boolean isFileTemplate= FileTemplateContextType.isFileTemplateContextType(curr.getTemplate().getContextTypeId()); + if (!isUserAdded && !isFileTemplate && isComment == curr.getTemplate().getName().endsWith(CodeTemplateContextType.COMMENT_SUFFIX)) { + res.add(curr); + } + } + return (TemplatePersistenceData[]) res.toArray(new TemplatePersistenceData[res.size()]); + } + + private TemplatePersistenceData[] getTemplatesOfContextType(TemplateContextType contextType) { + return getTemplatesOfContextType(contextType.getId()); + } + + protected TemplatePersistenceData[] getTemplatesOfContextType(String contextTypeId) { + ArrayList res= new ArrayList(); + TemplatePersistenceData[] templates= fTemplateStore.getTemplateData(); + for (int i= 0; i < templates.length; i++) { + TemplatePersistenceData curr= templates[i]; + if (contextTypeId.equals(curr.getTemplate().getContextTypeId())) { + res.add(curr); + } + } + return (TemplatePersistenceData[]) res.toArray(new TemplatePersistenceData[res.size()]); + } + + protected ContextTypeRegistry getFileTemplateContextRegistry() { + if (fFileTemplateContextTypes == null) { + fFileTemplateContextTypes= new ContextTypeRegistry(); + Iterator contextTypesIter= CUIPlugin.getDefault().getCodeTemplateContextRegistry().contextTypes(); + while(contextTypesIter.hasNext()) { + TemplateContextType contextType= (TemplateContextType)contextTypesIter.next(); + final String contextTypeId= contextType.getId(); + // add if at least one template registered + if (FileTemplateContextType.isFileTemplateContextType(contextTypeId)) { + fFileTemplateContextTypes.addContextType(contextType); + } + } + } + return fFileTemplateContextTypes; + } + + protected TemplateContextType[] getFileTemplateContextTypes() { + Iterator iter= getFileTemplateContextRegistry().contextTypes(); + ArrayList result= new ArrayList(); + while (iter.hasNext()) { + TemplateContextType contextType= (TemplateContextType)iter.next(); + if (getTemplatesOfContextType(contextType).length > 0) { + result.add(contextType); + } + } + return (TemplateContextType[]) result.toArray(new TemplateContextType[0]); + } + + protected static boolean canAdd(List selected) { + if (selected.size() == 1) { + Object element= selected.get(0); + if (element instanceof TemplateContextType || element == FILE_NODE) { + return true; + } + if (element instanceof TemplatePersistenceData) { + TemplatePersistenceData data = (TemplatePersistenceData) element; + if (FileTemplateContextType.isFileTemplateContextType(data.getTemplate().getContextTypeId())) { + return true; + } + } + } + return false; + } + + protected static boolean canEdit(List selected) { + return selected.size() == 1 && (selected.get(0) instanceof TemplatePersistenceData); + } + + protected static boolean canRemove(List selected) { + if (selected.size() == 1 && (selected.get(0) instanceof TemplatePersistenceData)) { + TemplatePersistenceData data= (TemplatePersistenceData)selected.get(0); + return data.isUserAdded(); + } + return false; + } + + protected void updateSourceViewerInput(List selection) { + if (fPatternViewer == null || fPatternViewer.getTextWidget().isDisposed()) { + return; + } + if (selection.size() == 1 && selection.get(0) instanceof TemplatePersistenceData) { + TemplatePersistenceData data= (TemplatePersistenceData) selection.get(0); + Template template= data.getTemplate(); + TemplateContextType type= CUIPlugin.getDefault().getCodeTemplateContextRegistry().getContextType(template.getContextTypeId()); + fTemplateProcessor.setContextType(type); + reconfigurePatternViewer(); + fPatternViewer.getDocument().set(template.getPattern()); + } else { + fPatternViewer.getDocument().set(""); //$NON-NLS-1$ + } + } + + protected void doButtonPressed(int buttonIndex, List selected) { + switch (buttonIndex) { + case IDX_EDIT: + edit((TemplatePersistenceData) selected.get(0), false); + break; + case IDX_ADD: { + Object element= selected.get(0); + Template orig= null; + String contextTypeId; + if (element instanceof TemplatePersistenceData) { + orig= ((TemplatePersistenceData)element).getTemplate(); + contextTypeId= orig.getContextTypeId(); + } else if (element instanceof TemplateContextType) { + TemplateContextType type= (TemplateContextType)selected.get(0); + contextTypeId= type.getId(); + } else { + // default: text file + contextTypeId= FileTemplateContextType.TEXTFILE_CONTEXTTYPE; + } + Template newTemplate; + if (orig != null) { + newTemplate= new Template("", "", contextTypeId, orig.getPattern(), false); //$NON-NLS-1$//$NON-NLS-2$ + } else { + newTemplate= new Template("", "", contextTypeId, "", false); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + } + TemplatePersistenceData newData= new TemplatePersistenceData(newTemplate, true); + edit(newData, true); + break; + } + case IDX_REMOVE: + remove((TemplatePersistenceData) selected.get(0)); + break; + case IDX_EXPORT: + export(selected); + break; + case IDX_EXPORTALL: + exportAll(); + break; + case IDX_IMPORT: + import_(); + break; + } + } + + private void remove(TemplatePersistenceData data) { + if (data.isUserAdded()) { + fTemplateStore.delete(data); + fCodeTemplateTree.refresh(); + } + } + + private void edit(TemplatePersistenceData data, boolean isNew) { + Template newTemplate= new Template(data.getTemplate()); + boolean isFileTemplate= FileTemplateContextType.isFileTemplateContextType(newTemplate.getContextTypeId()); + ContextTypeRegistry contextTypeRegistry; + if (isFileTemplate) { + contextTypeRegistry= getFileTemplateContextRegistry(); + } else { + contextTypeRegistry= CUIPlugin.getDefault().getCodeTemplateContextRegistry(); + } + EditTemplateDialog dialog= new EditTemplateDialog(getShell(), newTemplate, !isNew, data.isUserAdded(), isFileTemplate, contextTypeRegistry); + if (dialog.open() == Window.OK) { + // changed + data.setTemplate(dialog.getTemplate()); + if (isNew) { + // add to store + fTemplateStore.addTemplateData(data); + } + if (isNew || isFileTemplate) { + fCodeTemplateTree.refresh(); + } else { + fCodeTemplateTree.refresh(data); + } + fCodeTemplateTree.selectElements(new StructuredSelection(data)); + } + } + + private void import_() { + FileDialog dialog= new FileDialog(getShell()); + dialog.setText(PreferencesMessages.CodeTemplateBlock_import_title); + dialog.setFilterExtensions(new String[] {PreferencesMessages.CodeTemplateBlock_import_extension}); + String path= dialog.open(); + + if (path == null) + return; + + try { + TemplateReaderWriter reader= new TemplateReaderWriter(); + File file= new File(path); + if (file.exists()) { + InputStream input= new BufferedInputStream(new FileInputStream(file)); + try { + TemplatePersistenceData[] datas= reader.read(input, null); + for (int i= 0; i < datas.length; i++) { + updateTemplate(datas[i]); + } + } finally { + try { + input.close(); + } catch (IOException x) { + } + } + } + + fCodeTemplateTree.refresh(); + updateSourceViewerInput(fCodeTemplateTree.getSelectedElements()); + + } catch (FileNotFoundException e) { + openReadErrorDialog(e); + } catch (IOException e) { + openReadErrorDialog(e); + } + + } + + private void updateTemplate(TemplatePersistenceData data) { + String dataId= data.getId(); + TemplatePersistenceData[] datas= fTemplateStore.getTemplateData(); + if (dataId != null) { + // predefined + for (int i= 0; i < datas.length; i++) { + String id= datas[i].getId(); + if (id != null && id.equals(dataId)) { + datas[i].setTemplate(data.getTemplate()); + return; + } + } + } else { + // user added + String dataName= data.getTemplate().getName(); + for (int i= 0; i < datas.length; i++) { + if (datas[i].getId() == null) { + String name= datas[i].getTemplate().getName(); + String contextTypeId= datas[i].getTemplate().getContextTypeId(); + if (name != null && name.equals(dataName) && contextTypeId.equals(data.getTemplate().getContextTypeId())) { + datas[i].setTemplate(data.getTemplate()); + return; + } + } + } + // new + fTemplateStore.addTemplateData(data); + } + } + + private void exportAll() { + export(fTemplateStore.getTemplateData()); + } + + private void export(List selected) { + Set datas= new HashSet(); + for (int i= 0; i < selected.size(); i++) { + Object curr= selected.get(i); + if (curr instanceof TemplatePersistenceData) { + datas.add(curr); + } else if (curr instanceof TemplateContextType) { + TemplatePersistenceData[] cat= getTemplatesOfContextType((TemplateContextType)curr); + datas.addAll(Arrays.asList(cat)); + } else if (curr == FILE_NODE) { + TemplateContextType[] types= getFileTemplateContextTypes(); + for (int j = 0; j < types.length; j++) { + TemplateContextType contextType = types[j]; + TemplatePersistenceData[] cat= getTemplatesOfContextType(contextType); + datas.addAll(Arrays.asList(cat)); + } + } else if (curr == COMMENT_NODE || curr == CODE_NODE) { + TemplatePersistenceData[] cat= getCodeTemplatesOfCategory(curr == COMMENT_NODE); + datas.addAll(Arrays.asList(cat)); + } + } + export((TemplatePersistenceData[]) datas.toArray(new TemplatePersistenceData[datas.size()])); + } + + private void export(TemplatePersistenceData[] templates) { + FileDialog dialog= new FileDialog(getShell(), SWT.SAVE); + dialog.setText(Messages.format(PreferencesMessages.CodeTemplateBlock_export_title, String.valueOf(templates.length))); + dialog.setFilterExtensions(new String[] {PreferencesMessages.CodeTemplateBlock_export_extension}); + dialog.setFileName(PreferencesMessages.CodeTemplateBlock_export_filename); + String path= dialog.open(); + + if (path == null) + return; + + File file= new File(path); + + if (file.isHidden()) { + String title= PreferencesMessages.CodeTemplateBlock_export_error_title; + String message= Messages.format(PreferencesMessages.CodeTemplateBlock_export_error_hidden, file.getAbsolutePath()); + MessageDialog.openError(getShell(), title, message); + return; + } + + if (file.exists() && !file.canWrite()) { + String title= PreferencesMessages.CodeTemplateBlock_export_error_title; + String message= Messages.format(PreferencesMessages.CodeTemplateBlock_export_error_canNotWrite, file.getAbsolutePath()); + MessageDialog.openError(getShell(), title, message); + return; + } + + if (!file.exists() || confirmOverwrite(file)) { + OutputStream output= null; + try { + output= new BufferedOutputStream(new FileOutputStream(file)); + TemplateReaderWriter writer= new TemplateReaderWriter(); + writer.save(templates, output); + output.close(); + } catch (IOException e) { + if (output != null) { + try { + output.close(); + } catch (IOException e2) { + // ignore + } + } + openWriteErrorDialog(); + } + } + + } + + private boolean confirmOverwrite(File file) { + return MessageDialog.openQuestion(getShell(), + PreferencesMessages.CodeTemplateBlock_export_exists_title, + Messages.format(PreferencesMessages.CodeTemplateBlock_export_exists_message, file.getAbsolutePath())); + } + + public void performDefaults() { + super.performDefaults(); + fTemplateStore.restoreDefaults(); + + // refresh + fCodeTemplateTree.refresh(); + updateSourceViewerInput(fCodeTemplateTree.getSelectedElements()); + } + + public boolean performOk(boolean enabled) { + boolean res= super.performOk(); + if (!res) + return false; + + if (fProject != null) { + TemplatePersistenceData[] templateData= fTemplateStore.getTemplateData(); + for (int i= 0; i < templateData.length; i++) { + fTemplateStore.setProjectSpecific(templateData[i].getId(), enabled); + } + } + try { + fTemplateStore.save(); + } catch (IOException e) { + CUIPlugin.getDefault().log(e); + openWriteErrorDialog(); + } + return true; + } + + public void performCancel() { + try { + fTemplateStore.revertChanges(); + } catch (IOException e) { + openReadErrorDialog(e); + } + } + + private void openReadErrorDialog(Exception e) { + String title= PreferencesMessages.CodeTemplateBlock_error_read_title; + + String message= e.getLocalizedMessage(); + if (message != null) + message= Messages.format(PreferencesMessages.CodeTemplateBlock_error_parse_message, message); + else + message= PreferencesMessages.CodeTemplateBlock_error_read_message; + MessageDialog.openError(getShell(), title, message); + } + + private void openWriteErrorDialog() { + String title= PreferencesMessages.CodeTemplateBlock_error_write_title; + String message= PreferencesMessages.CodeTemplateBlock_error_write_message; + MessageDialog.openError(getShell(), title, message); + } + + /* + * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(java.lang.String, java.lang.String) + */ + protected void validateSettings(Key changedKey, String oldValue, String newValue) { + // no validation here + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplatePreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplatePreferencePage.java new file mode 100644 index 00000000000..514473e1926 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplatePreferencePage.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; + +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.dialogs.StatusUtil; + +/* + * The page to configure the code templates. + */ +public class CodeTemplatePreferencePage extends PropertyAndPreferencePage { + + public static final String PREF_ID= "org.eclipse.cdt.ui.preferences.CodeTemplatePreferencePage"; //$NON-NLS-1$ + public static final String PROP_ID= "org.eclipse.cdt.ui.propertyPages.CodeTemplatePreferencePage"; //$NON-NLS-1$ + + public static final String DATA_SELECT_TEMPLATE= "CodeTemplatePreferencePage.select_template"; //$NON-NLS-1$ + + private CodeTemplateBlock fCodeTemplateConfigurationBlock; + + public CodeTemplatePreferencePage() { + setPreferenceStore(CUIPlugin.getDefault().getPreferenceStore()); + + // only used when page is shown programatically + setTitle(PreferencesMessages.CodeTemplatesPreferencePage_title); + } + + /* + * @see PreferencePage#createControl(Composite) + */ + public void createControl(Composite parent) { + IWorkbenchPreferenceContainer container= (IWorkbenchPreferenceContainer) getContainer(); + fCodeTemplateConfigurationBlock= new CodeTemplateBlock(getNewStatusChangedListener(), getProject(), container); + + super.createControl(parent); + PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ICHelpContextIds.CODE_TEMPLATES_PREFERENCE_PAGE); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#createPreferenceContent(org.eclipse.swt.widgets.Composite) + */ + protected Control createPreferenceContent(Composite composite) { + return fCodeTemplateConfigurationBlock.createContents(composite); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#enableProjectSpecificSettings(boolean) + */ + protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { + super.enableProjectSpecificSettings(useProjectSpecificSettings); + if (fCodeTemplateConfigurationBlock != null) { + fCodeTemplateConfigurationBlock.useProjectSpecificSettings(useProjectSpecificSettings); + } + } + + /* + * @see IPreferencePage#performOk() + */ + public boolean performOk() { + if (fCodeTemplateConfigurationBlock != null) { + return fCodeTemplateConfigurationBlock.performOk(useProjectSettings()); + } + return true; + } + + /* + * @see PreferencePage#performDefaults() + */ + protected void performDefaults() { + super.performDefaults(); + if (fCodeTemplateConfigurationBlock != null) { + fCodeTemplateConfigurationBlock.performDefaults(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.DialogPage#dispose() + */ + public void dispose() { + if (fCodeTemplateConfigurationBlock != null) { + fCodeTemplateConfigurationBlock.dispose(); + } + super.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus) + */ + public void statusChanged(IStatus status) { + setValid(!status.matches(IStatus.ERROR)); + StatusUtil.applyToStatusLine(this, status); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.IPreferencePage#performCancel() + */ + public boolean performCancel() { + if (fCodeTemplateConfigurationBlock != null) { + fCodeTemplateConfigurationBlock.performCancel(); + } + return super.performCancel(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#hasProjectSpecificOptions(org.eclipse.core.resources.IProject) + */ + protected boolean hasProjectSpecificOptions(IProject project) { + return fCodeTemplateConfigurationBlock.hasProjectSpecificOptions(project); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#getPreferencePageID() + */ + protected String getPreferencePageID() { + return PREF_ID; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#getPropertyPageID() + */ + protected String getPropertyPageID() { + return null; + // TODO project specific settings +// return PROP_ID; + } + + /* + * @see org.eclipse.jface.preference.PreferencePage#applyData(java.lang.Object) + */ + public void applyData(Object data) { + if (data instanceof Map) { + Object id= ((Map) data).get(DATA_SELECT_TEMPLATE); + if (id instanceof String) { + final TemplatePersistenceData[] templates= fCodeTemplateConfigurationBlock.fTemplateStore.getTemplateData(); + TemplatePersistenceData template= null; + for (int index= 0; index < templates.length; index++) { + template= templates[index]; + if (id.equals(template.getId()) || id.equals(template.getTemplate().getName())) { + fCodeTemplateConfigurationBlock.postSetSelection(template); + break; + } + } + } + } + super.applyData(data); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateSourceViewerConfiguration.java new file mode 100644 index 00000000000..b8ebe851a5b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateSourceViewerConfiguration.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.util.Iterator; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultInformationControl; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlCreator; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.jface.text.templates.TemplateVariableResolver; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.texteditor.ITextEditor; + +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.corext.template.c.CodeTemplateContextType; + +import org.eclipse.cdt.internal.ui.text.CWordFinder; +import org.eclipse.cdt.internal.ui.text.HTMLTextPresenter; +import org.eclipse.cdt.internal.ui.text.IColorManager; +import org.eclipse.cdt.internal.ui.text.SimpleCSourceViewerConfiguration; +import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference; +import org.eclipse.cdt.internal.ui.text.template.TemplateVariableProcessor; + + +public class CodeTemplateSourceViewerConfiguration extends SimpleCSourceViewerConfiguration { + + private static class TemplateVariableTextHover implements ITextHover { + + private TemplateVariableProcessor fProcessor; + + /** + * @param processor the template variable processor + */ + public TemplateVariableTextHover(TemplateVariableProcessor processor) { + fProcessor= processor; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion) + */ + public String getHoverInfo(ITextViewer textViewer, IRegion subject) { + try { + IDocument doc= textViewer.getDocument(); + int offset= subject.getOffset(); + if (offset >= 2 && "${".equals(doc.get(offset-2, 2))) { //$NON-NLS-1$ + String varName= doc.get(offset, subject.getLength()); + TemplateContextType contextType= fProcessor.getContextType(); + if (contextType != null) { + Iterator iter= contextType.resolvers(); + while (iter.hasNext()) { + TemplateVariableResolver var= (TemplateVariableResolver) iter.next(); + if (varName.equals(var.getType())) { + return var.getDescription(); + } + } + } + } + } catch (BadLocationException e) { + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int) + */ + public IRegion getHoverRegion(ITextViewer textViewer, int offset) { + if (textViewer != null) { + return CWordFinder.findWord(textViewer.getDocument(), offset); + } + return null; + } + + } + + private final TemplateVariableProcessor fProcessor; + + public CodeTemplateSourceViewerConfiguration(IColorManager colorManager, IPreferenceStore store, ITextEditor editor, TemplateVariableProcessor processor) { + super(colorManager, store, editor, ICPartitions.C_PARTITIONING, false); + fProcessor= processor; + } + + /* + * @see SourceViewerConfiguration#getContentAssistant(ISourceViewer) + */ + public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { + + IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); + + + ContentAssistant assistant= new ContentAssistant(); + assistant.setContentAssistProcessor(fProcessor, IDocument.DEFAULT_CONTENT_TYPE); + // Register the same processor for strings and single line comments to get code completion at the start of those partitions. + assistant.setContentAssistProcessor(fProcessor, ICPartitions.C_STRING); + assistant.setContentAssistProcessor(fProcessor, ICPartitions.C_CHARACTER); + assistant.setContentAssistProcessor(fProcessor, ICPartitions.C_SINGLE_LINE_COMMENT); + assistant.setContentAssistProcessor(fProcessor, ICPartitions.C_MULTI_LINE_COMMENT); + assistant.setContentAssistProcessor(fProcessor, ICPartitions.C_PREPROCESSOR); + + ContentAssistPreference.configure(assistant, store); + + assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY); + assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE); + assistant.setInformationControlCreator(new IInformationControlCreator() { + public IInformationControl createInformationControl(Shell parent) { + return new DefaultInformationControl(parent, SWT.NONE, new HTMLTextPresenter(true)); + } + }); + + return assistant; + } + + /* + * @see SourceViewerConfiguration#getTextHover(ISourceViewer, String, int) + */ + public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType, int stateMask) { + return new TemplateVariableTextHover(fProcessor); + } + + /* + * @see org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration#getPresentationReconciler(org.eclipse.jface.text.source.ISourceViewer) + */ + public IPresentationReconciler getPresentationReconciler( ISourceViewer sourceViewer) { + if (fProcessor.getContextType() instanceof CodeTemplateContextType) { + return super.getPresentationReconciler(sourceViewer); + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/EditTemplateDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/EditTemplateDialog.java new file mode 100644 index 00000000000..55d2b1b5bf8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/EditTemplateDialog.java @@ -0,0 +1,648 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.expressions.Expression; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.GroupMarker; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.commands.ActionHandler; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.JFaceResources; +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.ITextListener; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.templates.ContextTypeRegistry; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.jface.text.templates.TemplateException; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; +import org.eclipse.ui.ActiveShellExpression; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; +import org.eclipse.ui.texteditor.IUpdate; +import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; + +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.IContextMenuConstants; +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.editor.CSourceViewer; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.text.template.TemplateVariableProcessor; + +/** + * Dialog to edit a template. + */ +class EditTemplateDialog extends StatusDialog { + + private static class TextViewerAction extends Action implements IUpdate { + + private int fOperationCode= -1; + private ITextOperationTarget fOperationTarget; + + /** + * Creates a new action. + * + * @param viewer the viewer + * @param operationCode the opcode + */ + public TextViewerAction(ITextViewer viewer, int operationCode) { + fOperationCode= operationCode; + fOperationTarget= viewer.getTextOperationTarget(); + update(); + } + + /** + * Updates the enabled state of the action. + * Fires a property change if the enabled state changes. + * + * @see Action#firePropertyChange(String, Object, Object) + */ + public void update() { + // XXX: workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=206111 + if (fOperationCode == ITextOperationTarget.REDO) + return; + + boolean wasEnabled= isEnabled(); + boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode)); + setEnabled(isEnabled); + + if (wasEnabled != isEnabled) { + firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE); + } + } + + /** + * @see Action#run() + */ + public void run() { + if (fOperationCode != -1 && fOperationTarget != null) { + fOperationTarget.doOperation(fOperationCode); + } + } + } + + private Template fTemplate; + + private Text fNameText; + private Text fDescriptionText; + private Combo fContextCombo; + private SourceViewer fPatternEditor; + private Button fInsertVariableButton; + private Button fAutoInsertCheckbox; + private boolean fIsNameModifiable; + private boolean fIsContextTypeModifiable; + + private StatusInfo fValidationStatus; + private boolean fSuppressError= true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=4354 + private Map fGlobalActions= new HashMap(10); + private List fSelectionActions = new ArrayList(3); + private String[][] fContextTypes; + + private ContextTypeRegistry fContextTypeRegistry; + + private final TemplateVariableProcessor fTemplateProcessor= new TemplateVariableProcessor(); + + /** + * Creates a new dialog. + * + * @param parent the shell parent of the dialog + * @param template the template to edit + * @param edit whether this is a new template or an existing being edited + * @param isNameModifiable whether the name of the template may be modified + * @param isContextTypeModifiable whether the context type of the template may be modified + * @param registry the context type registry to use + */ + public EditTemplateDialog(Shell parent, Template template, boolean edit, boolean isNameModifiable, boolean isContextTypeModifiable, ContextTypeRegistry registry) { + super(parent); + + String title= edit + ? PreferencesMessages.EditTemplateDialog_title_edit + : PreferencesMessages.EditTemplateDialog_title_new; + setTitle(title); + + fTemplate= template; + fIsNameModifiable= isNameModifiable; + fIsContextTypeModifiable= isContextTypeModifiable; + +// String delim= new Document().getLegalLineDelimiters()[0]; + + List contexts= new ArrayList(); + for (Iterator it= registry.contextTypes(); it.hasNext();) { + TemplateContextType type= (TemplateContextType) it.next(); + // TODO cppdoc? doxygen? +// if (type.getId().equals("javadoc")) //$NON-NLS-1$ +// contexts.add(new String[] { type.getId(), type.getName(), "/**" + delim }); //$NON-NLS-1$ +// else + contexts.add(0, new String[] { type.getId(), type.getName(), "" }); //$NON-NLS-1$ + } + Collections.sort(contexts, new Comparator() { + public int compare(Object o1, Object o2) { + String[] lhs= (String[]) o1; + String[] rhs= (String[]) o2; + return lhs[1].compareTo(rhs[1]); + }}); + fContextTypes= (String[][]) contexts.toArray(new String[contexts.size()][]); + + fValidationStatus= new StatusInfo(); + + fContextTypeRegistry= registry; + + TemplateContextType type= fContextTypeRegistry.getContextType(template.getContextTypeId()); + fTemplateProcessor.setContextType(type); + } + + /* + * @see org.eclipse.jface.dialogs.Dialog#isResizable() + */ + protected boolean isResizable() { + return true; + } + + /* + * @see org.eclipse.cdt.internal.ui.dialogs.StatusDialog#create() + */ + public void create() { + super.create(); + updateStatusAndButtons(); + getButton(IDialogConstants.OK_ID).setEnabled(getStatus().isOK()); + } + + /* + * @see Dialog#createDialogArea(Composite) + */ + protected Control createDialogArea(Composite ancestor) { + Composite parent= new Composite(ancestor, SWT.NONE); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + parent.setLayout(layout); + parent.setLayoutData(new GridData(GridData.FILL_BOTH)); + + ModifyListener listener= new ModifyListener() { + public void modifyText(ModifyEvent e) { + doTextWidgetChanged(e.widget); + } + }; + + if (fIsNameModifiable) { + createLabel(parent, PreferencesMessages.EditTemplateDialog_name); + + Composite composite= new Composite(parent, SWT.NONE); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + layout= new GridLayout(); + layout.numColumns= fIsContextTypeModifiable ? 3 : 1; + layout.marginWidth= 0; + layout.marginHeight= 0; + composite.setLayout(layout); + + fNameText= createText(composite); + fNameText.addFocusListener(new FocusListener() { + + public void focusGained(FocusEvent e) { + } + + public void focusLost(FocusEvent e) { + if (fSuppressError) { + fSuppressError= false; + updateStatusAndButtons(); + } + } + }); + + if (fIsContextTypeModifiable) { + createLabel(composite, PreferencesMessages.EditTemplateDialog_contextType); + fContextCombo= new Combo(composite, SWT.READ_ONLY); + fContextCombo.setVisibleItemCount(10); + for (int i= 0; i < fContextTypes.length; i++) { + fContextCombo.add(fContextTypes[i][1]); + } + + fContextCombo.addModifyListener(listener); + +// fAutoInsertCheckbox= createCheckbox(composite, PreferencesMessages.EditTemplateDialog_autoinsert); +// fAutoInsertCheckbox.setSelection(fTemplate.isAutoInsertable()); + } + } + + createLabel(parent, PreferencesMessages.EditTemplateDialog_description); + + int descFlags= fIsNameModifiable ? SWT.BORDER : SWT.BORDER | SWT.READ_ONLY; + fDescriptionText= new Text(parent, descFlags ); + fDescriptionText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + fDescriptionText.addModifyListener(listener); + + Label patternLabel= createLabel(parent, PreferencesMessages.EditTemplateDialog_pattern); + patternLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); + fPatternEditor= createEditor(parent); + + Label filler= new Label(parent, SWT.NONE); + filler.setLayoutData(new GridData()); + + Composite composite= new Composite(parent, SWT.NONE); + layout= new GridLayout(); + layout.marginWidth= 0; + layout.marginHeight= 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData()); + + fInsertVariableButton= new Button(composite, SWT.NONE); + fInsertVariableButton.setLayoutData(getButtonGridData()); + fInsertVariableButton.setText(PreferencesMessages.EditTemplateDialog_insert_variable); + fInsertVariableButton.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + fPatternEditor.getTextWidget().setFocus(); + fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); + } + + public void widgetDefaultSelected(SelectionEvent e) {} + }); + + fDescriptionText.setText(fTemplate.getDescription()); + if (fIsNameModifiable) { + fNameText.setText(fTemplate.getName()); + fNameText.addModifyListener(listener); + if (fContextCombo != null) { + fContextCombo.select(getIndex(fTemplate.getContextTypeId())); + } + } else { + fPatternEditor.getControl().setFocus(); + } + initializeActions(); + + applyDialogFont(parent); + return composite; + } + + protected void doTextWidgetChanged(Widget w) { + if (w == fNameText) { + fSuppressError= false; + updateStatusAndButtons(); + } else if (w == fContextCombo) { + String contextId= getContextId(); + fTemplateProcessor.setContextType(fContextTypeRegistry.getContextType(contextId)); + reconfigurePatternEditor(); + IDocument document= fPatternEditor.getDocument(); + String prefix= getPrefix(); + document.set(prefix + getPattern()); + fPatternEditor.setVisibleRegion(prefix.length(), document.getLength() - prefix.length()); + updateStatusAndButtons(); + } else if (w == fDescriptionText) { + // nothing + } + } + + private String getContextId() { + if (fContextCombo != null && !fContextCombo.isDisposed()) { + String name= fContextCombo.getText(); + for (int i= 0; i < fContextTypes.length; i++) { + if (name.equals(fContextTypes[i][1])) { + return fContextTypes[i][0]; + } + } + } + + return fTemplate.getContextTypeId(); + } + + protected void doSourceChanged(IDocument document) { + String text= document.get(); + fValidationStatus.setOK(); + TemplateContextType contextType= fContextTypeRegistry.getContextType(getContextId()); + if (contextType != null) { + try { + contextType.validate(text); + } catch (TemplateException e) { + fValidationStatus.setError(e.getLocalizedMessage()); + } + } + + updateAction(ITextEditorActionConstants.UNDO); + updateStatusAndButtons(); + } + + private static GridData getButtonGridData() { + GridData data= new GridData(GridData.FILL_HORIZONTAL); + return data; + } + + private static Label createLabel(Composite parent, String name) { + Label label= new Label(parent, SWT.NULL); + label.setText(name); + label.setLayoutData(new GridData()); + + return label; + } + +// private static Button createCheckbox(Composite parent, String name) { +// Button button= new Button(parent, SWT.CHECK); +// button.setText(name); +// button.setLayoutData(new GridData()); +// +// return button; +// } + + private static Text createText(Composite parent) { + Text text= new Text(parent, SWT.BORDER); + text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + return text; + } + + private SourceViewer createEditor(Composite parent) { + String prefix= getPrefix(); + IDocument document= new Document(prefix + fTemplate.getPattern()); + CTextTools tools= CUIPlugin.getDefault().getTextTools(); + tools.setupCDocumentPartitioner(document, ICPartitions.C_PARTITIONING); + IPreferenceStore store= CUIPlugin.getDefault().getCombinedPreferenceStore(); + SourceViewer viewer= new CSourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store); + CodeTemplateSourceViewerConfiguration configuration= new CodeTemplateSourceViewerConfiguration(tools.getColorManager(), store, null, fTemplateProcessor); + viewer.configure(configuration); + viewer.setEditable(true); + viewer.setDocument(document, prefix.length(), document.getLength() - prefix.length()); + + Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT); + viewer.getTextWidget().setFont(font); + new CSourcePreviewerUpdater(viewer, configuration, store); + + int nLines= document.getNumberOfLines(); + if (nLines < 5) { + nLines= 5; + } else if (nLines > 12) { + nLines= 12; + } + + Control control= viewer.getControl(); + GridData data= new GridData(GridData.FILL_BOTH); + data.widthHint= convertWidthInCharsToPixels(80); + data.heightHint= convertHeightInCharsToPixels(nLines); + control.setLayoutData(data); + + viewer.addTextListener(new ITextListener() { + public void textChanged(TextEvent event) { + if (event .getDocumentEvent() != null) + doSourceChanged(event.getDocumentEvent().getDocument()); + } + }); + + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + updateSelectionDependentActions(); + } + }); + + return viewer; + } + + private void reconfigurePatternEditor() { + if (fPatternEditor == null) + return; + CTextTools tools= CUIPlugin.getDefault().getTextTools(); + IPreferenceStore store= CUIPlugin.getDefault().getCombinedPreferenceStore(); + CodeTemplateSourceViewerConfiguration configuration= new CodeTemplateSourceViewerConfiguration(tools.getColorManager(), store, null, fTemplateProcessor); + fPatternEditor.unconfigure(); + fPatternEditor.configure(configuration); + fPatternEditor.invalidateTextPresentation(); + } + + private String getPrefix() { + String id= getContextId(); + int idx= getIndex(id); + if (idx != -1) + return fContextTypes[idx][2]; + else + return ""; //$NON-NLS-1$ + } + + private void initializeActions() { + final ArrayList handlerActivations= new ArrayList(3); + final IHandlerService handlerService= (IHandlerService) PlatformUI.getWorkbench().getAdapter(IHandlerService.class); + getShell().addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + handlerService.deactivateHandlers(handlerActivations); + } + }); + + Expression expression= new ActiveShellExpression(fPatternEditor.getControl().getShell()); + + TextViewerAction action= new TextViewerAction(fPatternEditor, ITextOperationTarget.UNDO); + action.setText(PreferencesMessages.EditTemplateDialog_undo); + fGlobalActions.put(ITextEditorActionConstants.UNDO, action); + handlerActivations.add(handlerService.activateHandler(IWorkbenchActionDefinitionIds.UNDO, new ActionHandler(action), expression)); + + action= new TextViewerAction(fPatternEditor, ITextOperationTarget.REDO); + action.setText(PreferencesMessages.EditTemplateDialog_redo); + fGlobalActions.put(ITextEditorActionConstants.REDO, action); + handlerActivations.add(handlerService.activateHandler(IWorkbenchActionDefinitionIds.REDO, new ActionHandler(action), expression)); + + action= new TextViewerAction(fPatternEditor, ITextOperationTarget.CUT); + action.setText(PreferencesMessages.EditTemplateDialog_cut); + fGlobalActions.put(ITextEditorActionConstants.CUT, action); + + action= new TextViewerAction(fPatternEditor, ITextOperationTarget.COPY); + action.setText(PreferencesMessages.EditTemplateDialog_copy); + fGlobalActions.put(ITextEditorActionConstants.COPY, action); + + action= new TextViewerAction(fPatternEditor, ITextOperationTarget.PASTE); + action.setText(PreferencesMessages.EditTemplateDialog_paste); + fGlobalActions.put(ITextEditorActionConstants.PASTE, action); + + action= new TextViewerAction(fPatternEditor, ITextOperationTarget.SELECT_ALL); + action.setText(PreferencesMessages.EditTemplateDialog_select_all); + fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action); + + action= new TextViewerAction(fPatternEditor, ISourceViewer.CONTENTASSIST_PROPOSALS); + action.setText(PreferencesMessages.EditTemplateDialog_content_assist); + fGlobalActions.put("ContentAssistProposal", action); //$NON-NLS-1$ + handlerActivations.add(handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, new ActionHandler(action), expression)); + + fSelectionActions.add(ITextEditorActionConstants.CUT); + fSelectionActions.add(ITextEditorActionConstants.COPY); + fSelectionActions.add(ITextEditorActionConstants.PASTE); + + // create context menu + MenuManager manager= new MenuManager(null, null); + manager.setRemoveAllWhenShown(true); + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager mgr) { + fillContextMenu(mgr); + } + }); + + StyledText text= fPatternEditor.getTextWidget(); + Menu menu= manager.createContextMenu(text); + text.setMenu(menu); + } + + private void fillContextMenu(IMenuManager menu) { + menu.add(new GroupMarker(ITextEditorActionConstants.GROUP_UNDO)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, (IAction) fGlobalActions.get(ITextEditorActionConstants.REDO)); + + menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.CUT)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.COPY)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.PASTE)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.SELECT_ALL)); + + menu.add(new Separator(IContextMenuConstants.GROUP_GENERATE)); + menu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, (IAction) fGlobalActions.get("ContentAssistProposal")); //$NON-NLS-1$ + } + + + protected void updateSelectionDependentActions() { + Iterator iterator= fSelectionActions.iterator(); + while (iterator.hasNext()) + updateAction((String)iterator.next()); + } + + protected void updateAction(String actionId) { + IAction action= (IAction) fGlobalActions.get(actionId); + if (action instanceof IUpdate) + ((IUpdate) action).update(); + } + + private int getIndex(String contextid) { + + if (contextid == null) + return -1; + + for (int i= 0; i < fContextTypes.length; i++) { + if (contextid.equals(fContextTypes[i][0])) { + return i; + } + } + return -1; + } + + protected void okPressed() { + String name= fNameText == null ? fTemplate.getName() : fNameText.getText(); + boolean isAutoInsertable= fAutoInsertCheckbox != null && fAutoInsertCheckbox.getSelection(); + fTemplate= new Template(name, fDescriptionText.getText(), getContextId(), getPattern(), isAutoInsertable); + super.okPressed(); + } + + private void updateStatusAndButtons() { + StatusInfo status= fValidationStatus; + boolean isEmpty= fNameText != null && fNameText.getText().length() == 0; + if (!fSuppressError && isEmpty) { + status= new StatusInfo(); + status.setError(PreferencesMessages.EditTemplateDialog_error_noname); + } else if (fNameText != null && !isValidTemplateName(fNameText.getText())) { + status= new StatusInfo(); + status.setError(PreferencesMessages.EditTemplateDialog_error_invalidName); + } + updateStatus(status); + } + + /** + * Checks whether the given string is a valid + * template name. + * + * @param name the string to test + * @return true if the name is valid + */ + private boolean isValidTemplateName(String name) { + return true; + } + + /* + * @see org.eclipse.jface.window.Window#configureShell(Shell) + */ + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, ICHelpContextIds.EDIT_TEMPLATE_DIALOG); + } + + /** + * Returns the created template. + * + * @return the created template + */ + public Template getTemplate() { + return fTemplate; + } + + private String getPattern() { + IDocument doc= fPatternEditor.getDocument(); + IRegion visible= fPatternEditor.getVisibleRegion(); + try { + return doc.get(visible.getOffset(), doc.getLength() - visible.getOffset()); + } catch (BadLocationException e) { + return ""; //$NON-NLS-1$ + } + } + + /* + * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings() + */ + protected IDialogSettings getDialogBoundsSettings() { + String sectionName= getClass().getName() + "_dialogBounds"; //$NON-NLS-1$ + IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings(); + IDialogSettings section= settings.getSection(sectionName); + if (section == null) + section= settings.addNewSection(sectionName); + return section; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java index 3d319f09738..c59e1c1ae8e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java @@ -295,7 +295,7 @@ public abstract class OptionsConfigurationBlock { } - public final boolean hasProjectSpecificOptions(IProject project) { + public boolean hasProjectSpecificOptions(IProject project) { if (project != null) { IScopeContext projectContext= new ProjectScope(project); Key[] allKeys= fAllKeys; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java index 4fc80f44320..ee7c94c38ef 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java @@ -294,7 +294,72 @@ public final class PreferencesMessages extends NLS { public static String CPluginPreferencePage_structuralParseMode_label; public static String CPluginPreferencePage_note; public static String CPluginPreferencePage_performanceHint; - + + public static String PropertyAndPreferencePage_useworkspacesettings_change; + public static String PropertyAndPreferencePage_showprojectspecificsettings_label; + public static String PropertyAndPreferencePage_useprojectsettings_label; + + public static String ProjectSelectionDialog_title; + public static String ProjectSelectionDialog_desciption; + public static String ProjectSelectionDialog_filter; + + public static String CodeTemplatesPreferencePage_title; + public static String CodeTemplateBlock_link_tooltip; + public static String CodeTemplateBlock_templates_comment_node; + public static String CodeTemplateBlock_templates_code_node; + public static String CodeTemplateBlock_templates_file_node; + public static String CodeTemplateBlock_methodstub_label; + public static String CodeTemplateBlock_constructorstub_label; + public static String CodeTemplateBlock_destructorstub_label; + public static String CodeTemplateBlock_typecomment_label; + public static String CodeTemplateBlock_fieldcomment_label; + public static String CodeTemplateBlock_filecomment_label; + public static String CodeTemplateBlock_methodcomment_label; + public static String CodeTemplateBlock_constructorcomment_label; + public static String CodeTemplateBlock_destructorcomment_label; + public static String CodeTemplateBlock_templates_new_button; + public static String CodeTemplateBlock_templates_edit_button; + public static String CodeTemplateBlock_templates_remove_button; + public static String CodeTemplateBlock_templates_import_button; + public static String CodeTemplateBlock_templates_export_button; + public static String CodeTemplateBlock_templates_exportall_button; + public static String CodeTemplateBlock_createcomment_label; + public static String CodeTemplateBlock_templates_label; + public static String CodeTemplateBlock_preview; + public static String CodeTemplateBlock_import_title; + public static String CodeTemplateBlock_import_extension; + public static String CodeTemplateBlock_export_title; + public static String CodeTemplateBlock_export_filename; + public static String CodeTemplateBlock_export_extension; + public static String CodeTemplateBlock_export_exists_title; + public static String CodeTemplateBlock_export_exists_message; + public static String CodeTemplateBlock_error_read_title; + public static String CodeTemplateBlock_error_read_message; + public static String CodeTemplateBlock_error_parse_message; + public static String CodeTemplateBlock_error_write_title; + public static String CodeTemplateBlock_error_write_message; + public static String CodeTemplateBlock_export_error_title; + public static String CodeTemplateBlock_export_error_hidden; + public static String CodeTemplateBlock_export_error_canNotWrite; + + public static String EditTemplateDialog_error_noname; + public static String EditTemplateDialog_error_invalidName; + public static String EditTemplateDialog_title_new; + public static String EditTemplateDialog_title_edit; + public static String EditTemplateDialog_name; + public static String EditTemplateDialog_description; + public static String EditTemplateDialog_contextType; + public static String EditTemplateDialog_pattern; + public static String EditTemplateDialog_insert_variable; + public static String EditTemplateDialog_undo; + public static String EditTemplateDialog_redo; + public static String EditTemplateDialog_cut; + public static String EditTemplateDialog_copy; + public static String EditTemplateDialog_paste; + public static String EditTemplateDialog_select_all; + public static String EditTemplateDialog_content_assist; + public static String EditTemplateDialog_autoinsert; + static { NLS.initializeMessages(BUNDLE_NAME, PreferencesMessages.class); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties index b83a4eda436..e897a3c87b4 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -334,3 +334,83 @@ CPluginPreferencePage_caption= General settings for C/C++ Development: CPluginPreferencePage_structuralParseMode_label= Follow unindexed header files when producing the outline view CPluginPreferencePage_note= Note: CPluginPreferencePage_performanceHint= Enabling this preference may have negative impact on performance. + +PropertyAndPreferencePage_useworkspacesettings_change=Configure Workspace Settings... +PropertyAndPreferencePage_showprojectspecificsettings_label=Configure Project Specific Settings... +PropertyAndPreferencePage_useprojectsettings_label=Enable pr&oject specific settings + +ProjectSelectionDialog_title=Project Specific Configuration +ProjectSelectionDialog_desciption=&Select the project to configure: +ProjectSelectionDialog_filter=Show only &projects with project specific settings + +# Code Templates +CodeTemplatesPreferencePage_title=Code Templates + +CodeTemplateBlock_templates_comment_node=Comments +CodeTemplateBlock_templates_code_node=Code +CodeTemplateBlock_templates_file_node=Files + +CodeTemplateBlock_methodstub_label=Method body +CodeTemplateBlock_constructorstub_label=Constructor body +CodeTemplateBlock_destructorstub_label=Destructor body +CodeTemplateBlock_typecomment_label=Types +CodeTemplateBlock_fieldcomment_label=Fields +CodeTemplateBlock_filecomment_label=Files +CodeTemplateBlock_methodcomment_label=Methods +CodeTemplateBlock_constructorcomment_label=Constructors +CodeTemplateBlock_destructorcomment_label=Destructors + +CodeTemplateBlock_templates_new_button=&New... +CodeTemplateBlock_templates_edit_button=&Edit... +CodeTemplateBlock_templates_remove_button=&Remove +CodeTemplateBlock_templates_import_button=I&mport... +CodeTemplateBlock_templates_export_button=E&xport... +CodeTemplateBlock_templates_exportall_button=Ex&port All... + +CodeTemplateBlock_link_tooltip=Show code style settings +CodeTemplateBlock_createcomment_label=Automatically add comments &for new methods and classes +CodeTemplateBlock_templates_label=&Configure generated code and comments: +CodeTemplateBlock_preview=Pa&ttern: + +CodeTemplateBlock_import_title=Import Templates +CodeTemplateBlock_import_extension=*.xml + +CodeTemplateBlock_export_title=Export {0} Code Template(s) +CodeTemplateBlock_export_filename=codetemplates.xml +CodeTemplateBlock_export_extension=*.xml + +CodeTemplateBlock_export_exists_title=Export Code Templates +CodeTemplateBlock_export_exists_message={0} already exists.\nDo you want to replace it? + +CodeTemplateBlock_error_read_title= Code Templates +CodeTemplateBlock_error_read_message= Failed to read templates. + +CodeTemplateBlock_error_parse_message= Failed to parse templates:\n{0} + +CodeTemplateBlock_error_write_title=Code Templates +CodeTemplateBlock_error_write_message=Failed to write templates. + +CodeTemplateBlock_export_error_title= Export Templates +CodeTemplateBlock_export_error_hidden= Export failed.\n{0} is a hidden file. +CodeTemplateBlock_export_error_canNotWrite= Export failed.\n{0} cannot be modified. + +# edit template dialog +EditTemplateDialog_error_noname=Template name cannot be empty. +EditTemplateDialog_error_invalidName=Template name contains invalid characters. +EditTemplateDialog_title_new=New Template +EditTemplateDialog_title_edit=Edit Template + +EditTemplateDialog_name=&Name: +EditTemplateDialog_description=&Description: +EditTemplateDialog_contextType=&Type: +EditTemplateDialog_pattern=&Pattern: +EditTemplateDialog_insert_variable=Insert &Variable... + +EditTemplateDialog_undo=&Undo +EditTemplateDialog_redo=&Redo +EditTemplateDialog_cut=Cu&t +EditTemplateDialog_copy=&Copy +EditTemplateDialog_paste=&Paste +EditTemplateDialog_select_all=Select &All +EditTemplateDialog_autoinsert=Auto&matically insert +EditTemplateDialog_content_assist=Insert &Variable... diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ProjectSelectionDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ProjectSelectionDialog.java new file mode 100644 index 00000000000..2b36a951bf4 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ProjectSelectionDialog.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.SelectionStatusDialog; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICModel; +import org.eclipse.cdt.ui.CElementContentProvider; +import org.eclipse.cdt.ui.CElementLabelProvider; +import org.eclipse.cdt.ui.CElementSorter; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; + +public class ProjectSelectionDialog extends SelectionStatusDialog { + + // the visual selection widget group + private TableViewer fTableViewer; + private Set fProjectsWithSpecifics; + + // sizing constants + private final static int SIZING_SELECTION_WIDGET_HEIGHT= 250; + private final static int SIZING_SELECTION_WIDGET_WIDTH= 300; + + private final static String DIALOG_SETTINGS_SHOW_ALL= "ProjectSelectionDialog.show_all"; //$NON-NLS-1$ + + private ViewerFilter fFilter; + + public ProjectSelectionDialog(Shell parentShell, Set projectsWithSpecifics) { + super(parentShell); + setTitle(PreferencesMessages.ProjectSelectionDialog_title); + setMessage(PreferencesMessages.ProjectSelectionDialog_desciption); + fProjectsWithSpecifics= projectsWithSpecifics; + + fFilter= new ViewerFilter() { + public boolean select(Viewer viewer, Object parentElement, Object element) { + return fProjectsWithSpecifics.contains(element); + } + }; + } + + + /* (non-Javadoc) + * Method declared on Dialog. + */ + protected Control createDialogArea(Composite parent) { + // page group + Composite composite= (Composite) super.createDialogArea(parent); + + Font font= parent.getFont(); + composite.setFont(font); + + createMessageArea(composite); + + fTableViewer= new TableViewer(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); + fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + doSelectionChanged(((IStructuredSelection) event.getSelection()).toArray()); + } + }); + fTableViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + okPressed(); + } + }); + GridData data= new GridData(SWT.FILL, SWT.FILL, true, true); + data.heightHint= SIZING_SELECTION_WIDGET_HEIGHT; + data.widthHint= SIZING_SELECTION_WIDGET_WIDTH; + fTableViewer.getTable().setLayoutData(data); + + fTableViewer.setLabelProvider(new CElementLabelProvider()); + fTableViewer.setContentProvider(new CElementContentProvider()); + fTableViewer.setComparator(new CElementSorter()); + fTableViewer.getControl().setFont(font); + + Button checkbox= new Button(composite, SWT.CHECK); + checkbox.setText(PreferencesMessages.ProjectSelectionDialog_filter); + checkbox.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false)); + checkbox.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + updateFilter(((Button) e.widget).getSelection()); + } + public void widgetDefaultSelected(SelectionEvent e) { + updateFilter(((Button) e.widget).getSelection()); + } + }); + IDialogSettings dialogSettings= CUIPlugin.getDefault().getDialogSettings(); + boolean doFilter= !dialogSettings.getBoolean(DIALOG_SETTINGS_SHOW_ALL) && !fProjectsWithSpecifics.isEmpty(); + checkbox.setSelection(doFilter); + updateFilter(doFilter); + + ICModel input= CoreModel.getDefault().getCModel(); + fTableViewer.setInput(input); + + doSelectionChanged(new Object[0]); + Dialog.applyDialogFont(composite); + return composite; + } + + protected void updateFilter(boolean selected) { + if (selected) { + fTableViewer.addFilter(fFilter); + } else { + fTableViewer.removeFilter(fFilter); + } + CUIPlugin.getDefault().getDialogSettings().put(DIALOG_SETTINGS_SHOW_ALL, !selected); + } + + private void doSelectionChanged(Object[] objects) { + if (objects.length != 1) { + updateStatus(new StatusInfo(IStatus.ERROR, "")); //$NON-NLS-1$ + setSelectionResult(null); + } else { + updateStatus(new StatusInfo()); + setSelectionResult(objects); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult() + */ + protected void computeResult() { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PropertyAndPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PropertyAndPreferencePage.java index b42a4caef15..8bdc0fe62aa 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PropertyAndPreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PropertyAndPreferencePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2007 IBM Corporation 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 @@ -8,9 +8,12 @@ * Contributors: * IBM Corporation - initial API and implementation * Sergey Prigogin, Google + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.preferences; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import org.eclipse.core.resources.IProject; @@ -20,20 +23,32 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.dialogs.ControlEnableState; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.IWorkbenchPropertyPage; import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; + import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener; import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; import org.eclipse.cdt.internal.ui.dialogs.StatusUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; /** * Base for project property and preference pages @@ -43,7 +58,7 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement private Control fConfigurationBlockControl; private ControlEnableState fBlockEnableState; private Link fChangeWorkspaceSettings; -// private SelectionButtonDialogField fUseProjectSettings; + private SelectionButtonDialogField fUseProjectSettings; private IStatus fBlockStatus; private Composite fParentComposite; @@ -73,48 +88,47 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement return fData == null || !Boolean.TRUE.equals(fData.get(DATA_NO_LINK)); } -// TODO: Project specific settings are not supported yet. -//protected Label createDescriptionLabel(Composite parent) { -// fParentComposite= parent; -// if (isProjectPreferencePage()) { -// Composite composite= new Composite(parent, SWT.NONE); -// composite.setFont(parent.getFont()); -// GridLayout layout= new GridLayout(); -// layout.marginHeight= 0; -// layout.marginWidth= 0; -// layout.numColumns= 2; -// composite.setLayout(layout); -// composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); -// -// IDialogFieldListener listener= new IDialogFieldListener() { -// public void dialogFieldChanged(DialogField field) { -// enableProjectSpecificSettings(((SelectionButtonDialogField)field).isSelected()); -// } -// }; -// -// fUseProjectSettings= new SelectionButtonDialogField(SWT.CHECK); -// fUseProjectSettings.setDialogFieldListener(listener); -// fUseProjectSettings.setLabelText(PreferencesMessages.PropertyAndPreferencePage_useprojectsettings_label); -// fUseProjectSettings.doFillIntoGrid(composite, 1); -// LayoutUtil.setHorizontalGrabbing(fUseProjectSettings.getSelectionButton(null)); -// -// if (offerLink()) { -// fChangeWorkspaceSettings= createLink(composite, PreferencesMessages.PropertyAndPreferencePage_useworkspacesettings_change); -// fChangeWorkspaceSettings.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); -// } else { -// LayoutUtil.setHorizontalSpan(fUseProjectSettings.getSelectionButton(null), 2); -// } -// -// Label horizontalLine= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); -// horizontalLine.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1)); -// horizontalLine.setFont(composite.getFont()); -// } else if (supportsProjectSpecificOptions() && offerLink()) { -// fChangeWorkspaceSettings= createLink(parent, PreferencesMessages.PropertyAndPreferencePage_showprojectspecificsettings_label); -// fChangeWorkspaceSettings.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false)); -// } -// -// return super.createDescriptionLabel(parent); -// } + protected Label createDescriptionLabel(Composite parent) { + fParentComposite= parent; + if (isProjectPreferencePage()) { + Composite composite= new Composite(parent, SWT.NONE); + composite.setFont(parent.getFont()); + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.numColumns= 2; + composite.setLayout(layout); + composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + IDialogFieldListener listener= new IDialogFieldListener() { + public void dialogFieldChanged(DialogField field) { + enableProjectSpecificSettings(((SelectionButtonDialogField)field).isSelected()); + } + }; + + fUseProjectSettings= new SelectionButtonDialogField(SWT.CHECK); + fUseProjectSettings.setDialogFieldListener(listener); + fUseProjectSettings.setLabelText(PreferencesMessages.PropertyAndPreferencePage_useprojectsettings_label); + fUseProjectSettings.doFillIntoGrid(composite, 1); + LayoutUtil.setHorizontalGrabbing(fUseProjectSettings.getSelectionButton(null)); + + if (offerLink()) { + fChangeWorkspaceSettings= createLink(composite, PreferencesMessages.PropertyAndPreferencePage_useworkspacesettings_change); + fChangeWorkspaceSettings.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); + } else { + LayoutUtil.setHorizontalSpan(fUseProjectSettings.getSelectionButton(null), 2); + } + + Label horizontalLine= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); + horizontalLine.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1)); + horizontalLine.setFont(composite.getFont()); + } else if (supportsProjectSpecificOptions() && offerLink()) { + fChangeWorkspaceSettings= createLink(parent, PreferencesMessages.PropertyAndPreferencePage_showprojectspecificsettings_label); + fChangeWorkspaceSettings.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false)); + } + + return super.createDescriptionLabel(parent); + } /* * @see org.eclipse.jface.preference.IPreferencePage#createContents(Composite) @@ -132,20 +146,33 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement fConfigurationBlockControl= createPreferenceContent(composite); fConfigurationBlockControl.setLayoutData(data); -// TODO: Project specific settings are not supported yet. -// if (isProjectPreferencePage()) { -// boolean useProjectSettings= hasProjectSpecificOptions(getProject()); -// enableProjectSpecificSettings(useProjectSettings); -// } + if (isProjectPreferencePage()) { + boolean useProjectSettings= hasProjectSpecificOptions(getProject()); + enableProjectSpecificSettings(useProjectSettings); + } Dialog.applyDialogFont(composite); return composite; } + private Link createLink(Composite composite, String text) { + Link link= new Link(composite, SWT.NONE); + link.setFont(composite.getFont()); + link.setText("" + text + ""); //$NON-NLS-1$//$NON-NLS-2$ + link.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + doLinkActivated((Link) e.widget); + } + + public void widgetDefaultSelected(SelectionEvent e) { + doLinkActivated((Link) e.widget); + } + }); + return link; + } + protected boolean useProjectSettings() { -// TODO: Project specific settings are not supported yet. -// return isProjectPreferencePage() && fUseProjectSettings != null && fUseProjectSettings.isSelected(); - return false; + return isProjectPreferencePage() && fUseProjectSettings != null && fUseProjectSettings.isSelected(); } protected boolean isProjectPreferencePage() { @@ -156,6 +183,38 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement return fProject; } + /** + * Handle link activation. + * + * @param link the link + */ + final void doLinkActivated(Link link) { + Map data= new HashMap(); + data.put(DATA_NO_LINK, Boolean.TRUE); + + if (isProjectPreferencePage()) { + openWorkspacePreferences(data); + } else { + HashSet projectsWithSpecifics= new HashSet(); + try { + ICProject[] projects= CoreModel.getDefault().getCModel().getCProjects(); + for (int i= 0; i < projects.length; i++) { + ICProject curr= projects[i]; + if (hasProjectSpecificOptions(curr.getProject())) { + projectsWithSpecifics.add(curr); + } + } + } catch (CModelException e) { + // ignore + } + ProjectSelectionDialog dialog= new ProjectSelectionDialog(getShell(), projectsWithSpecifics); + if (dialog.open() == Window.OK) { + ICProject res= (ICProject) dialog.getFirstResult(); + openProjectProperties(res.getProject(), data); + } + } + } + protected final void openWorkspacePreferences(Object data) { String id= getPreferencePageID(); PreferencesUtil.createPreferenceDialogOn(getShell(), id, new String[] { id }, data).open(); @@ -168,24 +227,25 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement } } -// TODO: Project specific settings are not supported yet. -// protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { -// fUseProjectSettings.setSelection(useProjectSpecificSettings); -// enablePreferenceContent(useProjectSpecificSettings); -// updateLinkVisibility(); -// doStatusChanged(); -// } -// -// private void updateLinkVisibility() { -// if (fChangeWorkspaceSettings == null || fChangeWorkspaceSettings.isDisposed()) { -// return; -// } -// -// if (isProjectPreferencePage()) { -// fChangeWorkspaceSettings.setEnabled(!useProjectSettings()); -// } -// } + protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { + fUseProjectSettings.setSelection(useProjectSpecificSettings); + enablePreferenceContent(useProjectSpecificSettings); + updateLinkVisibility(); + doStatusChanged(); + } + + private void updateLinkVisibility() { + if (fChangeWorkspaceSettings == null || fChangeWorkspaceSettings.isDisposed()) { + return; + } + + if (isProjectPreferencePage()) { + fChangeWorkspaceSettings.setEnabled(!useProjectSettings()); + } + } + + protected void setPreferenceContentStatus(IStatus status) { fBlockStatus= status; doStatusChanged(); @@ -201,7 +261,7 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement public void statusChanged(IStatus status) { setPreferenceContentStatus(status); } - }; + }; } protected IStatus getPreferenceContentStatus() { @@ -226,17 +286,16 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement if (fBlockEnableState == null) { fBlockEnableState= ControlEnableState.disable(fConfigurationBlockControl); } - } + } } /* * @see org.eclipse.jface.preference.IPreferencePage#performDefaults() */ protected void performDefaults() { -// TODO: Project specific settings are not supported yet. -// if (useProjectSettings()) { -// enableProjectSpecificSettings(false); -// } + if (useProjectSettings()) { + enableProjectSpecificSettings(false); + } super.performDefaults(); } @@ -284,4 +343,5 @@ public abstract class PropertyAndPreferencePage extends PreferencePage implement protected Map getData() { return fData; } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPreferencePage.java index b72f209c9ed..120d43ed513 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPreferencePage.java @@ -85,19 +85,20 @@ public class TodoTaskPreferencePage extends PropertyAndPreferencePage { * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#getPropertyPageID() */ protected String getPropertyPageID() { - return PROP_ID; + // TODO: Project specific settings are not supported yet. +// return PROP_ID; + return null; } -// TODO: Project specific settings are not supported yet. -// /* (non-Javadoc) -// * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#enableProjectSpecificSettings(boolean) -// */ -// protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { -// super.enableProjectSpecificSettings(useProjectSpecificSettings); -// if (fConfigurationBlock != null) { -// fConfigurationBlock.useProjectSpecificSettings(useProjectSpecificSettings); -// } -// } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.PropertyAndPreferencePage#enableProjectSpecificSettings(boolean) + */ + protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { + super.enableProjectSpecificSettings(useProjectSpecificSettings); + if (fConfigurationBlock != null) { + fConfigurationBlock.useProjectSpecificSettings(useProjectSpecificSettings); + } + } /* * @see org.eclipse.jface.preference.IPreferencePage#performDefaults() diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterProfileManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterProfileManager.java index 32181625b2e..77511de9efa 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterProfileManager.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterProfileManager.java @@ -95,7 +95,7 @@ public class FormatterProfileManager extends ProfileManager { } /* (non-Javadoc) - * @see org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager#getSelectedProfileId(org.eclipse.core.runtime.preferences.IScopeContext) + * @see org.eclipse.cdt.internal.ui.preferences.formatter.ProfileManager#getSelectedProfileId(org.eclipse.core.runtime.preferences.IScopeContext) */ protected String getSelectedProfileId(IScopeContext instanceScope) { String profileId= instanceScope.getNode(CUIPlugin.PLUGIN_ID).get(PROFILE_KEY, null); @@ -117,7 +117,7 @@ public class FormatterProfileManager extends ProfileManager { } /* (non-Javadoc) - * @see org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager#getDefaultProfile() + * @see org.eclipse.cdt.internal.ui.preferences.formatter.ProfileManager#getDefaultProfile() */ public Profile getDefaultProfile() { return getProfile(DEFAULT_PROFILE); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/TranslationUnitPreview.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/TranslationUnitPreview.java index c2e0415f6a1..cc60600e15c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/TranslationUnitPreview.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/TranslationUnitPreview.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2007 IBM Corporation 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 @@ -19,6 +19,7 @@ import java.util.Map; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.formatter.FormattingContext; import org.eclipse.jface.text.formatter.FormattingContextProperties; import org.eclipse.jface.text.formatter.IContentFormatter; import org.eclipse.jface.text.formatter.IContentFormatterExtension; @@ -29,7 +30,6 @@ import org.eclipse.cdt.core.CCorePreferenceConstants; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.ui.ICStatusConstants; -import org.eclipse.cdt.internal.ui.text.comment.CommentFormattingContext; public class TranslationUnitPreview extends CPreview { @@ -53,7 +53,7 @@ public class TranslationUnitPreview extends CPreview { fPreviewDocument.set(fPreviewText); fSourceViewer.setRedraw(false); - final IFormattingContext context = new CommentFormattingContext(); + final IFormattingContext context = new FormattingContext(); try { final IContentFormatter formatter = fViewerConfiguration.getContentFormatter(fSourceViewer); if (formatter instanceof IContentFormatterExtension) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java index b1422e95d07..77f94724ad0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 QNX Software Systems and others. + * Copyright (c) 2000, 2007 QNX Software Systems 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 @@ -59,7 +59,7 @@ public class CFormattingStrategy extends ContextBasedFormattingStrategy { try { final TextEdit edit = CodeFormatterUtil.format( - CodeFormatter.K_COMPILATION_UNIT, document.get(), + CodeFormatter.K_TRANSLATION_UNIT, document.get(), partition.getOffset(), partition.getLength(), 0, TextUtilities.getDefaultLineDelimiter(document), getPreferences()); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java index f62719ea8c9..ecd27d6fcde 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java @@ -95,7 +95,6 @@ import org.eclipse.cdt.internal.ui.typehierarchy.THInformationProvider; * Configuration for an SourceViewer which shows C/C++ code. */ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { - private CTextTools fTextTools; private ITextEditor fTextEditor; /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java index bbb8189f10c..ebbc7b4dd6c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java @@ -84,11 +84,11 @@ import org.eclipse.cdt.ui.IWorkingCopyManager; import org.eclipse.cdt.ui.text.ICPartitions; import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable; +import org.eclipse.cdt.internal.corext.util.Strings; import org.eclipse.cdt.internal.ui.editor.ASTProvider; import org.eclipse.cdt.internal.ui.text.CCodeReader; import org.eclipse.cdt.internal.ui.text.CHeuristicScanner; -import org.eclipse.cdt.internal.ui.util.Strings; /** * A text hover presenting the source of the element under the cursor. @@ -604,7 +604,7 @@ public class CSourceHover extends AbstractCEditorTextHover implements ITextHover String firstLine= sourceLines[0]; if (!Character.isWhitespace(firstLine.charAt(0))) sourceLines[0]= ""; //$NON-NLS-1$ - Strings.trimIndentation(sourceLines, getTabWidth()); + Strings.trimIndentation(sourceLines, getTabWidth(), getTabWidth()); if (!Character.isWhitespace(firstLine.charAt(0))) sourceLines[0]= firstLine; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java index ed680ef92d0..0a22ec1a133 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java @@ -241,6 +241,3 @@ public class ContentAssistPreference { changeCProcessor(assistant, store, p); } } - - - diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java index 766a3daf165..8708dfad2ae 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 QNX Software Systems and others. + * Copyright (c) 2000, 2007 QNX Software Systems 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 @@ -79,7 +79,7 @@ public class DefaultCFoldingPreferenceBlock implements ICFoldingPreferenceBlock } /* - * @see org.eclipse.jdt.internal.ui.text.folding.ICFoldingPreferences#createControl(org.eclipse.swt.widgets.Group) + * @see org.eclipse.cdt.internal.ui.text.folding.ICFoldingPreferences#createControl(org.eclipse.swt.widgets.Group) */ public Control createControl(Composite composite) { fOverlayStore.load(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/EmptyCFoldingPreferenceBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/EmptyCFoldingPreferenceBlock.java index 10c5eb00e1f..97de0446e9c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/EmptyCFoldingPreferenceBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/EmptyCFoldingPreferenceBlock.java @@ -21,7 +21,7 @@ import org.eclipse.swt.widgets.Label; /** * Empty preference block for extensions to the - * org.eclipse.jdt.ui.javaFoldingStructureProvider extension + * org.eclipse.cdt.ui.foldingStructureProviders extension * point that do not specify their own. * * @since 3.0 diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/comment/CommentFormattingContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateMessages.java similarity index 51% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/comment/CommentFormattingContext.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateMessages.java index bdd8cf5f0a9..b2a208cc74a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/comment/CommentFormattingContext.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2007 IBM Corporation 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 @@ -7,18 +7,23 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Sergey Prigogin, Google * Anton Leherbauer (Wind River Systems) *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text.template; -package org.eclipse.cdt.internal.ui.text.comment; +import org.eclipse.osgi.util.NLS; -import org.eclipse.jface.text.formatter.FormattingContext; +public final class TemplateMessages extends NLS { -/** - * Formatting context for the comment formatter. - * - * @since 4.0 - */ -public class CommentFormattingContext extends FormattingContext { + private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.text.template.TemplateMessages";//$NON-NLS-1$ + + private TemplateMessages() { + // Do not instantiate + } + + public static String TemplateVariableProposal_error_title; + + static { + NLS.initializeMessages(BUNDLE_NAME, TemplateMessages.class); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateMessages.properties new file mode 100644 index 00000000000..4c7d64da32c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateMessages.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2000, 2007 IBM Corporation 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: +# IBM Corporation - initial API and implementation +# Anton Leherbauer (Wind River Systems) +############################################################################### + +TemplateVariableProposal_error_title=Error applying template variable proposal diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProcessor.java new file mode 100644 index 00000000000..ebf41b4cc87 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProcessor.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text.template; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.jface.text.templates.TemplateVariableResolver; + + + +public class TemplateVariableProcessor implements IContentAssistProcessor { + + private static Comparator fgTemplateVariableProposalComparator= new Comparator() { + public int compare(Object arg0, Object arg1) { + TemplateVariableProposal proposal0= (TemplateVariableProposal) arg0; + TemplateVariableProposal proposal1= (TemplateVariableProposal) arg1; + + return proposal0.getDisplayString().compareTo(proposal1.getDisplayString()); + } + + public boolean equals(Object arg0) { + return false; + } + }; + + + /** the context type */ + private TemplateContextType fContextType; + + /** + * Sets the context type. + * + * @param contextType the context type + */ + public void setContextType(TemplateContextType contextType) { + fContextType= contextType; + } + + /** + * Gets the context type. + * + * @return the context type + */ + public TemplateContextType getContextType() { + return fContextType; + } + + /* + * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int) + */ + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { + + if (fContextType == null) + return null; + + List proposals= new ArrayList(); + + String text= viewer.getDocument().get(); + int start= getStart(text, documentOffset); + int end= documentOffset; + + String string= text.substring(start, end); + int colon= string.indexOf(':'); + boolean includeBrace= true; + int offset= start; + String prefix= string; + if (colon != -1) { + includeBrace= false; + offset= start + colon + 1; + prefix= string.substring(colon + 1); + } else { + int escape= string.indexOf("${"); //$NON-NLS-1$ + if (escape != -1) { + offset= start + escape + 2; + includeBrace= false; + prefix= string.substring(escape + 2); + } + } + if (prefix.equals("$")) //$NON-NLS-1$ + prefix= ""; //$NON-NLS-1$ + + int length= end - offset; + + for (Iterator iterator= fContextType.resolvers(); iterator.hasNext(); ) { + TemplateVariableResolver variable= (TemplateVariableResolver) iterator.next(); + + if (variable.getType().startsWith(prefix)) + proposals.add(new TemplateVariableProposal(variable, offset, length, viewer, includeBrace)); + } + + Collections.sort(proposals, fgTemplateVariableProposalComparator); + return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]); + } + + /* Guesses the start position of the completion */ + private int getStart(String string, int end) { + int start= end; + + if (start >= 1 && string.charAt(start - 1) == '$') + return start - 1; + + while ((start != 0) && Character.isUnicodeIdentifierPart(string.charAt(start - 1))) + start--; + + if (start >= 1 && string.charAt(start - 1) == ':') { + start--; + while ((start != 0) && Character.isUnicodeIdentifierPart(string.charAt(start - 1))) + start--; + } + + if (start >= 2 && string.charAt(start - 1) == '{' && string.charAt(start - 2) == '$') + return start - 2; + + return end; + } + + /* + * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int) + */ + public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { + return null; + } + + /* + * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() + */ + public char[] getCompletionProposalAutoActivationCharacters() { + return new char[] {'$'}; + } + + /* + * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters() + */ + public char[] getContextInformationAutoActivationCharacters() { + return null; + } + + /* + * @see IContentAssistProcessor#getErrorMessage() + */ + public String getErrorMessage() { + return null; + } + + /* + * @see IContentAssistProcessor#getContextInformationValidator() + */ + public IContextInformationValidator getContextInformationValidator() { + return null; + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProposal.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProposal.java new file mode 100644 index 00000000000..9d1df507c39 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProposal.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text.template; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.templates.TemplateVariableResolver; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.cdt.ui.CUIPlugin; + +/** + * A proposal for insertion of template variables. + */ +public class TemplateVariableProposal implements ICompletionProposal { + + private TemplateVariableResolver fResolver; + private int fOffset; + private int fLength; + private ITextViewer fViewer; + + private Point fSelection; + private final boolean fIncludeBrace; + + /** + * Creates a template variable proposal. + * + * @param variable the template variable + * @param offset the offset to replace + * @param length the length to replace + * @param viewer the viewer + * @param includeBrace whether to also replace the ${ + */ + public TemplateVariableProposal(TemplateVariableResolver variable, int offset, int length, ITextViewer viewer, boolean includeBrace) { + fResolver= variable; + fOffset= offset; + fLength= length; + fViewer= viewer; + fIncludeBrace= includeBrace; + } + + /* + * @see ICompletionProposal#apply(IDocument) + */ + public void apply(IDocument document) { + + try { + String variable; + String type= fResolver.getType(); + if (type.equals("dollar")) //$NON-NLS-1$ + variable= "$$"; //$NON-NLS-1$ + else if (fIncludeBrace) + variable= "${" + type + '}'; //$NON-NLS-1$ + else + variable= type; + document.replace(fOffset, fLength, variable); + fSelection= new Point(fOffset + variable.length(), 0); + + } catch (BadLocationException e) { + CUIPlugin.getDefault().log(e); + + Shell shell= fViewer.getTextWidget().getShell(); + MessageDialog.openError(shell, TemplateMessages.TemplateVariableProposal_error_title, e.getMessage()); + } + } + + /* + * @see ICompletionProposal#getSelection(IDocument) + */ + public Point getSelection(IDocument document) { + return fSelection; + } + + /* + * @see ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return fResolver.getDescription(); + } + + /* + * @see ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return fResolver.getType(); + } + + /* + * @see ICompletionProposal#getImage() + */ + public Image getImage() { + return null; + } + + /* + * @see ICompletionProposal#getContextInformation() + */ + public IContextInformation getContextInformation() { + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/Strings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/Strings.java deleted file mode 100644 index 9e5e4f76bb5..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/Strings.java +++ /dev/null @@ -1,396 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2006 IBM Corporation 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: - * Rational Software - initial implementation - *******************************************************************************/ -package org.eclipse.cdt.internal.ui.util; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DefaultLineTracker; -import org.eclipse.jface.text.ILineTracker; -import org.eclipse.jface.text.IRegion; - -/** - * Helper class to provide String manipulation functions not available in standard JDK. - */ -public class Strings { - - /** - * Indent char is a space char but not a line delimiters. - * == Character.isWhitespace(ch) && ch != '\n' && ch != '\r' - */ - public static boolean isIndentChar(char ch) { - return Character.isWhitespace(ch) && !isLineDelimiterChar(ch); - } - - /** - * tests if a char is lower case. Fix for 26529 - */ - public static boolean isLowerCase(char ch) { - return Character.toLowerCase(ch) == ch; - } - - /** - * Line delimiter chars are '\n' and '\r'. - */ - public static boolean isLineDelimiterChar(char ch) { - return ch == '\n' || ch == '\r'; - } - - public static String removeNewLine(String message) { - StringBuffer result= new StringBuffer(); - int current= 0; - int index= message.indexOf('\n', 0); - while (index != -1) { - result.append(message.substring(current, index)); - if (current < index && index != 0) - result.append(' '); - current= index + 1; - index= message.indexOf('\n', current); - } - result.append(message.substring(current)); - return result.toString(); - } - - /** - * Converts the given string into an array of lines. The lines - * don't contain any line delimiter characters. - * - * @return the string converted into an array of strings. Returns - * null if the input string can't be converted in an array of lines. - */ - public static String[] convertIntoLines(String input) { - try { - ILineTracker tracker= new DefaultLineTracker(); - tracker.set(input); - int size= tracker.getNumberOfLines(); - String result[]= new String[size]; - for (int i= 0; i < size; i++) { - IRegion region= tracker.getLineInformation(i); - int offset= region.getOffset(); - result[i]= input.substring(offset, offset + region.getLength()); - } - return result; - } catch (BadLocationException e) { - return null; - } - } - - /** - * Returns true if the given string only consists of - * white spaces according to Java. If the string is empty, true - * is returned. - * - * @return true if the string only consists of white - * spaces; otherwise false is returned - * - * @see java.lang.Character#isWhitespace(char) - */ - public static boolean containsOnlyWhitespaces(String s) { - int size= s.length(); - for (int i= 0; i < size; i++) { - if (!Character.isWhitespace(s.charAt(i))) - return false; - } - return true; - } - - /** - * Removes leading tabs and spaces from the given string. If the string - * doesn't contain any leading tabs or spaces then the string itself is - * returned. - */ - public static String trimLeadingTabsAndSpaces(String line) { - int size= line.length(); - int start= size; - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (!isIndentChar(c)) { - start= i; - break; - } - } - if (start == 0) - return line; - else if (start == size) - return ""; //$NON-NLS-1$ - else - return line.substring(start); - } - - public static String trimTrailingTabsAndSpaces(String line) { - int size= line.length(); - int end= size; - for (int i= size - 1; i >= 0; i--) { - char c= line.charAt(i); - if (isIndentChar(c)) { - end= i; - } else { - break; - } - } - if (end == size) - return line; - else if (end == 0) - return ""; //$NON-NLS-1$ - else - return line.substring(0, end); - } - - /** - * Returns the indent of the given string. - * - * @param line the text line - * @param tabWidth the width of the '\t' character. - * @return the indentation level of the given string - * - * @deprecated use {@link #computeIndent(String, int, int)} instead. - */ - public static int computeIndent(String line, int tabWidth) { - return computeIndent(line, tabWidth, tabWidth); - } - - /** - * Returns the indent level of the given string. - * - * @param line the text line - * @param tabWidth the width of the '\t' character. - * @param indentSize the space-equivalent of an indent level - * @return the indentation level of the given string - */ - public static int computeIndent(String line, int tabWidth, int indentSize) { - int result= 0; - int size= line.length(); - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (c == '\t') { - result+= tabWidth; - } else if (isIndentChar(c)) { - result++; - } else { - break; - } - } - return result / indentSize; - } - - /** - * Removes the given number of idents from the line. Asserts that the given line - * has the requested number of indents. If indentsToRemove <= 0 - * the line is returned. - */ - public static String trimIndent(String line, int indentsToRemove, int tabWidth) { - if (line == null || indentsToRemove <= 0) - return line; - - int start= 0; - int indents= 0; - int blanks= 0; - int size= line.length(); - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (c == '\t') { - indents++; - blanks= 0; - } else if (isIndentChar(c)) { - blanks++; - if (blanks == tabWidth) { - indents++; - blanks= 0; - } - } else { - // Assert.isTrue(false, "Line does not have requested number of indents"); //$NON-NLS-1$ - start= i + 1; - break; - } - if (indents == indentsToRemove) { - start= i + 1; - break; - } - } - if (start == size) - return ""; //$NON-NLS-1$ - return line.substring(start); - } - - /** - * Removes all leading indents from the given line. If the line doesn't contain - * any indents the line itself is returned. - */ - public static String trimIndents(String s, int tabWidth) { - int indent= computeIndent(s, tabWidth); - if (indent == 0) - return s; - return trimIndent(s, indent, tabWidth); - } - - /** - * Removes the common number of indents from all lines. If a line - * only consists out of white space it is ignored. - */ - public static void trimIndentation(String[] lines, int tabWidth) { - trimIndentation(lines, tabWidth, true); - } - - /** - * Removes the common number of indents from all lines. If a line - * only consists out of white space it is ignored. If - * considerFirstLine is false the first line will be ignored. - */ - public static void trimIndentation(String[] lines, int tabWidth, boolean considerFirstLine) { - String[] toDo= new String[lines.length]; - // find indentation common to all lines - int minIndent= Integer.MAX_VALUE; // very large - for (int i= considerFirstLine ? 0 : 1; i < lines.length; i++) { - String line= lines[i]; - if (containsOnlyWhitespaces(line)) - continue; - toDo[i]= line; - int indent= computeIndent(line, tabWidth); - if (indent < minIndent) { - minIndent= indent; - } - } - - if (minIndent > 0) { - // remove this indent from all lines - for (int i= considerFirstLine ? 0 : 1; i < toDo.length; i++) { - String s= toDo[i]; - if (s != null) - lines[i]= trimIndent(s, minIndent, tabWidth); - else { - String line= lines[i]; - int indent= computeIndent(line, tabWidth); - if (indent > minIndent) - lines[i]= trimIndent(line, minIndent, tabWidth); - else - lines[i]= trimLeadingTabsAndSpaces(line); - } - } - } - } - - public static String getIndentString(String line, int tabWidth) { - int size= line.length(); - int end= 0; - int blanks= 0; - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (c == '\t') { - end= i + 1; - blanks= 0; - } else if (isIndentChar(c)) { - blanks++; - if (blanks == tabWidth) { - end= i + 1; - blanks= 0; - } - } else { - break; - } - } - if (end == 0) - return ""; //$NON-NLS-1$ - else if (end == size) - return line; - else - return line.substring(0, end); - } - - public static String[] removeTrailingEmptyLines(String[] sourceLines) { - int lastNonEmpty= findLastNonEmptyLineIndex(sourceLines); - String[] result= new String[lastNonEmpty + 1]; - for (int i= 0; i < result.length; i++) { - result[i]= sourceLines[i]; - } - return result; - } - - private static int findLastNonEmptyLineIndex(String[] sourceLines) { - for (int i= sourceLines.length - 1; i >= 0; i--) { - if (! sourceLines[i].trim().equals(""))//$NON-NLS-1$ - return i; - } - return -1; - } - - /** - * Change the indent of, possible muti-line, code range. The current indent is removed, a new indent added. - * The first line of the code will not be changed. (It is considered to have no indent as it might start in - * the middle of a line) - */ - public static String changeIndent(String code, int codeIndentLevel, int tabWidth, String newIndent, String lineDelim) { - try { - ILineTracker tracker= new DefaultLineTracker(); - tracker.set(code); - int nLines= tracker.getNumberOfLines(); - if (nLines == 1) { - return code; - } - - StringBuffer buf= new StringBuffer(); - - for (int i= 0; i < nLines; i++) { - IRegion region= tracker.getLineInformation(i); - int start= region.getOffset(); - int end= start + region.getLength(); - String line= code.substring(start, end); - - if (i == 0) { // no indent for first line (contained in the formatted string) - buf.append(line); - } else { // no new line after last line - buf.append(lineDelim); - buf.append(newIndent); - buf.append(trimIndent(line, codeIndentLevel, tabWidth)); - } - } - return buf.toString(); - } catch (BadLocationException e) { - // can not happen - return code; - } - } - - /** - * Concatenate the given strings into one strings using the passed line delimiter as a - * delimiter. No delimiter is added to the last line. - */ - public static String concatenate(String[] lines, String delimiter) { - StringBuffer buffer= new StringBuffer(); - for (int i= 0; i < lines.length; i++) { - if (i > 0) - buffer.append(delimiter); - buffer.append(lines[i]); - } - return buffer.toString(); - } - - public static boolean equals(String s, char[] c) { - if (s.length() != c.length) - return false; - - for (int i = c.length; --i >= 0;) - if (s.charAt(i) != c[i]) - return false; - return true; - } - - /** - * Creates a string that consists of the given number of tab characters. - * @param indentLevel - */ - public static String createIndentString(int indentLevel) { - StringBuffer result = new StringBuffer(); - for (int i = 0; i < indentLevel; i++) { - result.append('\t'); - } - return result.toString(); - } - -} - diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/ProjectTemplateStore.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/ProjectTemplateStore.java new file mode 100644 index 00000000000..139d6cd1b5d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/ProjectTemplateStore.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.viewsupport; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; +import org.eclipse.jface.text.templates.persistence.TemplateReaderWriter; +import org.eclipse.jface.text.templates.persistence.TemplateStore; +import org.eclipse.ui.preferences.ScopedPreferenceStore; + +import org.eclipse.cdt.ui.CUIPlugin; + +/** + * @since 5.0 + */ +public final class ProjectTemplateStore { + + private static final String KEY= "org.eclipse.cdt.ui.text.custom_code_templates"; //$NON-NLS-1$ + + private final TemplateStore fInstanceStore; + private final TemplateStore fProjectStore; + + public ProjectTemplateStore(IProject project) { + fInstanceStore= CUIPlugin.getDefault().getCodeTemplateStore(); + if (project == null) { + fProjectStore= null; + } else { + final ScopedPreferenceStore projectSettings= new ScopedPreferenceStore(new ProjectScope(project), CUIPlugin.PLUGIN_ID); + fProjectStore= new TemplateStore(projectSettings, KEY) { + /* + * Make sure we keep the id of added code templates - add removes + * it in the usual add() method + */ + public void add(TemplatePersistenceData data) { + if (data.isUserAdded()) { + super.add(data); + } else { + internalAdd(data); + } + } + + public void save() throws IOException { + + StringWriter output= new StringWriter(); + TemplateReaderWriter writer= new TemplateReaderWriter(); + writer.save(getTemplateData(false), output); + + projectSettings.setValue(KEY, output.toString()); + projectSettings.save(); + } + }; + } + } + + public static boolean hasProjectSpecificTempates(IProject project) { + String pref= new ProjectScope(project).getNode(CUIPlugin.PLUGIN_ID).get(KEY, null); + if (pref != null && pref.trim().length() > 0) { + Reader input= new StringReader(pref); + TemplateReaderWriter reader= new TemplateReaderWriter(); + TemplatePersistenceData[] datas; + try { + datas= reader.read(input); + return datas.length > 0; + } catch (IOException e) { + // ignore + } + } + return false; + } + + + public TemplatePersistenceData[] getTemplateData() { + if (fProjectStore != null) { + return fProjectStore.getTemplateData(true); + } else { + return fInstanceStore.getTemplateData(true); + } + } + + public Template findTemplateById(String id) { + Template template= null; + if (fProjectStore != null) + template= fProjectStore.findTemplateById(id); + if (template == null) + template= fInstanceStore.findTemplateById(id); + + return template; + } + + public void load() throws IOException { + if (fProjectStore != null) { + fProjectStore.load(); + + Set datas= new HashSet(); + TemplatePersistenceData[] data= fProjectStore.getTemplateData(false); + for (int i= 0; i < data.length; i++) { + String id= data[i].getId(); + if (id == null) { + id= data[i].getTemplate().getName(); + } + datas.add(id); + } + + data= fInstanceStore.getTemplateData(false); + for (int i= 0; i < data.length; i++) { + TemplatePersistenceData orig= data[i]; + String origId= orig.getId(); + if (origId == null) { + origId= orig.getTemplate().getName(); + } + if (!datas.contains(orig.getId())) { + TemplatePersistenceData copy= new TemplatePersistenceData(new Template(orig.getTemplate()), orig.isEnabled(), orig.getId()); + fProjectStore.add(copy); + copy.setDeleted(true); + } + } + } + } + + public boolean isProjectSpecific(String id) { + if (id == null) { + return false; + } + + if (fProjectStore == null) + return false; + + return fProjectStore.findTemplateById(id) != null; + } + + + public void setProjectSpecific(String id, boolean projectSpecific) { + Assert.isNotNull(fProjectStore); + + TemplatePersistenceData data= fProjectStore.getTemplateData(id); + if (data == null) { + return; // does not exist + } else { + data.setDeleted(!projectSpecific); + } + } + + public void restoreDefaults() { + if (fProjectStore == null) { + fInstanceStore.restoreDefaults(); + } else { + fProjectStore.restoreDefaults(); + } + } + + public void save() throws IOException { + if (fProjectStore == null) { + fInstanceStore.save(); + } else { + fProjectStore.save(); + } + } + + public void revertChanges() throws IOException { + if (fProjectStore != null) { + // nothing to do + } else { + fInstanceStore.load(); + } + } + + public void addTemplateData(TemplatePersistenceData data) { + if (fProjectStore != null) { + fProjectStore.add(data); + } else { + fInstanceStore.add(data); + } + } + + public void delete(TemplatePersistenceData data) { + if (fProjectStore != null) { + fProjectStore.delete(data); + } else { + fInstanceStore.delete(data); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/NewWizardMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/NewWizardMessages.properties index 5c141d169d6..b99bb257944 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/NewWizardMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/NewWizardMessages.properties @@ -85,15 +85,6 @@ BaseClassSelectionDialog.title=Choose Base Class BaseClassSelectionDialog.message=&Choose a class (? = any character, * = any string): BaseClassSelectionDialog.filter= -# --- New File --- -WizardNewFileCreationPage.progress = Creating -WizardNewFileCreationPage.errorTitle = Creation Problems -WizardNewFileCreationPage.fileLabel = File &name: -WizardNewFileCreationPage.file = file -WizardNewFileCreationPage.internalErrorTitle = Creation problems -WizardNewFileCreationPage.internalErrorMessage = Internal error: {0} -WizardNewFileCreationPage.fileExistsMessage = A file ''{0}'' already exists in the file system. - # ----------- SourceFolderSelectionDialog ------------- SourceFolderSelectionDialog.title= Folder Selection SourceFolderSelectionDialog.description= &Choose a source folder: diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java index 0896dfec403..08cc40a8757 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,9 +7,13 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; public abstract class AbstractMethodStub implements IMethodStub { @@ -78,7 +82,7 @@ public abstract class AbstractMethodStub implements IMethodStub { return false; } - public abstract String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); + public abstract String createMethodDeclaration(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException; - public abstract String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); + public abstract String createMethodImplementation(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java index 846b3d1760a..2f3e435f230 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java @@ -10,7 +10,11 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; +import org.eclipse.cdt.ui.CodeGeneration; public final class ConstructorMethodStub extends AbstractMethodStub { @@ -25,34 +29,42 @@ public final class ConstructorMethodStub extends AbstractMethodStub { super(NAME, access, false, isInline); } - public String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { - //TODO should use code templates + public String createMethodDeclaration(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException { StringBuffer buf = new StringBuffer(); buf.append(className); buf.append("()"); //$NON-NLS-1$ if (fIsInline) { - buf.append(" {}"); //$NON-NLS-1$ + buf.append('{'); + buf.append(lineDelimiter); + String body= CodeGeneration.getConstructorBodyContent(tu, className, null, lineDelimiter); + if (body != null) { + buf.append(body); + buf.append(lineDelimiter); + } + buf.append('}'); } else { buf.append(";"); //$NON-NLS-1$ } return buf.toString(); } - public String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { - //TODO should use code templates + public String createMethodImplementation(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException { if (fIsInline) { return ""; //$NON-NLS-1$ } StringBuffer buf = new StringBuffer(); buf.append(className); buf.append("::"); //$NON-NLS-1$ - buf.append(className.toString()); + buf.append(className); buf.append("()"); //$NON-NLS-1$ buf.append(lineDelimiter); buf.append('{'); buf.append(lineDelimiter); - //buf.append("// TODO Auto-generated constructor stub"); - //buf.append(lineDelimiter); + String body= CodeGeneration.getConstructorBodyContent(tu, className, null, lineDelimiter); + if (body != null) { + buf.append(body); + buf.append(lineDelimiter); + } buf.append('}'); return buf.toString(); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java index e3ef2b94ca8..b665a3490f7 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,10 +7,15 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; +import org.eclipse.cdt.ui.CodeGeneration; public final class DestructorMethodStub extends AbstractMethodStub { @@ -25,8 +30,7 @@ public final class DestructorMethodStub extends AbstractMethodStub { super(NAME, access, isVirtual, isInline); } - public String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { - //TODO should use code templates + public String createMethodDeclaration(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException { StringBuffer buf = new StringBuffer(); if (fIsVirtual){ buf.append("virtual "); //$NON-NLS-1$ @@ -35,15 +39,21 @@ public final class DestructorMethodStub extends AbstractMethodStub { buf.append(className); buf.append("()"); //$NON-NLS-1$ if (fIsInline) { - buf.append(" {}"); //$NON-NLS-1$ + buf.append('{'); + buf.append(lineDelimiter); + String body= CodeGeneration.getDestructorBodyContent(tu, className, null, lineDelimiter); + if (body != null) { + buf.append(body); + buf.append(lineDelimiter); + } + buf.append('}'); } else { buf.append(";"); //$NON-NLS-1$ } return buf.toString(); } - public String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { - //TODO should use code templates + public String createMethodImplementation(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException { if (fIsInline) { return ""; //$NON-NLS-1$ } @@ -53,11 +63,14 @@ public final class DestructorMethodStub extends AbstractMethodStub { buf.append(className); buf.append("()"); //$NON-NLS-1$ buf.append(lineDelimiter); - buf.append('{'); - buf.append(lineDelimiter); - //buf.append("// TODO Auto-generated destructor stub"); - //buf.append(lineDelimiter); - buf.append('}'); + buf.append('{'); + buf.append(lineDelimiter); + String body= CodeGeneration.getDestructorBodyContent(tu, className, null, lineDelimiter); + if (body != null) { + buf.append(body); + buf.append(lineDelimiter); + } + buf.append('}'); return buf.toString(); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java index ba8c9b39e32..1d0e380fde4 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,9 +7,13 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; @@ -32,6 +36,6 @@ public interface IMethodStub { public boolean isConstructor(); public boolean isDestructor(); - public String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); - public String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); + public String createMethodDeclaration(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException; + public String createMethodImplementation(ITranslationUnit tu, String className, IBaseClassInfo[] baseClasses, String lineDelimiter) throws CoreException; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java index d95afb44126..f5b5e0a35bd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java @@ -9,6 +9,7 @@ * QNX Software Systems - initial API and implementation * IBM Corporation * Warren Paul (Nokia) - 173555 + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; @@ -16,11 +17,28 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.TextEdit; + import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.browser.IQualifiedTypeName; import org.eclipse.cdt.core.browser.ITypeReference; import org.eclipse.cdt.core.browser.PathUtil; import org.eclipse.cdt.core.browser.QualifiedTypeName; +import org.eclipse.cdt.core.formatter.CodeFormatter; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICContainer; @@ -33,19 +51,14 @@ import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfoProvider; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; -import org.eclipse.cdt.internal.corext.util.CModelUtil; -import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.cdt.ui.CodeGeneration; + +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; +import org.eclipse.cdt.internal.corext.util.CModelUtil; +import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil; + +import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; public class NewClassCodeGenerator { @@ -53,12 +66,12 @@ public class NewClassCodeGenerator { private IPath fSourcePath = null; private String fClassName = null; private IQualifiedTypeName fNamespace = null; - private String fLineDelimiter; private IBaseClassInfo[] fBaseClasses = null; private IMethodStub[] fMethodStubs = null; private ITranslationUnit fCreatedHeaderTU = null; private ITranslationUnit fCreatedSourceTU = null; private ICElement fCreatedClass = null; + private String fFullyQualifiedClassName; public static class CodeGeneratorException extends CoreException { /** @@ -84,9 +97,13 @@ public class NewClassCodeGenerator { if (namespace != null && namespace.length() > 0) { fNamespace = new QualifiedTypeName(namespace); } + if (fNamespace != null) { + fFullyQualifiedClassName= fNamespace.append(fClassName).getFullyQualifiedName(); + } else { + fFullyQualifiedClassName= fClassName; + } fBaseClasses = baseClasses; fMethodStubs = methodStubs; - fLineDelimiter = NewSourceFileGenerator.getLineDelimiter(); } public ICElement getCreatedClass() { @@ -155,6 +172,7 @@ public class NewClassCodeGenerator { // headerWorkingCopy = headerTU.getSharedWorkingCopy(null, CUIPlugin.getDefault().getBufferFactory()); String headerContent = constructHeaderFileContent(headerTU, publicMethods, protectedMethods, privateMethods, headerWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100)); + headerContent= formatSource(headerContent, headerTU); headerWorkingCopy.getBuffer().setContents(headerContent); if (monitor.isCanceled()) { @@ -165,11 +183,7 @@ public class NewClassCodeGenerator { headerWorkingCopy.commit(true, monitor); monitor.worked(50); - IQualifiedTypeName className = new QualifiedTypeName(fClassName); - if(fNamespace != null){ - className = fNamespace.append(className); - } - createdClass = headerWorkingCopy.getElement(className.getFullyQualifiedName()); + createdClass = headerWorkingCopy.getElement(fFullyQualifiedClassName); fCreatedClass = createdClass; fCreatedHeaderTU = headerTU; } @@ -196,6 +210,7 @@ public class NewClassCodeGenerator { sourceWorkingCopy = sourceTU.getWorkingCopy(); String sourceContent = constructSourceFileContent(sourceTU, headerTU, publicMethods, protectedMethods, privateMethods, sourceWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100)); + sourceContent= formatSource(sourceContent, sourceTU); sourceWorkingCopy.getBuffer().setContents(sourceContent); if (monitor.isCanceled()) { @@ -222,13 +237,40 @@ public class NewClassCodeGenerator { return fCreatedClass; } - public String constructHeaderFileContent(ITranslationUnit headerTU, List publicMethods, List protectedMethods, List privateMethods, String oldContents, IProgressMonitor monitor) throws CodeGeneratorException { + /** + * Format given source content according to the project's code style options. + * + * @param content the source content + * @param tu the translation unit + * @return the formatted source text or the original if the text could not be formatted successfully + * @throws CModelException + */ + private String formatSource(String content, ITranslationUnit tu) throws CModelException { + String lineDelimiter= StubUtility.getLineDelimiterUsed(tu); + TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_TRANSLATION_UNIT, content, 0, lineDelimiter, tu.getCProject().getOptions(true)); + if (edit != null) { + IDocument doc= new Document(content); + try { + edit.apply(doc); + content= doc.get(); + } catch (MalformedTreeException exc) { + CUIPlugin.getDefault().log(exc); + } catch (BadLocationException exc) { + CUIPlugin.getDefault().log(exc); + } + } + return content; + } + + public String constructHeaderFileContent(ITranslationUnit headerTU, List publicMethods, List protectedMethods, List privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException { monitor.beginTask(NewClassWizardMessages.getString("NewClassCodeGeneration.createType.task.header"), 100); //$NON-NLS-1$ - if (oldContents != null && oldContents.length() == 0) + String lineDelimiter= StubUtility.getLineDelimiterUsed(headerTU); + + if (oldContents != null && oldContents.length() == 0) oldContents = null; - //TODO should use code templates + StringBuffer text = new StringBuffer(); int appendFirstCharPos = -1; @@ -247,45 +289,46 @@ public class NewClassCodeGenerator { } appendFirstCharPos = prependLastCharPos + 1; } - text.append(fLineDelimiter); + text.append(lineDelimiter); // insert a blank line before class definition - text.append(fLineDelimiter); + text.append(lineDelimiter); } if (fBaseClasses != null && fBaseClasses.length > 0) { - addBaseClassIncludes(headerTU, text, new SubProgressMonitor(monitor, 50)); - text.append(fLineDelimiter); + addBaseClassIncludes(headerTU, text, lineDelimiter, new SubProgressMonitor(monitor, 50)); + text.append(lineDelimiter); } if (fNamespace != null) { - beginNamespace(text); + beginNamespace(text, lineDelimiter); } text.append("class "); //$NON-NLS-1$ text.append(fClassName); addBaseClassInheritance(text); - text.append(fLineDelimiter); + text.append(lineDelimiter); text.append('{'); - text.append(fLineDelimiter); + text.append(lineDelimiter); //TODO sort methods (eg constructor always first?) if (!publicMethods.isEmpty() || !protectedMethods.isEmpty() || !privateMethods.isEmpty()) { - addMethodDeclarations(publicMethods, protectedMethods, privateMethods, text); + addMethodDeclarations(headerTU, publicMethods, protectedMethods, privateMethods, text, lineDelimiter); } text.append("};"); //$NON-NLS-1$ - text.append(fLineDelimiter); + text.append(lineDelimiter); if (fNamespace != null) { - endNamespace(text); + endNamespace(text, lineDelimiter); } + String fileContent; if (oldContents != null && appendFirstCharPos != -1) { // insert a blank line after class definition - text.append(fLineDelimiter); + text.append(lineDelimiter); // skip over any extra whitespace int len = oldContents.length(); @@ -295,11 +338,14 @@ public class NewClassCodeGenerator { if (appendFirstCharPos < len) { text.append(oldContents.substring(appendFirstCharPos)); } + fileContent= text.toString(); + } else { + String classComment= getClassComment(headerTU, lineDelimiter); + fileContent= CodeGeneration.getHeaderFileContent(headerTU, classComment, text.toString(), lineDelimiter); } - - String newContents = text.toString(); + monitor.done(); - return newContents; + return fileContent; } private int getClassDefInsertionPos(String contents) { @@ -318,59 +364,100 @@ public class NewClassCodeGenerator { return insertPos; } - private void beginNamespace(StringBuffer text) { + /** + * Retrieve the class comment. Returns the content of the 'type comment' template. + * + * @param tu the translation unit + * @param lineDelimiter the line delimiter to use + * @return the type comment or null if a type comment + * is not desired + * + * @since 5.0 + */ + private String getClassComment(ITranslationUnit tu, String lineDelimiter) { + if (isAddComments(tu)) { + try { + String fqName= fFullyQualifiedClassName; + String comment= CodeGeneration.getClassComment(tu, fqName, lineDelimiter); + if (comment != null && isValidComment(comment)) { + return comment; + } + } catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } + } + return null; + } + + private boolean isValidComment(String template) { + // TODO verify comment + return true; + } + + /** + * Returns if comments are added. The settings as specified in the preferences is used. + * + * @param tu + * @return Returns true if comments can be added + * @since 5.0 + */ + public boolean isAddComments(ITranslationUnit tu) { + return StubUtility.doAddComments(tu.getCProject()); + } + + private void beginNamespace(StringBuffer text, String lineDelimiter) { for (int i = 0; i < fNamespace.segmentCount(); ++i) { text.append("namespace "); //$NON-NLS-1$ text.append(fNamespace.segment(i)); - text.append(fLineDelimiter); + text.append(lineDelimiter); text.append('{'); - text.append(fLineDelimiter); - text.append(fLineDelimiter); + text.append(lineDelimiter); + text.append(lineDelimiter); } } - private void endNamespace(StringBuffer text) { + private void endNamespace(StringBuffer text, String lineDelimiter) { for (int i = 0; i < fNamespace.segmentCount(); ++i) { - text.append(fLineDelimiter); + text.append(lineDelimiter); text.append("}"); //$NON-NLS-1$ - text.append(fLineDelimiter); + text.append(lineDelimiter); } } - private void addMethodDeclarations(List publicMethods, List protectedMethods, List privateMethods, StringBuffer text) { + private void addMethodDeclarations(ITranslationUnit tu, List publicMethods, List protectedMethods, List privateMethods, StringBuffer text, String lineDelimiter) throws CoreException { if (!publicMethods.isEmpty()) { text.append("public:"); //$NON-NLS-1$ - text.append(fLineDelimiter); + text.append(lineDelimiter); for (Iterator i = publicMethods.iterator(); i.hasNext();) { IMethodStub stub = (IMethodStub) i.next(); - String code = stub.createMethodDeclaration(fClassName, fBaseClasses, fLineDelimiter); + String code = stub.createMethodDeclaration(tu, fClassName, fBaseClasses, lineDelimiter); text.append('\t'); text.append(code); - text.append(fLineDelimiter); + text.append(lineDelimiter); } } if (!protectedMethods.isEmpty()) { text.append("protected:"); //$NON-NLS-1$ - text.append(fLineDelimiter); + text.append(lineDelimiter); for (Iterator i = protectedMethods.iterator(); i.hasNext();) { IMethodStub stub = (IMethodStub) i.next(); - String code = stub.createMethodDeclaration(fClassName, fBaseClasses, fLineDelimiter); + String code = stub.createMethodDeclaration(tu, fClassName, fBaseClasses, lineDelimiter); text.append('\t'); text.append(code); - text.append(fLineDelimiter); + text.append(lineDelimiter); } } if (!privateMethods.isEmpty()) { text.append("private:"); //$NON-NLS-1$ - text.append(fLineDelimiter); + text.append(lineDelimiter); for (Iterator i = privateMethods.iterator(); i.hasNext();) { IMethodStub stub = (IMethodStub) i.next(); - String code = stub.createMethodDeclaration(fClassName, fBaseClasses, fLineDelimiter); + String code = stub.createMethodDeclaration(tu, fClassName, fBaseClasses, lineDelimiter); text.append('\t'); text.append(code); - text.append(fLineDelimiter); + text.append(lineDelimiter); } } } @@ -412,7 +499,7 @@ public class NewClassCodeGenerator { } } - private void addBaseClassIncludes(ITranslationUnit headerTU, StringBuffer text, IProgressMonitor monitor) throws CodeGeneratorException { + private void addBaseClassIncludes(ITranslationUnit headerTU, StringBuffer text, String lineDelimiter, IProgressMonitor monitor) throws CodeGeneratorException { monitor.beginTask(NewClassWizardMessages.getString("NewClassCodeGeneration.createType.task.header.includePaths"), 100); //$NON-NLS-1$ @@ -465,7 +552,7 @@ public class NewClassCodeGenerator { if (!(headerTU.getElementName().equals(includePath.toString()))) { String include = getIncludeString(includePath.toString(), true); text.append(include); - text.append(fLineDelimiter); + text.append(lineDelimiter); } } @@ -475,7 +562,7 @@ public class NewClassCodeGenerator { if (!(headerTU.getElementName().equals(includePath.toString()))) { String include = getIncludeString(includePath.toString(), false); text.append(include); - text.append(fLineDelimiter); + text.append(lineDelimiter); } } @@ -649,9 +736,10 @@ public class NewClassCodeGenerator { return list; } - public String constructSourceFileContent(ITranslationUnit sourceTU, ITranslationUnit headerTU, List publicMethods, List protectedMethods, List privateMethods, String oldContents, IProgressMonitor monitor) { + public String constructSourceFileContent(ITranslationUnit sourceTU, ITranslationUnit headerTU, List publicMethods, List protectedMethods, List privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException { monitor.beginTask(NewClassWizardMessages.getString("NewClassCodeGeneration.createType.task.source"), 150); //$NON-NLS-1$ + String lineDelimiter= StubUtility.getLineDelimiterUsed(sourceTU); if (oldContents != null && oldContents.length() == 0) oldContents = null; @@ -675,27 +763,27 @@ public class NewClassCodeGenerator { int insertionPos = getIncludeInsertionPos(oldContents); if (insertionPos == -1) { text.append(oldContents); - text.append(fLineDelimiter); + text.append(lineDelimiter); text.append(includeString); - text.append(fLineDelimiter); + text.append(lineDelimiter); } else { text.append(oldContents.substring(0, insertionPos)); text.append(includeString); - text.append(fLineDelimiter); + text.append(lineDelimiter); text.append(oldContents.substring(insertionPos)); } } else { text.append(includeString); - text.append(fLineDelimiter); + text.append(lineDelimiter); } // add a blank line - text.append(fLineDelimiter); + text.append(lineDelimiter); } else if (oldContents != null) { text.append(oldContents); // add a blank line - text.append(fLineDelimiter); + text.append(lineDelimiter); } //TODO sort methods (eg constructor always first?) @@ -705,19 +793,24 @@ public class NewClassCodeGenerator { // no methods } else { if (fNamespace != null) { - beginNamespace(text); + beginNamespace(text, lineDelimiter); } - addMethodBodies(publicMethods, protectedMethods, privateMethods, text, new SubProgressMonitor(monitor, 50)); + addMethodBodies(sourceTU, publicMethods, protectedMethods, privateMethods, text, lineDelimiter, new SubProgressMonitor(monitor, 50)); if (fNamespace != null) { - endNamespace(text); + endNamespace(text, lineDelimiter); } } - String newContents = text.toString(); + String fileContent; + if (oldContents != null) { + fileContent = text.toString(); + } else { + fileContent= CodeGeneration.getBodyFileContent(sourceTU, null, text.toString(), lineDelimiter); + } monitor.done(); - return newContents; + return fileContent; } private String getHeaderIncludeString(ITranslationUnit sourceTU, ITranslationUnit headerTU, StringBuffer text, IProgressMonitor monitor) { @@ -800,37 +893,37 @@ public class NewClassCodeGenerator { return -1; } - private void addMethodBodies(List publicMethods, List protectedMethods, List privateMethods, StringBuffer text, IProgressMonitor monitor) { + private void addMethodBodies(ITranslationUnit tu, List publicMethods, List protectedMethods, List privateMethods, StringBuffer text, String lineDelimiter, IProgressMonitor monitor) throws CoreException { if (!publicMethods.isEmpty()) { for (Iterator i = publicMethods.iterator(); i.hasNext();) { IMethodStub stub = (IMethodStub) i.next(); - String code = stub.createMethodImplementation(fClassName, fBaseClasses, fLineDelimiter); + String code = stub.createMethodImplementation(tu, fClassName, fBaseClasses, lineDelimiter); text.append(code); - text.append(fLineDelimiter); + text.append(lineDelimiter); if (i.hasNext()) - text.append(fLineDelimiter); + text.append(lineDelimiter); } } if (!protectedMethods.isEmpty()) { for (Iterator i = protectedMethods.iterator(); i.hasNext();) { IMethodStub stub = (IMethodStub) i.next(); - String code = stub.createMethodImplementation(fClassName, fBaseClasses, fLineDelimiter); + String code = stub.createMethodImplementation(tu, fClassName, fBaseClasses, lineDelimiter); text.append(code); - text.append(fLineDelimiter); + text.append(lineDelimiter); if (i.hasNext()) - text.append(fLineDelimiter); + text.append(lineDelimiter); } } if (!privateMethods.isEmpty()) { for (Iterator i = privateMethods.iterator(); i.hasNext();) { IMethodStub stub = (IMethodStub) i.next(); - String code = stub.createMethodImplementation(fClassName, fBaseClasses, fLineDelimiter); + String code = stub.createMethodImplementation(tu, fClassName, fBaseClasses, lineDelimiter); text.append(code); - text.append(fLineDelimiter); + text.append(lineDelimiter); if (i.hasNext()) - text.append(fLineDelimiter); + text.append(lineDelimiter); } } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/TreeListDialogField.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/TreeListDialogField.java index f1df06c0d57..2a15c0f15fb 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/TreeListDialogField.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/TreeListDialogField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2006 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.dialogfields; @@ -40,6 +41,7 @@ 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.viewers.ViewerSorter; import org.eclipse.cdt.internal.ui.util.PixelConverter; @@ -56,7 +58,7 @@ public class TreeListDialogField extends DialogField { protected ILabelProvider fLabelProvider; protected TreeViewerAdapter fTreeViewerAdapter; protected List fElements; - protected ViewerSorter fViewerSorter; + protected ViewerComparator fViewerComparator; protected String[] fButtonLabels; private Button[] fButtonControls; @@ -149,9 +151,21 @@ public class TreeListDialogField extends DialogField { * * @param viewerSorter * The viewerSorter to set + * + * @deprecated Use {@link #setViewerComparator(ViewerComparator)} instead. */ public void setViewerSorter(ViewerSorter viewerSorter) { - fViewerSorter = viewerSorter; + setViewerComparator(viewerSorter); + } + + /** + * Sets the viewerComparator. + * + * @param viewerComparator + * The viewerComparator to set + */ + public void setViewerComparator(ViewerComparator viewerComparator) { + fViewerComparator = viewerComparator; } public void setTreeExpansionLevel(int level) { @@ -274,8 +288,8 @@ public class TreeListDialogField extends DialogField { fTree.setInput(fParentElement); fTree.expandToLevel(fTreeExpandLevel); - if (fViewerSorter != null) { - fTree.setSorter(fViewerSorter); + if (fViewerComparator != null) { + fTree.setComparator(fViewerComparator); } fTreeControl.setEnabled(isEnabled()); @@ -666,9 +680,9 @@ public class TreeListDialogField extends DialogField { public void selectFirstElement() { Object element = null; - if (fViewerSorter != null) { + if (fViewerComparator != null) { Object[] arr = fElements.toArray(); - fViewerSorter.sort(fTree, arr); + fViewerComparator.sort(fTree, arr); if (arr.length > 0) { element = arr[0]; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizard.java index bac2fe65cb9..b7223ed9397 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizard.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizard.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2006 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.filewizard; @@ -27,7 +28,7 @@ public abstract class AbstractFileCreationWizard extends NewElementWizard { super(); setDefaultPageImageDescriptor(CPluginImages.DESC_WIZBAN_NEW_FILE); setDialogSettings(CUIPlugin.getDefault().getDialogSettings()); - setWindowTitle(NewFileWizardMessages.getString("AbstractFileCreationWizard.title")); //$NON-NLS-1$ + setWindowTitle(NewFileWizardMessages.AbstractFileCreationWizard_title); } /* diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizardPage.java index 256eeee4b7f..ceee11d4cd4 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizardPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/AbstractFileCreationWizardPage.java @@ -8,9 +8,13 @@ * Contributors: * QNX Software Systems - initial API and implementation * IBM Corporation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.filewizard; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -22,21 +26,29 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; +import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.cdt.core.model.CModelException; @@ -53,9 +65,11 @@ import org.eclipse.cdt.internal.corext.util.CModelUtil; import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.preferences.CodeTemplatePreferencePage; import org.eclipse.cdt.internal.ui.viewsupport.IViewPartInputProvider; import org.eclipse.cdt.internal.ui.wizards.NewElementWizardPage; import org.eclipse.cdt.internal.ui.wizards.SourceFolderSelectionDialog; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.ComboDialogField; import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.cdt.internal.ui.wizards.dialogfields.IStringButtonAdapter; @@ -85,19 +99,29 @@ public abstract class AbstractFileCreationWizardPage extends NewElementWizardPag * created. */ private boolean isFirstTime = false; + + private Template[] fTemplates; + + private ComboDialogField fTemplateDialogField; public AbstractFileCreationWizardPage(String name) { super(name); - setDescription(NewFileWizardMessages.getString("AbstractFileCreationWizardPage.description")); //$NON-NLS-1$ + setDescription(NewFileWizardMessages.AbstractFileCreationWizardPage_description); fWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); SourceFolderFieldAdapter sourceFolderAdapter = new SourceFolderFieldAdapter(); fSourceFolderDialogField = new StringButtonDialogField(sourceFolderAdapter); fSourceFolderDialogField.setDialogFieldListener(sourceFolderAdapter); - fSourceFolderDialogField.setLabelText(NewFileWizardMessages.getString("AbstractFileCreationWizardPage.sourceFolder.label")); //$NON-NLS-1$ - fSourceFolderDialogField.setButtonLabel(NewFileWizardMessages.getString("AbstractFileCreationWizardPage.sourceFolder.button")); //$NON-NLS-1$ + fSourceFolderDialogField.setLabelText(NewFileWizardMessages.AbstractFileCreationWizardPage_sourceFolder_label); + fSourceFolderDialogField.setButtonLabel(NewFileWizardMessages.AbstractFileCreationWizardPage_sourceFolder_button); + + fTemplates= getApplicableTemplates(); + if (fTemplates != null && fTemplates.length > 0) { + fTemplateDialogField= new ComboDialogField(SWT.NONE); + fTemplateDialogField.setLabelText(NewFileWizardMessages.AbstractFileCreationWizardPage_template_label); + } fSourceFolderStatus = STATUS_OK; fNewFileStatus = STATUS_OK; @@ -109,7 +133,7 @@ public abstract class AbstractFileCreationWizardPage extends NewElementWizardPag // -------- UI Creation --------- - public void createControl(Composite parent) { + public void createControl(Composite parent) { initializeDialogUnits(parent); Composite composite = new Composite(parent, SWT.NONE); @@ -124,7 +148,9 @@ public abstract class AbstractFileCreationWizardPage extends NewElementWizardPag createSourceFolderControls(composite, nColumns); createFileControls(composite, nColumns); - + + createTemplateControls(composite, nColumns); + composite.layout(); setErrorMessage(null); @@ -167,7 +193,82 @@ public abstract class AbstractFileCreationWizardPage extends NewElementWizardPag * @param nColumns number of columns to span */ protected abstract void createFileControls(Composite parent, int nColumns); - + + /** + * Creates the controls for the file template field. Expects a GridLayout with at + * least 3 columns. + * + * @param parent the parent composite + * @param columns number of columns to span + */ + protected void createTemplateControls(Composite parent, int columns) { + if (fTemplateDialogField != null) { + fTemplateDialogField.doFillIntoGrid(parent, columns - 1); + Button configureButton= new Button(parent, SWT.PUSH); + configureButton.setText(NewFileWizardMessages.AbstractFileCreationWizardPage_configure_label); + configureButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + editTemplates(); + } + }); + Combo comboControl= fTemplateDialogField.getComboControl(null); + LayoutUtil.setWidthHint(comboControl, getMaxFieldWidth()); + } + } + + protected void editTemplates() { + String prefPageId= CodeTemplatePreferencePage.PREF_ID; + Map data= null; + String templateName= null; + Template template= getSelectedTemplate(); + if (template != null) { + templateName= template.getName(); + } + if (templateName != null) { + data= new HashMap(); + data.put(CodeTemplatePreferencePage.DATA_SELECT_TEMPLATE, templateName); + } + PreferenceDialog dialog= PreferencesUtil.createPreferenceDialogOn(getShell(), prefPageId, new String[] { prefPageId }, data); + if (dialog.open() == Window.OK) { + updateTemplates(); + } + } + + protected void updateTemplates() { + Template selected= getSelectedTemplate(); + fTemplates= getApplicableTemplates(); + int idx= 1; + String[] names= new String[fTemplates.length + 1]; + for (int i = 0; i < fTemplates.length; i++) { + names[i + 1]= fTemplates[i].getName(); + if (selected != null && selected.getName().equals(names[i + 1])) { + idx= i; + } + } + names[0]= NewFileWizardMessages.AbstractFileCreationWizardPage_noTemplate; + fTemplateDialogField.setItems(names); + fTemplateDialogField.selectItem(idx + 1); + } + + /** + * Configure the set of selectable templates. + * @return the set of templates + */ + protected abstract Template[] getApplicableTemplates(); + + /** + * @return the selected template or null if none + */ + protected Template getSelectedTemplate() { + if (fTemplateDialogField != null) { + int index= fTemplateDialogField.getSelectionIndex() - 1; + if (index >= 0 && index < fTemplates.length) { + return fTemplates[index]; + } + } + return null; + } + /** * The wizard owning this page is responsible for calling this method with the * current selection. The selection is used to initialize the fields of the wizard @@ -255,6 +356,7 @@ public abstract class AbstractFileCreationWizardPage extends NewElementWizardPag */ protected void initFields(ICElement elem) { initSourceFolder(elem); + updateTemplates(); handleFieldChanged(ALL_FIELDS); } @@ -376,7 +478,7 @@ public abstract class AbstractFileCreationWizardPage extends NewElementWizardPag IPath folderPath = getSourceFolderFullPath(); if (folderPath == null) { - status.setError(NewFileWizardMessages.getString("AbstractFileCreationWizardPage.error.EnterSourceFolderName")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.AbstractFileCreationWizardPage_error_EnterSourceFolderName); return status; } @@ -386,27 +488,27 @@ public abstract class AbstractFileCreationWizardPage extends NewElementWizardPag if (resType == IResource.PROJECT || resType == IResource.FOLDER) { IProject proj = res.getProject(); if (!proj.isOpen()) { - status.setError(NewFileWizardMessages.getFormattedString("AbstractFileCreationWizardPage.error.NotAFolder", folderPath)); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.AbstractFileCreationWizardPage_error_NotAFolder, folderPath)); return status; } if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { if (resType == IResource.PROJECT) { - status.setError(NewFileWizardMessages.getString("AbstractFileCreationWizardPage.warning.NotACProject")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.AbstractFileCreationWizardPage_warning_NotACProject); return status; } - status.setWarning(NewFileWizardMessages.getString("AbstractFileCreationWizardPage.warning.NotInACProject")); //$NON-NLS-1$ + status.setWarning(NewFileWizardMessages.AbstractFileCreationWizardPage_warning_NotInACProject); } ICElement e = CoreModel.getDefault().create(res.getFullPath()); if (CModelUtil.getSourceFolder(e) == null) { - status.setError(NewFileWizardMessages.getFormattedString("AbstractFileCreationWizardPage.error.NotASourceFolder", folderPath)); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.AbstractFileCreationWizardPage_error_NotASourceFolder, folderPath)); return status; } } else { - status.setError(NewFileWizardMessages.getFormattedString("AbstractFileCreationWizardPage.error.NotAFolder", folderPath)); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.AbstractFileCreationWizardPage_error_NotAFolder, folderPath)); return status; } } else { - status.setError(NewFileWizardMessages.getFormattedString("AbstractFileCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.AbstractFileCreationWizardPage_error_FolderDoesNotExist, folderPath)); return status; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileFromTemplateWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileFromTemplateWizard.java new file mode 100644 index 00000000000..c45b95e9c60 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileFromTemplateWizard.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.wizards.filewizard; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.dialogs.WizardNewFileCreationPage; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; + +import org.eclipse.cdt.internal.ui.CPluginImages; + +/** + * A generic new file wizard with support for file templates. + * Based on {@link org.eclipse.ui.wizards.newresource.BasicNewFileResourceWizard BasicNewFileResourceWizard}. + * + * @since 5.0 + */ +public class NewFileFromTemplateWizard extends BasicNewResourceWizard { + private WizardNewFileCreationPage mainPage; + + /** + * Creates a wizard for creating a new file resource in the workspace. + */ + public NewFileFromTemplateWizard() { + super(); + } + + /* + * Method declared on IWizard. + */ + public void addPages() { + super.addPages(); + mainPage = new WizardNewFileFromTemplateCreationPage("newFilePage1", getSelection());//$NON-NLS-1$ + mainPage.setTitle(NewFileWizardMessages.NewFileFromTemplateWizard_pageTitle); + mainPage.setDescription(NewFileWizardMessages.NewFileFromTemplateWizard_description); + addPage(mainPage); + } + + /* + * Method declared on IWorkbenchWizard. + */ + public void init(IWorkbench workbench, IStructuredSelection currentSelection) { + super.init(workbench, currentSelection); + setWindowTitle(NewFileWizardMessages.NewFileFromTemplateWizard_shellTitle); + setNeedsProgressMonitor(true); + } + + /* + * Method declared on BasicNewResourceWizard. + */ + protected void initializeDefaultPageImageDescriptor() { + ImageDescriptor desc = CPluginImages.DESC_WIZBAN_NEW_FILE; + setDefaultPageImageDescriptor(desc); + } + + /* + * Method declared on IWizard. + */ + public boolean performFinish() { + IFile file = mainPage.createNewFile(); + if (file == null) { + return false; + } + + selectAndReveal(file); + + // Open editor on new file. + IWorkbenchWindow dw = getWorkbench().getActiveWorkbenchWindow(); + try { + if (dw != null) { + IWorkbenchPage page = dw.getActivePage(); + if (page != null) { + IDE.openEditor(page, file, true); + } + } + } catch (PartInitException e) { + openError(getShell(), NewFileWizardMessages.NewFileFromTemplateWizard_errorMessage, e.getMessage(), e); + } + + return true; + } + + /** + * Open an error style dialog for PartInitException by + * including any extra information from the nested + * CoreException if present. + */ + public static void openError(Shell parent, String title, String message, + PartInitException exception) { + // Check for a nested CoreException + CoreException nestedException = null; + IStatus status = exception.getStatus(); + if (status != null && status.getException() instanceof CoreException) { + nestedException = (CoreException) status.getException(); + } + + if (nestedException != null) { + // Open an error dialog and include the extra + // status information from the nested CoreException + ErrorDialog.openError(parent, title, message, nestedException + .getStatus()); + } else { + // Open a regular error dialog since there is no + // extra information to display + MessageDialog.openError(parent, title, message); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.java index 34881859df8..06ff79e7fc6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2006 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,54 +7,75 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.filewizard; +import org.eclipse.osgi.util.NLS; -import java.text.MessageFormat; -import java.util.MissingResourceException; -import java.util.ResourceBundle; +public final class NewFileWizardMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.wizards.filewizard.NewFileWizardMessages";//$NON-NLS-1$ -public class NewFileWizardMessages { - - private static final String RESOURCE_BUNDLE= NewFileWizardMessages.class.getName(); - private static ResourceBundle fgResourceBundle; - static { - try { - fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE); - } catch (MissingResourceException x) { - fgResourceBundle = null; - } - } - private NewFileWizardMessages() { + // Do not instantiate } - - public static String getString(String key) { - try { - return fgResourceBundle.getString(key); - } catch (MissingResourceException e) { - return '!' + key + '!'; - } catch (NullPointerException e) { - return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$ - } - } + + public static String AbstractFileCreationWizard_title; + public static String AbstractFileCreationWizardPage_description; + public static String AbstractFileCreationWizardPage_error_SelectedProjectError; + public static String AbstractFileCreationWizardPage_error_DefaultSourceFolderError; + public static String AbstractFileCreationWizardPage_error_NotAvailableForNonCProjects; + public static String AbstractFileCreationWizardPage_sourceFolder_label; + public static String AbstractFileCreationWizardPage_sourceFolder_button; + public static String AbstractFileCreationWizardPage_ChooseSourceFolderDialog_title; + public static String AbstractFileCreationWizardPage_ChooseSourceFolderDialog_description; + public static String AbstractFileCreationWizardPage_error_EnterSourceFolderName; + public static String AbstractFileCreationWizardPage_error_NotAFolder; + public static String AbstractFileCreationWizardPage_error_NotASourceFolder; + public static String AbstractFileCreationWizardPage_error_ProjectClosed; + public static String AbstractFileCreationWizardPage_error_FolderDoesNotExist; + public static String AbstractFileCreationWizardPage_template_label; + public static String AbstractFileCreationWizardPage_configure_label; + public static String AbstractFileCreationWizardPage_noTemplate; + public static String AbstractFileCreationWizardPage_warning_NotACProject; + public static String AbstractFileCreationWizardPage_warning_NotInACProject; + public static String NewHeaderFileCreationWizard_title; + public static String NewSourceFileCreationWizard_title; + public static String NewHeaderFileCreationWizardPage_title; + public static String NewHeaderFileCreationWizardPage_description; + public static String NewHeaderFileCreationWizardPage_headerFile_label; + public static String NewHeaderFileCreationWizardPage_error_EnterFileName; + public static String NewHeaderFileCreationWizardPage_error_FileNotInSourceFolder; + public static String NewHeaderFileCreationWizardPage_error_FileExists; + public static String NewHeaderFileCreationWizardPage_error_MatchingFolderExists; + public static String NewHeaderFileCreationWizardPage_error_MatchingResourceExists; + public static String NewHeaderFileCreationWizardPage_error_FolderDoesNotExist; + public static String NewHeaderFileCreationWizardPage_warning_FileNameDiscouraged; + public static String NewHeaderFileCreationWizardPage_error_InvalidFileName; + public static String NewSourceFileCreationWizardPage_title; + public static String NewSourceFileCreationWizardPage_description; + public static String NewSourceFileCreationWizardPage_sourceFile_label; + public static String NewSourceFileCreationWizardPage_error_EnterFileName; + public static String NewSourceFileCreationWizardPage_error_FileNotInSourceFolder; + public static String NewSourceFileCreationWizardPage_error_FileExists; + public static String NewSourceFileCreationWizardPage_error_MatchingFolderExists; + public static String NewSourceFileCreationWizardPage_error_MatchingResourceExists; + public static String NewSourceFileCreationWizardPage_error_FolderDoesNotExist; + public static String NewSourceFileCreationWizardPage_warning_FileNameDiscouraged; + public static String NewSourceFileCreationWizardPage_error_InvalidFileName; + public static String NewSourceFileGenerator_createFile_task; + + public static String NewFileFromTemplateWizard_pageTitle; + public static String NewFileFromTemplateWizard_description; + public static String NewFileFromTemplateWizard_shellTitle; + public static String NewFileFromTemplateWizard_errorMessage; - /** - * Gets a string from the resource bundle and formats it with the argument - * - * @param key the string used to get the bundle value, must not be null - */ - public static String getFormattedString(String key, Object arg) { - return MessageFormat.format(getString(key), new Object[] { arg }); - } + public static String WizardNewFileFromTemplateCreationPage_configure_label; + public static String WizardNewFileFromTemplateCreationPage_noTemplate_name; + public static String WizardNewFileFromTemplateCreationPage_useTemplate_label; - /** - * Gets a string from the resource bundle and formats it with arguments - */ - public static String getFormattedString(String key, Object[] args) { - return MessageFormat.format(getString(key), args); + static { + NLS.initializeMessages(BUNDLE_NAME, NewFileWizardMessages.class); } - -} +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.properties index 27011dd88bf..a6db5a67e8b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewFileWizardMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2004, 2006 QNX Software Systems and others. +# Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,60 +7,73 @@ # # Contributors: # QNX Software Systems - Initial API and implementation +# Anton Leherbauer (Wind River Systems) ############################################################################### -# ------- AbstractFileCreationWizard ------- -AbstractFileCreationWizard.title= New File +# ------- AbstractFileCreationWizard ------- +AbstractFileCreationWizard_title= New File # ----------- AbstractFileCreationWizardPage ------------- -AbstractFileCreationWizardPage.error.SelectedProjectError= Error in determining the selected project. -AbstractFileCreationWizardPage.error.DefaultSourceFolderError= Error in determining the default source folder. -AbstractFileCreationWizardPage.error.NotAvailableForNonCProjects= The wizard is not available for non C/C++ projects. -AbstractFileCreationWizardPage.sourceFolder.label=Source &Folder: -AbstractFileCreationWizardPage.sourceFolder.button=Br&owse... -AbstractFileCreationWizardPage.ChooseSourceFolderDialog.title=Folder Selection -AbstractFileCreationWizardPage.ChooseSourceFolderDialog.description=&Choose a source folder: -AbstractFileCreationWizardPage.error.EnterSourceFolderName=Source folder name is empty. -AbstractFileCreationWizardPage.error.NotAFolder=''{0}'' is not a project or folder. -AbstractFileCreationWizardPage.error.NotASourceFolder=Folder ''{0}'' is not a source folder. -AbstractFileCreationWizardPage.error.ProjectClosed=Project ''{0}'' must be accessible. -AbstractFileCreationWizardPage.error.FolderDoesNotExist=Folder ''{0}'' does not exist. -AbstractFileCreationWizardPage.warning.NotACProject=Folder is not a C/C++ project. -AbstractFileCreationWizardPage.warning.NotInACProject=Folder is not in a C/C++ project. +AbstractFileCreationWizardPage_description=Creates a new file +AbstractFileCreationWizardPage_error_SelectedProjectError= Error in determining the selected project. +AbstractFileCreationWizardPage_error_DefaultSourceFolderError= Error in determining the default source folder. +AbstractFileCreationWizardPage_error_NotAvailableForNonCProjects= The wizard is not available for non C/C++ projects. +AbstractFileCreationWizardPage_sourceFolder_label=Source &Folder: +AbstractFileCreationWizardPage_sourceFolder_button=Br&owse... +AbstractFileCreationWizardPage_ChooseSourceFolderDialog_title=Folder Selection +AbstractFileCreationWizardPage_ChooseSourceFolderDialog_description=&Choose a source folder: +AbstractFileCreationWizardPage_error_EnterSourceFolderName=Source folder name is empty. +AbstractFileCreationWizardPage_error_NotAFolder=''{0}'' is not a project or folder. +AbstractFileCreationWizardPage_error_NotASourceFolder=Folder ''{0}'' is not a source folder. +AbstractFileCreationWizardPage_error_ProjectClosed=Project ''{0}'' must be accessible. +AbstractFileCreationWizardPage_error_FolderDoesNotExist=Folder ''{0}'' does not exist. +AbstractFileCreationWizardPage_template_label=Template: +AbstractFileCreationWizardPage_configure_label=Configure... +AbstractFileCreationWizardPage_noTemplate= +AbstractFileCreationWizardPage_warning_NotACProject=Folder is not a C/C++ project. +AbstractFileCreationWizardPage_warning_NotInACProject=Folder is not in a C/C++ project. -# ------- NewHeaderFileCreationWizard ------- -NewHeaderFileCreationWizard.title= New Header File +# ------- NewHeaderFileCreationWizard ------- +NewHeaderFileCreationWizard_title= New Header File -# ------- NewSourceFileCreationWizard ------- -NewSourceFileCreationWizard.title= New Source File +# ------- NewSourceFileCreationWizard ------- +NewSourceFileCreationWizard_title= New Source File # ----------- NewHeaderFileCreationWizardPage ------------- -NewHeaderFileCreationWizardPage.title= New Header File -NewHeaderFileCreationWizardPage.description= Create a new header file. -NewHeaderFileCreationWizardPage.headerFile.label= Header File: -NewHeaderFileCreationWizardPage.error.EnterFileName=File name is empty. -NewHeaderFileCreationWizardPage.error.FileNotInSourceFolder=File must be inside source folder. -NewHeaderFileCreationWizardPage.error.FileExists=File already exists. -NewHeaderFileCreationWizardPage.error.MatchingFolderExists=A folder with the same name already exists. -NewHeaderFileCreationWizardPage.error.MatchingResourceExists=A resource with the same name already exists. -NewHeaderFileCreationWizardPage.error.FolderDoesNotExist=Folder ''{0}'' does not exist. -NewHeaderFileCreationWizardPage.warning.FileNameDiscouraged=File name is discouraged. {0}. -NewHeaderFileCreationWizardPage.error.InvalidFileName=File name is not valid. {0}. +NewHeaderFileCreationWizardPage_title= New Header File +NewHeaderFileCreationWizardPage_description= Create a new header file. +NewHeaderFileCreationWizardPage_headerFile_label= Header File: +NewHeaderFileCreationWizardPage_error_EnterFileName=File name is empty. +NewHeaderFileCreationWizardPage_error_FileNotInSourceFolder=File must be inside source folder. +NewHeaderFileCreationWizardPage_error_FileExists=File already exists. +NewHeaderFileCreationWizardPage_error_MatchingFolderExists=A folder with the same name already exists. +NewHeaderFileCreationWizardPage_error_MatchingResourceExists=A resource with the same name already exists. +NewHeaderFileCreationWizardPage_error_FolderDoesNotExist=Folder ''{0}'' does not exist. +NewHeaderFileCreationWizardPage_warning_FileNameDiscouraged=File name is discouraged. {0}. +NewHeaderFileCreationWizardPage_error_InvalidFileName=File name is not valid. {0}. # ----------- NewSourceFileCreationWizardPage ------------- -NewSourceFileCreationWizardPage.title= New Source File -NewSourceFileCreationWizardPage.description= Create a new source file. -NewSourceFileCreationWizardPage.sourceFile.label= Source File: -NewSourceFileCreationWizardPage.error.EnterFileName=File name is empty. -NewSourceFileCreationWizardPage.error.FileNotInSourceFolder=File must be inside source folder. -NewSourceFileCreationWizardPage.error.FileExists=File already exists. -NewSourceFileCreationWizardPage.error.MatchingFolderExists=A folder with the same name already exists. -NewSourceFileCreationWizardPage.error.MatchingResourceExists=A resource with the same name already exists. -NewSourceFileCreationWizardPage.error.FolderDoesNotExist=Folder ''{0}'' does not exist. -NewSourceFileCreationWizardPage.warning.FileNameDiscouraged=File name is discouraged. {0}. -NewSourceFileCreationWizardPage.error.InvalidFileName=File name is not valid. {0}. +NewSourceFileCreationWizardPage_title= New Source File +NewSourceFileCreationWizardPage_description= Create a new source file. +NewSourceFileCreationWizardPage_sourceFile_label= Source File: +NewSourceFileCreationWizardPage_error_EnterFileName=File name is empty. +NewSourceFileCreationWizardPage_error_FileNotInSourceFolder=File must be inside source folder. +NewSourceFileCreationWizardPage_error_FileExists=File already exists. +NewSourceFileCreationWizardPage_error_MatchingFolderExists=A folder with the same name already exists. +NewSourceFileCreationWizardPage_error_MatchingResourceExists=A resource with the same name already exists. +NewSourceFileCreationWizardPage_error_FolderDoesNotExist=Folder ''{0}'' does not exist. +NewSourceFileCreationWizardPage_warning_FileNameDiscouraged=File name is discouraged. {0}. +NewSourceFileCreationWizardPage_error_InvalidFileName=File name is not valid. {0}. # ----------- NewSourceFileGenerator ------------- -NewSourceFileGenerator.createFile.task= Creating -NewSourceFileGenerator.createFile.mainTask= Creating file.... -NewSourceFileGenerator.includeGuard.suffix= _H +NewSourceFileGenerator_createFile_task= Creating + +# ----- NewFileFromTemplateWizard ------ +NewFileFromTemplateWizard_pageTitle= File +NewFileFromTemplateWizard_description=Create a new file resource from a template. +NewFileFromTemplateWizard_shellTitle= New File +NewFileFromTemplateWizard_errorMessage= Problems Opening Editor + +WizardNewFileFromTemplateCreationPage_configure_label=Configure... +WizardNewFileFromTemplateCreationPage_noTemplate_name= +WizardNewFileFromTemplateCreationPage_useTemplate_label=Use template: diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java index 7b0dc9b9638..a73d4ecbdaa 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2006 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,12 +7,18 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.filewizard; import org.eclipse.cdt.core.CConventions; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.ui.CodeGeneration; + +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; @@ -26,6 +32,8 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; @@ -35,8 +43,8 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP private StringDialogField fNewFileDialogField; public NewHeaderFileCreationWizardPage() { - super(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.title")); //$NON-NLS-1$ - setDescription(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.description")); //$NON-NLS-1$ + super(NewFileWizardMessages.NewHeaderFileCreationWizardPage_title); + setDescription(NewFileWizardMessages.NewHeaderFileCreationWizardPage_description); fNewFileDialogField = new StringDialogField(); fNewFileDialogField.setDialogFieldListener(new IDialogFieldListener() { @@ -44,7 +52,7 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP handleFieldChanged(NEW_FILE_ID); } }); - fNewFileDialogField.setLabelText(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.headerFile.label")); //$NON-NLS-1$ + fNewFileDialogField.setLabelText(NewFileWizardMessages.NewHeaderFileCreationWizardPage_headerFile_label); } /** @@ -87,13 +95,13 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP IPath filePath = getFileFullPath(); if (filePath == null) { - status.setError(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.error.EnterFileName")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewHeaderFileCreationWizardPage_error_EnterFileName); return status; } IPath sourceFolderPath = getSourceFolderFullPath(); if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(filePath)) { - status.setError(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.error.FileNotInSourceFolder")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewHeaderFileCreationWizardPage_error_FileNotInSourceFolder); return status; } @@ -101,11 +109,11 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP IResource file = getWorkspaceRoot().findMember(filePath); if (file != null && file.exists()) { if (file.getType() == IResource.FILE) { - status.setError(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.error.FileExists")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewHeaderFileCreationWizardPage_error_FileExists); } else if (file.getType() == IResource.FOLDER) { - status.setError(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.error.MatchingFolderExists")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewHeaderFileCreationWizardPage_error_MatchingFolderExists); } else { - status.setError(NewFileWizardMessages.getString("NewHeaderFileCreationWizardPage.error.MatchingResourceExists")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewHeaderFileCreationWizardPage_error_MatchingResourceExists); } return status; } @@ -114,16 +122,16 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP IPath folderPath = filePath.removeLastSegments(1).makeRelative(); IResource folder = getWorkspaceRoot().findMember(folderPath); if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { - status.setError(NewFileWizardMessages.getFormattedString("NewHeaderFileCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.NewHeaderFileCreationWizardPage_error_FolderDoesNotExist, folderPath)); return status; } IStatus convStatus = CConventions.validateHeaderFileName(getCurrentProject(), filePath.lastSegment()); if (convStatus.getSeverity() == IStatus.ERROR) { - status.setError(NewFileWizardMessages.getFormattedString("NewHeaderFileCreationWizardPage.error.InvalidFileName", convStatus.getMessage())); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.NewHeaderFileCreationWizardPage_error_InvalidFileName, convStatus.getMessage())); return status; } else if (convStatus.getSeverity() == IStatus.WARNING) { - status.setWarning(NewFileWizardMessages.getFormattedString("NewHeaderFileCreationWizardPage.warning.FileNameDiscouraged", convStatus.getMessage())); //$NON-NLS-1$ + status.setWarning(NLS.bind(NewFileWizardMessages.NewHeaderFileCreationWizardPage_warning_FileNameDiscouraged, convStatus.getMessage())); } return status; } @@ -138,6 +146,12 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP IFile newFile = NewSourceFileGenerator.createHeaderFile(filePath, true, monitor); if (newFile != null) { fNewFileTU = (ITranslationUnit) CoreModel.getDefault().create(newFile); + if (fNewFileTU != null) { + String lineDelimiter= StubUtility.getLineDelimiterUsed(fNewFileTU); + String content= CodeGeneration.getHeaderFileContent(getSelectedTemplate(), fNewFileTU, null, null, lineDelimiter); + fNewFileTU.getBuffer().setContents(content.toCharArray()); + fNewFileTU.save(monitor, true); + } } } finally { monitor.done(); @@ -151,4 +165,12 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP public ITranslationUnit getCreatedFileTU() { return fNewFileTU; } + + /* + * @see org.eclipse.cdt.internal.ui.wizards.filewizard.AbstractFileCreationWizardPage#getApplicableTemplates() + */ + protected Template[] getApplicableTemplates() { + return StubUtility.getFileTemplatesForContentTypes( + new String[] { CCorePlugin.CONTENT_TYPE_CXXHEADER, CCorePlugin.CONTENT_TYPE_CHEADER }, null); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileCreationWizardPage.java index 41d29f6a635..70eeec8d1e0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileCreationWizardPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileCreationWizardPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2006 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,17 +7,10 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.filewizard; -import org.eclipse.cdt.core.CConventions; -import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; @@ -26,16 +19,32 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; +import org.eclipse.cdt.core.CConventions; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.ui.CodeGeneration; + +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; + public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardPage { private ITranslationUnit fNewFileTU = null; private StringDialogField fNewFileDialogField; public NewSourceFileCreationWizardPage() { - super(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.title")); //$NON-NLS-1$ - setDescription(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.description")); //$NON-NLS-1$ + super(NewFileWizardMessages.NewSourceFileCreationWizardPage_title); + setDescription(NewFileWizardMessages.NewSourceFileCreationWizardPage_description); fNewFileDialogField = new StringDialogField(); fNewFileDialogField.setDialogFieldListener(new IDialogFieldListener() { @@ -43,12 +52,12 @@ public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardP handleFieldChanged(NEW_FILE_ID); } }); - fNewFileDialogField.setLabelText(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.sourceFile.label")); //$NON-NLS-1$ + fNewFileDialogField.setLabelText(NewFileWizardMessages.NewSourceFileCreationWizardPage_sourceFile_label); } /** * Sets the focus on the starting input field. - */ + */ protected void setFocus() { fNewFileDialogField.setFocus(); } @@ -86,13 +95,13 @@ public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardP IPath filePath = getFileFullPath(); if (filePath == null) { - status.setError(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.error.EnterFileName")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_EnterFileName); return status; } IPath sourceFolderPath = getSourceFolderFullPath(); if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(filePath)) { - status.setError(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.error.FileNotInSourceFolder")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_FileNotInSourceFolder); return status; } @@ -100,11 +109,11 @@ public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardP IResource file = getWorkspaceRoot().findMember(filePath); if (file != null && file.exists()) { if (file.getType() == IResource.FILE) { - status.setError(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.error.FileExists")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_FileExists); } else if (file.getType() == IResource.FOLDER) { - status.setError(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.error.MatchingFolderExists")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_MatchingFolderExists); } else { - status.setError(NewFileWizardMessages.getString("NewSourceFileCreationWizardPage.error.MatchingResourceExists")); //$NON-NLS-1$ + status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_MatchingResourceExists); } return status; } @@ -113,16 +122,16 @@ public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardP IPath folderPath = filePath.removeLastSegments(1).makeRelative(); IResource folder = getWorkspaceRoot().findMember(folderPath); if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { - status.setError(NewFileWizardMessages.getFormattedString("NewSourceFileCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_FolderDoesNotExist, folderPath)); return status; } IStatus convStatus = CConventions.validateSourceFileName(getCurrentProject(), filePath.lastSegment()); if (convStatus.getSeverity() == IStatus.ERROR) { - status.setError(NewFileWizardMessages.getFormattedString("NewSourceFileCreationWizardPage.error.InvalidFileName", convStatus.getMessage())); //$NON-NLS-1$ + status.setError(NLS.bind(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_InvalidFileName, convStatus.getMessage())); return status; } else if (convStatus.getSeverity() == IStatus.WARNING) { - status.setWarning(NewFileWizardMessages.getFormattedString("NewSourceFileCreationWizardPage.warning.FileNameDiscouraged", convStatus.getMessage())); //$NON-NLS-1$ + status.setWarning(NLS.bind(NewFileWizardMessages.NewSourceFileCreationWizardPage_warning_FileNameDiscouraged, convStatus.getMessage())); } return status; } @@ -137,6 +146,14 @@ public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardP IFile newFile = NewSourceFileGenerator.createSourceFile(filePath, true, monitor); if (newFile != null) { fNewFileTU = (ITranslationUnit) CoreModel.getDefault().create(newFile); + if (fNewFileTU != null) { + String lineDelimiter= StubUtility.getLineDelimiterUsed(fNewFileTU); + String content= CodeGeneration.getBodyFileContent(getSelectedTemplate(), fNewFileTU, null, null, lineDelimiter); + if (content != null) { + fNewFileTU.getBuffer().setContents(content.toCharArray()); + fNewFileTU.save(monitor, true); + } + } } } finally { monitor.done(); @@ -150,4 +167,12 @@ public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardP public ITranslationUnit getCreatedFileTU() { return fNewFileTU; } + + /* + * @see org.eclipse.cdt.internal.ui.wizards.filewizard.AbstractFileCreationWizardPage#getApplicableTemplates() + */ + protected Template[] getApplicableTemplates() { + return StubUtility.getFileTemplatesForContentTypes( + new String[] { CCorePlugin.CONTENT_TYPE_CXXSOURCE, CCorePlugin.CONTENT_TYPE_CSOURCE }, null); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java index b5056c5b17c..fc60ace62d0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 QNX Software Systems and others. + * Copyright (c) 2004, 2007 QNX Software Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.filewizard; @@ -30,14 +31,7 @@ public class NewSourceFileGenerator { //TODO these should all be configurable in prefs private static final String HEADER_EXT = ".h"; //$NON-NLS-1$ private static final String SOURCE_EXT = ".cpp"; //$NON-NLS-1$ - private static boolean fUseIncludeGuard = true; - private static final String fLineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - public static String getLineDelimiter() { - //TODO line delimiter part of code template prefs? - return fLineDelimiter; - } - public static String generateHeaderFileNameFromClass(String className) { //TODO eventually make this a prefs option - filename pattern return className + HEADER_EXT; @@ -49,55 +43,14 @@ public class NewSourceFileGenerator { } public static IFile createHeaderFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException { - //TODO should use code templates - ByteArrayInputStream stream; - if (fUseIncludeGuard) { - String includeGuardSymbol = generateIncludeGuardSymbol(filePath); - StringBuffer buf = new StringBuffer(); - buf.append("#ifndef "); //$NON-NLS-1$ - buf.append(includeGuardSymbol); - buf.append(fLineDelimiter); - buf.append("#define "); //$NON-NLS-1$ - buf.append(includeGuardSymbol); - buf.append(fLineDelimiter); - buf.append(fLineDelimiter); - buf.append("#endif /*"); //$NON-NLS-1$ - buf.append(includeGuardSymbol); - buf.append("*/"); //$NON-NLS-1$ - buf.append(fLineDelimiter); - stream = new ByteArrayInputStream(buf.toString().getBytes()); - } else { - stream = new ByteArrayInputStream(new byte[0]); - } - return createNewFile(filePath, stream, force, monitor); + return createEmptyFile(filePath, force, monitor); } - private static String generateIncludeGuardSymbol(IPath headerPath) { - //TODO eventually make this a prefs option - filename pattern or - // unique id/incremental value - String name = headerPath.lastSegment(); - if (name != null) { - //convert to upper case and remove invalid characters - //eg convert foo.h --> _FOO_H_ - StringBuffer buf = new StringBuffer(); - // Do not do this, leading underscores are discourage by the std. - //buf.append('_'); - for (int i = 0; i < name.length(); ++i) { - char ch = name.charAt(i); - if (Character.isLetterOrDigit(ch)) { - buf.append(Character.toUpperCase(ch)); - } else if (ch == '.' || ch == '_') { - buf.append('_'); - } - } - buf.append('_'); - return buf.toString(); - } - return null; + public static IFile createSourceFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException { + return createEmptyFile(filePath, force, monitor); } - public static IFile createSourceFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException { - //TODO should use code templates + public static IFile createEmptyFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException { ByteArrayInputStream stream = new ByteArrayInputStream(new byte[0]); return createNewFile(filePath, stream, force, monitor); } @@ -106,7 +59,7 @@ public class NewSourceFileGenerator { int totalWork = 100; int createFileWork = totalWork; - monitor.beginTask(NewFileWizardMessages.getString("NewSourceFileGenerator.createFile.task"), totalWork); //$NON-NLS-1$ + monitor.beginTask(NewFileWizardMessages.NewSourceFileGenerator_createFile_task, totalWork); IWorkspaceRoot root = CUIPlugin.getWorkspace().getRoot(); IFile newFile = root.getFileForLocation(newFilePath); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/WizardNewFileFromTemplateCreationPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/WizardNewFileFromTemplateCreationPage.java new file mode 100644 index 00000000000..27fbd86d23e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/WizardNewFileFromTemplateCreationPage.java @@ -0,0 +1,272 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. 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: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.wizards.filewizard; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.core.runtime.content.IContentTypeMatcher; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.dialogs.WizardNewFileCreationPage; + +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; +import org.eclipse.cdt.internal.corext.template.c.FileTemplateContextType; + +import org.eclipse.cdt.internal.ui.preferences.CodeTemplatePreferencePage; + +/** + * A new file creation wizard page with support for templates. + * + * @since 5.0 + */ +public class WizardNewFileFromTemplateCreationPage extends WizardNewFileCreationPage { + + private Combo fTemplatesCombo; + private Template[] fTemplates; + protected boolean fUseTemplate= true; + + /** + * Create a new 'file from template' page. + * + * @param pageName + * @param selection + */ + public WizardNewFileFromTemplateCreationPage(String pageName, IStructuredSelection selection) { + super(pageName, selection); + } + + /* + * @see org.eclipse.ui.dialogs.WizardNewFileCreationPage#createAdvancedControls(org.eclipse.swt.widgets.Composite) + */ + protected void createAdvancedControls(Composite parent) { + Composite groupComposite= new Composite(parent,SWT.NONE); + groupComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + GridLayout layout= new GridLayout(); + layout.numColumns= 3; + groupComposite.setLayout(layout); + + final Button useTemplateButton= new Button(groupComposite, SWT.CHECK); + + useTemplateButton.setText(NewFileWizardMessages.WizardNewFileFromTemplateCreationPage_useTemplate_label); + useTemplateButton.setSelection(fUseTemplate); + SelectionListener useTemplateListener= new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + fUseTemplate= useTemplateButton.getSelection(); + fTemplatesCombo.setEnabled(fUseTemplate); + } + }; + useTemplateButton.addSelectionListener(useTemplateListener); + + fTemplatesCombo= new Combo(groupComposite, SWT.READ_ONLY); + fTemplatesCombo.setEnabled(fUseTemplate); + fTemplatesCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + final Button configureButton= new Button(groupComposite, SWT.PUSH); + configureButton.setText(NewFileWizardMessages.WizardNewFileFromTemplateCreationPage_configure_label); + + SelectionListener changeTemplateListener= new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + editTemplates(); + } + }; + configureButton.addSelectionListener(changeTemplateListener); + updateTemplates(); + + super.createAdvancedControls(parent); + } + + protected void editTemplates() { + String prefPageId= CodeTemplatePreferencePage.PREF_ID; + Map data= null; + String templateName= null; + Template template= getSelectedTemplate(); + if (template != null) { + templateName= template.getName(); + } + if (templateName != null) { + data= new HashMap(); + data.put(CodeTemplatePreferencePage.DATA_SELECT_TEMPLATE, templateName); + } + PreferenceDialog dialog= PreferencesUtil.createPreferenceDialogOn(getShell(), prefPageId, new String[] { prefPageId }, data); + if (dialog.open() == Window.OK) { + updateTemplates(); + } + } + + /* + * @see org.eclipse.ui.dialogs.WizardNewFileCreationPage#getInitialContents() + */ + protected InputStream getInitialContents() { + Template template= getSelectedTemplate(); + if (fUseTemplate && template != null) { + IFile fileHandle= createFileHandle(getContainerFullPath().append(getResourceName())); + String lineDelimiter= StubUtility.getLineDelimiterPreference(getContainterProject()); + try { + String content= StubUtility.getFileContent(template, fileHandle, lineDelimiter); + if (content != null) { + try { + String charset= fileHandle.getParent().getDefaultCharset(); + return new ByteArrayInputStream(content.getBytes(charset)); + } catch (UnsupportedEncodingException exc) { + return new ByteArrayInputStream(content.getBytes()); + } + } + } catch (CoreException exc) { + } + } + return super.getInitialContents(); + } + + /* + * @see org.eclipse.ui.dialogs.WizardNewFileCreationPage#handleEvent(org.eclipse.swt.widgets.Event) + */ + public void handleEvent(Event event) { + updateTemplates(); + super.handleEvent(event); + } + + protected void updateTemplates() { + Template selected= getSelectedTemplate(); + boolean isDefaultSelected= (selected != null && fTemplates.length == 1) || (fTemplatesCombo != null && fTemplatesCombo.getSelectionIndex() == 0); + fTemplates= getApplicableTemplates(); + int idx= 0; + String[] names= new String[fTemplates.length]; + for (int i = 0; i < names.length; i++) { + names[i]= fTemplates[i].getName(); + if (!isDefaultSelected && selected != null && selected.getName().equals(names[i])) { + idx= i; + } + } + if (fTemplatesCombo != null) { + if (names.length == 0) { + names= new String[] { NewFileWizardMessages.WizardNewFileFromTemplateCreationPage_noTemplate_name }; + } + fTemplatesCombo.setItems(names); + fTemplatesCombo.select(idx); + } + } + + /** + * @return the selected template or null if none + */ + protected Template getSelectedTemplate() { + if (fTemplates != null) { + int index= 0; + if (fTemplatesCombo != null) { + index= fTemplatesCombo.getSelectionIndex(); + if (index < 0) { + index= 0; + } + } + if (index < fTemplates.length) { + return fTemplates[index]; + } + } + return null; + } + + private String getResourceName() { + String fileName= getFileName(); + String fileExtension= getFileExtension(); + if (fileExtension != null && fileExtension.length() > 0 && !fileName.endsWith('.' + fileExtension)) { + fileName += '.'; + fileName += fileExtension; + } + return fileName; + } + + private IProject getContainterProject() { + IPath containerPath= getContainerFullPath(); + if (containerPath != null) { + return ResourcesPlugin.getWorkspace().getRoot().getProject(containerPath.segment(0)); + } + return null; + } + + /** + * Configure the set of selectable templates. + * @return the set of templates + */ + protected Template[] getApplicableTemplates() { + IProject project= getContainterProject(); + String fileName= getResourceName(); + String[] contentTypes= getAllContentTypeIdsForFileName(project, fileName); + return StubUtility.getFileTemplatesForContentTypes(contentTypes, project); + } + + private static String[] getAllContentTypeIdsForFileName(IProject project, String fileName) { + IContentTypeMatcher matcher; + if (project == null || !project.isAccessible()) { + IContentTypeManager contentTypeMgr= Platform.getContentTypeManager(); + matcher= contentTypeMgr; + } else { + try { + matcher= project.getContentTypeMatcher(); + } catch (CoreException exc) { + IContentTypeManager contentTypeMgr= Platform.getContentTypeManager(); + matcher= contentTypeMgr; + } + } + IContentType[] contentTypes= matcher.findContentTypesFor(fileName); + List result= new ArrayList(contentTypes.length * 2); + for (int i = 0; i < contentTypes.length; i++) { + IContentType contentType = contentTypes[i]; + String id= contentType.getId(); + result.add(id); + } + // add base types + for (int i = 0; i < contentTypes.length; i++) { + IContentType contentType = contentTypes[i].getBaseType(); + while (contentType != null) { + String id= contentType.getId(); + if (result.contains(id)) { + break; + } + result.add(id); + contentType= contentType.getBaseType(); + } + } + if (result.isEmpty()) { + result.add(FileTemplateContextType.CONTENTTYPE_TEXT); + } + return (String[]) result.toArray(new String[result.size()]); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java index 6a217fdd747..72ca8a662d3 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java @@ -70,7 +70,9 @@ import org.eclipse.cdt.core.model.IWorkingCopyProvider; import org.eclipse.cdt.internal.core.model.IBufferFactory; import org.eclipse.cdt.internal.corext.template.c.CContextType; +import org.eclipse.cdt.internal.corext.template.c.CodeTemplateContextType; import org.eclipse.cdt.internal.corext.template.c.CommentContextType; +import org.eclipse.cdt.internal.corext.template.c.FileTemplateContextType; import org.eclipse.cdt.internal.ui.CElementAdapterFactory; import org.eclipse.cdt.internal.ui.ICStatusConstants; @@ -95,8 +97,6 @@ import org.eclipse.cdt.internal.ui.viewsupport.CDTContextActivator; public class CUIPlugin extends AbstractUIPlugin { - private ISharedTextColors fSharedTextColors; - public static final String PLUGIN_ID = "org.eclipse.cdt.ui"; //$NON-NLS-1$ public static final String PLUGIN_CORE_ID = "org.eclipse.cdt.core"; //$NON-NLS-1$ public static final String EDITOR_ID = PLUGIN_ID + ".editor.CEditor"; //$NON-NLS-1$ @@ -118,26 +118,9 @@ public class CUIPlugin extends AbstractUIPlugin { private static CUIPlugin fgCPlugin; private static ResourceBundle fgResourceBundle; - private ImageDescriptorRegistry fImageDescriptorRegistry; - private CEditorTextHoverDescriptor[] fCEditorTextHoverDescriptors; - - /** - * The extension point registry for the org.eclipse.cdt.ui.foldingStructureProviders - * extension point. - */ - private CFoldingStructureProviderRegistry fFoldingStructureProviderRegistry; - - /** - * The combined preference store. - * @since 3.0 - */ - private IPreferenceStore fCombinedPreferenceStore; - - static String SEPARATOR = System.getProperty("file.separator"); //$NON-NLS-1$ private static final String CONTENTASSIST = CUIPlugin.PLUGIN_ID + "/debug/contentassist" ; //$NON-NLS-1$ - /** * The id of the C perspective * (value "org.eclipse.cdt.ui.CPerspective"). @@ -211,6 +194,12 @@ public class CUIPlugin extends AbstractUIPlugin { */ public static final String CVIEWS_SCOPE = "org.eclipse.cdt.ui.cViewScope"; //$NON-NLS-1$ + /** + * The key to store customized code templates. + * @since 5.0 + */ + private static final String CODE_TEMPLATES_KEY= "org.eclipse.cdt.ui.text.custom_code_templates"; //$NON-NLS-1$ + // -------- static methods -------- static { @@ -337,6 +326,23 @@ public class CUIPlugin extends AbstractUIPlugin { // ------ CUIPlugin + + private ISharedTextColors fSharedTextColors; + private ImageDescriptorRegistry fImageDescriptorRegistry; + private CEditorTextHoverDescriptor[] fCEditorTextHoverDescriptors; + + /** + * The extension point registry for the org.eclipse.cdt.ui.foldingStructureProviders + * extension point. + */ + private CFoldingStructureProviderRegistry fFoldingStructureProviderRegistry; + + /** + * The combined preference store. + * @since 3.0 + */ + private IPreferenceStore fCombinedPreferenceStore; + private CoreModel fCoreModel; private CDocumentProvider fDocumentProvider; private ExternalSearchDocumentProvider fExternalDocumentProvider; @@ -367,6 +373,17 @@ public class CUIPlugin extends AbstractUIPlugin { */ private ASTProvider fASTProvider; + /** + * The code template context type registry for the C editor. + * @since 5.0 + */ + private ContextTypeRegistry fCodeTemplateContextTypeRegistry; + + /** + * The code template store for the C editor. + * @since 5.0 + */ + private TemplateStore fCodeTemplateStore; public CUIPlugin() { fgCPlugin = this; @@ -782,10 +799,10 @@ public class CUIPlugin extends AbstractUIPlugin { } /** - * Returns the registry of the extensions to the org.eclipse.jdt.ui.javaFoldingStructureProvider + * Returns the registry of the extensions to the org.eclipse.cdt.ui.foldingStructureProviders * extension point. * - * @return the registry of contributed IJavaFoldingStructureProvider + * @return the registry of contributed ICFoldingStructureProvider * @since 3.0 */ public synchronized CFoldingStructureProviderRegistry getFoldingStructureProviderRegistry() { @@ -827,6 +844,48 @@ public class CUIPlugin extends AbstractUIPlugin { return fTemplateStore; } + /** + * Returns the template context type registry for the code generation + * templates. + * + * @return the template context type registry for the code generation + * templates + * @since 5.0 + */ + public ContextTypeRegistry getCodeTemplateContextRegistry() { + if (fCodeTemplateContextTypeRegistry == null) { + fCodeTemplateContextTypeRegistry= new ContributionContextTypeRegistry(); + + CodeTemplateContextType.registerContextTypes(fCodeTemplateContextTypeRegistry); + FileTemplateContextType.registerContextTypes(fCodeTemplateContextTypeRegistry); + } + + return fCodeTemplateContextTypeRegistry; + } + + /** + * Returns the template store for the code generation templates. + * + * @return the template store for the code generation templates + * @since 5.0 + */ + public TemplateStore getCodeTemplateStore() { + if (fCodeTemplateStore == null) { + IPreferenceStore store= getPreferenceStore(); + fCodeTemplateStore= new ContributionTemplateStore(getCodeTemplateContextRegistry(), store, CODE_TEMPLATES_KEY); + + try { + fCodeTemplateStore.load(); + } catch (IOException e) { + log(e); + } + + fCodeTemplateStore.startListeningForPreferenceChanges(); + } + + return fCodeTemplateStore; + } + /** * Returns the AST provider. * diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java index 8682c3c13f2..744f4d878a1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2006 IBM Corporation and others. + * Copyright (c) 2001, 2007 IBM Corporation 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 @@ -7,17 +7,20 @@ * * Contributors: * Rational Software - initial implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.ui; import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.templates.Template; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.internal.ui.codemanipulation.StubUtility; +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + /** - * Class that offers access to the templates contained in the 'code generation' preference page. + * Class that offers access to the templates contained in the 'Code Templates' preference page. * * @since 2.1 */ @@ -27,8 +30,8 @@ public class CodeGeneration { } /** - * Returns the content for a new compilation unit using the 'new Java file' code template. - * @param tu The translation unit to create the source for. The compilation unit does not need to exist. + * Returns the content for a new header file using the default 'header file' code template. + * @param tu The translation unit to create the source for. The translation unit does not need to exist. * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if * no comment should be added. * @param typeContent The code of the type, including type declaration and body. @@ -37,12 +40,27 @@ public class CodeGeneration { * @throws CoreException */ public static String getHeaderFileContent(ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return StubUtility.getHeaderFileContent(tu, typeComment, typeContent, lineDelimiter); + return StubUtility.getHeaderFileContent(tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); } /** - * Returns the content for a new compilation unit using the 'new Java file' code template. - * @param tu The translation unit to create the source for. The compilation unit does not need to exist. + * Returns the content for a new header file using the default 'header file' code template. + * @param template The file template to use or null for the default template + * @param tu The translation unit to create the source for. The translation unit does not need to exist. + * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if + * no comment should be added. + * @param typeContent The code of the type, including type declaration and body. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + */ + public static String getHeaderFileContent(Template template, ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { + return StubUtility.getHeaderFileContent(template, tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); + } + + /** + * Returns the content for a new translation unit using the 'source file' code template. + * @param tu The translation unit to create the source for. The translation unit does not need to exist. * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if * no comment should be added. * @param typeContent The code of the type, including type declaration and body. @@ -51,12 +69,91 @@ public class CodeGeneration { * @throws CoreException */ public static String getBodyFileContent(ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { - return StubUtility.getBodyFileContent(tu, typeComment, typeContent, lineDelimiter); + return StubUtility.getBodyFileContent(tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); } + /** + * Returns the content for a new translation unit using the 'source file' code template. + * @param template The file template to use or null for the default template + * @param tu The translation unit to create the source for. The translation unit does not need to exist. + * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be null if + * no comment should be added. + * @param typeContent The code of the type, including type declaration and body. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the template is undefined or empty. + * @throws CoreException + */ + public static String getBodyFileContent(Template template, ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException { + return StubUtility.getBodyFileContent(template, tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter); + } + + /** + * Returns the content of the body for a method using the method body template. + * null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param typeName Name of the type to which the method belongs. + * @param methodName Name of the method. + * @param bodyStatement The code to be entered at the place of the variable ${body_statement}. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed body content or null if + * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + */ + public static String getMethodBodyContent(ITranslationUnit tu, String typeName, String methodName, String bodyStatement, String lineDelimiter) throws CoreException { + return StubUtility.getMethodBodyContent(tu.getCProject(), typeName, methodName, bodyStatement, lineDelimiter); + } + + /** + * Returns the content of the body for a constructor using the constructor body template. + * null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param typeName Name of the type to which the constructor belongs. + * @param bodyStatement The code to be entered at the place of the variable ${body_statement}. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed body content or null if + * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + */ + public static String getConstructorBodyContent(ITranslationUnit tu, String typeName, String bodyStatement, String lineDelimiter) throws CoreException { + return StubUtility.getConstructorBodyContent(tu.getCProject(), typeName, bodyStatement, lineDelimiter); + } + + /** + * Returns the content of the body for a destructor using the destructor body template. + * null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param typeName Name of the type to which the constructor belongs. + * @param bodyStatement The code to be entered at the place of the variable ${body_statement}. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed body content or null if + * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + */ + public static String getDestructorBodyContent(ITranslationUnit tu, String typeName, String bodyStatement, String lineDelimiter) throws CoreException { + return StubUtility.getDestructorBodyContent(tu.getCProject(), typeName, bodyStatement, lineDelimiter); + } + + /** + * Returns the content for a new file comment using the 'file comment' code template. The returned content is unformatted and is not indented. + * @param tu The translation unit to add the comment to. The translation unit does not need to exist. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the new content or null if the code template is undefined or empty. The returned content is unformatted and is not indented. + * @throws CoreException Thrown when the evaluation of the code template fails. + * @since 5.0 + */ + public static String getFileComment(ITranslationUnit tu, String lineDelimiter) throws CoreException { + return StubUtility.getFileComment(tu, lineDelimiter); + } + /** * Returns the content for a new type comment using the 'typecomment' code template. The returned content is unformatted and is not indented. - * @param tu The translation unit where the type is contained. The compilation unit does not need to exist. + * @param tu The translation unit where the type is contained. The translation unit does not need to exist. * @param typeQualifiedName The name of the type to which the comment is added. For inner types the name must be qualified and include the outer * types names (dot separated). * @param lineDelimiter The line delimiter to be used. @@ -66,5 +163,60 @@ public class CodeGeneration { public static String getClassComment(ITranslationUnit tu, String typeQualifiedName, String lineDelimiter) throws CoreException { return StubUtility.getClassComment(tu, typeQualifiedName, lineDelimiter); } - + + /** + * Returns the comment for a method using the method comment code template. + * null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param declaringTypeName Name of the type to which the method belongs. + * @param methodName Name of the method. + * @param paramNames Names of the parameters for the method. + * @param excTypeSig Thrown exceptions. + * @param retTypeSig Return type. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed comment or null if + * the comment code template is empty. The returned content is unformatted and not indented (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + */ + public static String getMethodComment(ITranslationUnit tu, String declaringTypeName, String methodName, String[] paramNames, String[] excTypeSig, String retTypeSig, String lineDelimiter) throws CoreException { + return StubUtility.getMethodComment(tu, declaringTypeName, methodName, paramNames, excTypeSig, retTypeSig, lineDelimiter); + } + + /** + * Returns the comment for a constructor using the constructor comment code template. + * null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param declaringTypeName Name of the type to which the method belongs. + * @param paramNames Names of the parameters for the method. + * @param excTypeSig Thrown exceptions. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed comment or null if + * the comment code template is empty. The returned content is unformatted and not indented (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + */ + public static String getConstructorComment(ITranslationUnit tu, String declaringTypeName, String[] paramNames, String[] excTypeSig, String lineDelimiter) throws CoreException { + return StubUtility.getConstructorComment(tu, declaringTypeName, paramNames, excTypeSig, lineDelimiter); + } + + /** + * Returns the comment for a destructor using the destructor comment code template. + * null is returned if the template is empty. + *

The returned string is unformatted and not indented. + * + * @param tu The translation unit to which the method belongs. The translation unit does not need to exist. + * @param declaringTypeName Name of the type to which the method belongs. + * @param excTypeSig Thrown exceptions. + * @param lineDelimiter The line delimiter to be used. + * @return Returns the constructed comment or null if + * the comment code template is empty. The returned content is unformatted and not indented (formatting required). + * @throws CoreException Thrown when the evaluation of the code template fails. + */ + public static String getDestructorComment(ITranslationUnit tu, String declaringTypeName, String[] excTypeSig, String lineDelimiter) throws CoreException { + return StubUtility.getDestructorComment(tu, declaringTypeName, excTypeSig, lineDelimiter); + } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java index d6d85e5c883..bfa35565f58 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java @@ -15,6 +15,9 @@ package org.eclipse.cdt.ui; import java.util.Locale; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.action.Action; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; @@ -24,6 +27,8 @@ import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; +import org.eclipse.cdt.core.model.ICProject; + import org.eclipse.cdt.internal.ui.ICThemeConstants; import org.eclipse.cdt.internal.ui.text.ICColorConstants; import org.eclipse.cdt.internal.ui.text.spelling.SpellCheckEngine; @@ -1003,7 +1008,6 @@ public class PreferenceConstants { * @since 5.0 */ public final static String CODEASSIST_PROPOSALS_BACKGROUND= "content_assist_proposals_background"; //$NON-NLS-1$ - /** * A named preference that holds the foreground color used in the code assist selection dialog. *

@@ -1171,6 +1175,16 @@ public class PreferenceConstants { */ public final static String SPELLING_ENABLE_CONTENTASSIST= "spelling_enable_contentassist"; //$NON-NLS-1$ + /** + * A named preference that controls if documentation comment stubs will be added + * automatically to newly created types and methods. + *

+ * Value is of type Boolean. + *

+ * @since 5.0 + */ + public static final String CODEGEN_ADD_COMMENTS= "org.eclipse.cdt.ui.add_comments"; //$NON-NLS-1$ + /** * Returns the CDT-UI preference store. * @@ -1289,6 +1303,7 @@ public class PreferenceConstants { // content assist store.setDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, "org.eclipse.cdt.ui.textProposalCategory\0"); //$NON-NLS-1$ store.setDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER, "org.eclipse.cdt.ui.parserProposalCategory:65539\0org.eclipse.cdt.ui.textProposalCategory:65541\0org.eclipse.cdt.ui.templateProposalCategory:2\0"); //$NON-NLS-1$ + setDefaultAndFireEvent( store, @@ -1329,7 +1344,36 @@ public class PreferenceConstants { * cannot return word proposals but only correction proposals. */ store.setToDefault(PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST); + + // codegen + store.setDefault(PreferenceConstants.CODEGEN_ADD_COMMENTS, false); } + + + /** + * Returns the value for the given key in the given context. + * @param key The preference key + * @param project The current context or null if no context is available and the + * workspace setting should be taken. Note that passing null should + * be avoided. + * @return Returns the current value for the string. + * @since 5.0 + */ + public static String getPreference(String key, ICProject project) { + String val; + if (project != null) { + val= new ProjectScope(project.getProject()).getNode(CUIPlugin.PLUGIN_ID).get(key, null); + if (val != null) { + return val; + } + } + val= new InstanceScope().getNode(CUIPlugin.PLUGIN_ID).get(key, null); + if (val != null) { + return val; + } + return new DefaultScope().getNode(CUIPlugin.PLUGIN_ID).get(key, null); + } + /** * Sets the default value and fires a property diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewHeaderFileCreationWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewHeaderFileCreationWizard.java index f7d63ef47c1..f459fd9d05e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewHeaderFileCreationWizard.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewHeaderFileCreationWizard.java @@ -22,7 +22,7 @@ public class NewHeaderFileCreationWizard extends AbstractFileCreationWizard { super(); setDefaultPageImageDescriptor(CPluginImages.DESC_WIZBAN_NEW_HEADERFILE); setDialogSettings(CUIPlugin.getDefault().getDialogSettings()); - setWindowTitle(NewFileWizardMessages.getString("NewHeaderFileCreationWizard.title")); //$NON-NLS-1$ + setWindowTitle(NewFileWizardMessages.NewHeaderFileCreationWizard_title); } /* diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewSourceFileCreationWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewSourceFileCreationWizard.java index 1ccb080821c..2ece37225f0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewSourceFileCreationWizard.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewSourceFileCreationWizard.java @@ -22,7 +22,7 @@ public class NewSourceFileCreationWizard extends AbstractFileCreationWizard { super(); setDefaultPageImageDescriptor(CPluginImages.DESC_WIZBAN_NEW_SOURCEFILE); setDialogSettings(CUIPlugin.getDefault().getDialogSettings()); - setWindowTitle(NewFileWizardMessages.getString("NewSourceFileCreationWizard.title")); //$NON-NLS-1$ + setWindowTitle(NewFileWizardMessages.NewSourceFileCreationWizard_title); } /* diff --git a/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml b/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml new file mode 100644 index 00000000000..81325dc23d6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/templates/default-filetemplates.xml b/core/org.eclipse.cdt.ui/templates/default-filetemplates.xml new file mode 100644 index 00000000000..4cea755ce2a --- /dev/null +++ b/core/org.eclipse.cdt.ui/templates/default-filetemplates.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/templates/default-templates.properties b/core/org.eclipse.cdt.ui/templates/default-templates.properties index 83cca3df0b3..20ba0e771cb 100644 --- a/core/org.eclipse.cdt.ui/templates/default-templates.properties +++ b/core/org.eclipse.cdt.ui/templates/default-templates.properties @@ -35,3 +35,33 @@ printtostderr = print to standard error authorname = author name commentText = To change this generated comment edit the template variable "comment":\n\ \ * Window > Preferences > C/C++ > Editor > Templates. + +# strings in default code templates +CodeTemplates.constructorcomment=Comment for created constructors +CodeTemplates.destructorcomment=Comment for created destructors +CodeTemplates.filecomment=Comment for created C/C++ files +CodeTemplates.typecomment=Comment for created classes +CodeTemplates.fieldcomment=Comment for fields +CodeTemplates.methodcomment=Comment for methods + +CodeTemplates.cppsourcefile=Default C++ source template +CodeTemplates.cppheaderfile=Default C++ header template +CodeTemplates.csourcefile=Default C source template +CodeTemplates.cheaderfile=Default C header template +CodeTemplates.cppsourcefile.desc=Default template for newly created C++ source files +CodeTemplates.cppheaderfile.desc=Default template for newly created C++ header files +CodeTemplates.csourcefile.desc=Default template for newly created C source files +CodeTemplates.cheaderfile.desc=Default template for newly created C header files + +CodeTemplates.methodstub=Code in created method stubs +CodeTemplates.constructorstub=Code in created constructor stubs +CodeTemplates.destructorstub=Code in created destructor stubs + +CodeTemplates.methodstub.tododesc=Auto-generated method stub +CodeTemplates.constructorstub.tododesc=Auto-generated constructor stub +CodeTemplates.destructorstub.tododesc=Auto-generated destructor stub + +FileTemplates.asmsourcefile=Default assembly template +FileTemplates.asmsourcefile.desc=Default template for newly created assembly files +FileTemplates.textfile=Default text file template +FileTemplates.textfile.desc=Default template for newly created text files