From: incastrix
+ * This interface contains constants only; it is not intended to be implemented
+ * or extended.
+ *
+ * Clients are required to call
+ * Note: This class is not intended to be subclassed outside the JDT UI plugin.
+ *
+ * Configure the action later using the set methods.
+ *
+ * Subclasses may override.
+ *
+ * @param selection
+ * containing the elements to be dragged
+ */
+ protected boolean isDragable(ISelection selection) {
+ return true;
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see org.eclipse.swt.dnd.DragSourceListener#dragSetData
+ */
+ public void dragSetData(DragSourceEvent event) {
+ // For consistency set the data to the selection even though
+ // the selection is provided by the LocalSelectionTransfer
+ // to the drop target adapter.
+ event.data = LocalSelectionTransfer.getInstance().getSelection();
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see org.eclipse.swt.dnd.DragSourceListener#dragFinished
+ */
+ public void dragFinished(DragSourceEvent event) {
+ // We assume that the drop target listener has done all
+ // the work.
+ Assert.isTrue(event.detail == DND.DROP_NONE);
+ LocalSelectionTransfer.getInstance().setSelection(null);
+ LocalSelectionTransfer.getInstance().setSelectionSetTime(0);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/DelegatingDragAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/DelegatingDragAdapter.java
new file mode 100644
index 0000000..df9c40a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/DelegatingDragAdapter.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+
+/**
+ * A delegating drag adapter negotiates between a set of
+ *
+ * This attribute is mandatory for custom filters. The ID for pattern
+ * filters is PATTERN_FILTER_ID_PREFIX plus the pattern itself.
+ *
+ * If the name of a pattern filter is missing then the pattern is used as
+ * its name.
+ *
+ * The following characters have special meaning: ? => any character * => any
+ * string
+ *
+ * The following characters have special meaning: ? => any character * =>
+ * any string
+ *
+ * Note: Folder which are direct children of a Java element are already filtered
+ * by the Java Model.
+ *
+ * Note: Must be public since it is referenced from plugin.xml
+ *
+ * Clients may implement this interface.
+ *
+ * All methods except firing, adding and removing listeners throw an
+ * {@link java.lang.UnsupportedOperationException}.
+ *
+ * Note: This method must be called before {@link #load()} is called.
+ *
+ * Word rules also allow for the association of tokens with specific words. That
+ * is, not only can the rule be used to provide tokens for exact matches, but
+ * also for the generalized notion of a word in the context in which it is used.
+ * A word rules uses a word detector to determine what a word is.
+ *
+ * This word rule allows a word detector to be shared among different word
+ * matchers. Its up to the word matchers to decide if a word matches and, in
+ * this a case, which token is associated with that word.
+ *
+ * Note that, if the document is modified concurrently, this method may
+ * return {@link CharacterIterator#DONE} if a {@link BadLocationException}
+ * was thrown when accessing the backing document.
+ * "); //$NON-NLS-1$
+ buffer.append(paragraph);
+ }
+ }
+
+ public static void addParagraph(StringBuffer buffer, Reader paragraphReader) {
+ if (paragraphReader != null)
+ addParagraph(buffer, read(paragraphReader));
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTMLTextPresenter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTMLTextPresenter.java
new file mode 100644
index 0000000..aa21538
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTMLTextPresenter.java
@@ -0,0 +1,196 @@
+package net.sourceforge.phpdt.internal.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.widgets.Display;
+
+public class HTMLTextPresenter implements
+ DefaultInformationControl.IInformationPresenter {
+
+ private static final String LINE_DELIM = System.getProperty(
+ "line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ private int fCounter;
+
+ private boolean fEnforceUpperLineLimit;
+
+ public HTMLTextPresenter(boolean enforceUpperLineLimit) {
+ super();
+ fEnforceUpperLineLimit = enforceUpperLineLimit;
+ }
+
+ public HTMLTextPresenter() {
+ this(true);
+ }
+
+ protected Reader createReader(String hoverInfo,
+ TextPresentation presentation) {
+ return new HTML2TextReader(new StringReader(hoverInfo), presentation);
+ }
+
+ protected void adaptTextPresentation(TextPresentation presentation,
+ int offset, int insertLength) {
+
+ int yoursStart = offset;
+ int yoursEnd = offset + insertLength - 1;
+ yoursEnd = Math.max(yoursStart, yoursEnd);
+
+ Iterator e = presentation.getAllStyleRangeIterator();
+ while (e.hasNext()) {
+
+ StyleRange range = (StyleRange) e.next();
+
+ int myStart = range.start;
+ int myEnd = range.start + range.length - 1;
+ myEnd = Math.max(myStart, myEnd);
+
+ if (myEnd < yoursStart)
+ continue;
+
+ if (myStart < yoursStart)
+ range.length += insertLength;
+ else
+ range.start += insertLength;
+ }
+ }
+
+ private void append(StringBuffer buffer, String string,
+ TextPresentation presentation) {
+
+ int length = string.length();
+ buffer.append(string);
+
+ if (presentation != null)
+ adaptTextPresentation(presentation, fCounter, length);
+
+ fCounter += length;
+ }
+
+ private String getIndent(String line) {
+ int length = line.length();
+
+ int i = 0;
+ while (i < length && Character.isWhitespace(line.charAt(i)))
+ ++i;
+
+ return (i == length ? line : line.substring(0, i)) + " "; //$NON-NLS-1$
+ }
+
+ /*
+ * @see IHoverInformationPresenter#updatePresentation(Display display,
+ * String, TextPresentation, int, int)
+ */
+ public String updatePresentation(Display display, String hoverInfo,
+ TextPresentation presentation, int maxWidth, int maxHeight) {
+
+ if (hoverInfo == null)
+ return null;
+
+ GC gc = new GC(display);
+ try {
+
+ StringBuffer buffer = new StringBuffer();
+ int maxNumberOfLines = Math.round(maxHeight
+ / gc.getFontMetrics().getHeight());
+
+ fCounter = 0;
+ LineBreakingReader reader = new LineBreakingReader(createReader(
+ hoverInfo, presentation), gc, maxWidth);
+
+ boolean lastLineFormatted = false;
+ String lastLineIndent = null;
+
+ String line = reader.readLine();
+ boolean lineFormatted = reader.isFormattedLine();
+ boolean firstLineProcessed = false;
+
+ while (line != null) {
+
+ if (fEnforceUpperLineLimit && maxNumberOfLines <= 0)
+ break;
+
+ if (firstLineProcessed) {
+ if (!lastLineFormatted)
+ append(buffer, LINE_DELIM, null);
+ else {
+ append(buffer, LINE_DELIM, presentation);
+ if (lastLineIndent != null)
+ append(buffer, lastLineIndent, presentation);
+ }
+ }
+
+ append(buffer, line, null);
+ firstLineProcessed = true;
+
+ lastLineFormatted = lineFormatted;
+ if (!lineFormatted)
+ lastLineIndent = null;
+ else if (lastLineIndent == null)
+ lastLineIndent = getIndent(line);
+
+ line = reader.readLine();
+ lineFormatted = reader.isFormattedLine();
+
+ maxNumberOfLines--;
+ }
+
+ if (line != null) {
+ append(buffer, LINE_DELIM, lineFormatted ? presentation : null);
+ append(buffer, PHPUIMessages
+ .getString("HTMLTextPresenter.ellipsis"), presentation); //$NON-NLS-1$
+ }
+
+ return trim(buffer, presentation);
+
+ } catch (IOException e) {
+
+ WebUI.log(e);
+ return null;
+
+ } finally {
+ gc.dispose();
+ }
+ }
+
+ private String trim(StringBuffer buffer, TextPresentation presentation) {
+
+ int length = buffer.length();
+
+ int end = length - 1;
+ while (end >= 0 && Character.isWhitespace(buffer.charAt(end)))
+ --end;
+
+ if (end == -1)
+ return ""; //$NON-NLS-1$
+
+ if (end < length - 1)
+ buffer.delete(end + 1, length);
+ else
+ end = length;
+
+ int start = 0;
+ while (start < end && Character.isWhitespace(buffer.charAt(start)))
+ ++start;
+
+ buffer.delete(0, start);
+ presentation.setResultWindow(new Region(start, buffer.length()));
+ return buffer.toString();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/IPHPPartitions.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/IPHPPartitions.java
new file mode 100644
index 0000000..18b2e2a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/IPHPPartitions.java
@@ -0,0 +1,49 @@
+/*
+ * Created on 05.03.2003
+ *
+ */
+package net.sourceforge.phpdt.internal.ui.text;
+
+/**
+ * @author Stefan Langer (musk)
+ *
+ */
+public interface IPHPPartitions {
+ public final static String PHP_PARTITIONING = "___php_partitioning"; //$NON-NLS-1$
+
+ public final static String PHP_PHPDOC_COMMENT = "__php_phpdoc_comment"; //$NON-NLS-1$
+
+ public final static String PHP_SINGLELINE_COMMENT = "__php_singleline_comment"; //$NON-NLS-1$
+
+ public final static String PHP_MULTILINE_COMMENT = "__php_multiline_comment"; //$NON-NLS-1$
+
+ public final static String PHP_STRING_DQ = "__php_string"; //$NON-NLS-1$
+
+ public final static String PHP_STRING_SQ = "__php_string_sq"; //$NON-NLS-1$
+
+ public final static String PHP_STRING_HEREDOC = "__php_string_heredoc"; //$NON-NLS-1$
+
+ public final static String JAVASCRIPT = "__javascript"; //$NON-NLS-1$
+
+ public final static String JS_MULTILINE_COMMENT = "__js_multiline_comment"; //$NON-NLS-1$
+
+ public final static String CSS = "__css"; //$NON-NLS-1$
+
+ public final static String CSS_MULTILINE_COMMENT = "__css_multiline_comment"; //$NON-NLS-1$
+
+ public final static String HTML = "__html"; //$NON-NLS-1$
+
+ public final static String HTML_MULTILINE_COMMENT = "__html_multiline_comment"; //$NON-NLS-1$
+
+ public final static String SMARTY = "__smarty"; //$NON-NLS-1$
+
+ public final static String SMARTY_MULTILINE_COMMENT = "__smarty_multiline_comment"; //$NON-NLS-1$
+
+ public final static int PHP_FILE = 1;
+
+ public final static int HTML_FILE = 2;
+
+ public final static int XML_FILE = 3;
+
+ public final static int SMARTY_FILE = 4;
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java
new file mode 100644
index 0000000..a1e35a5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType;
+
+/**
+ * Listener for
+ * A line break may be any of "\n", "\r", "\r\n", "\n\r".
+ *
+ * An instance holds some internal position in the document and is therefore not
+ * threadsafe.
+ *
+ * Note that
+ * Note that
+ * Algorithm: if the last non-WS, non-Comment code on the line is an if
+ * (condition), while (condition), for( expression), do, else, and there is
+ * no statement after that
+ *
+ * An instance holds some internal position in the document and is therefore not
+ * threadsafe.
+ *
+ * Every run of the number of spaces that make up a tab are replaced by a
+ * tab character.
+ *
+ * If
+ * Depending on the type of scope introduction, the indentation will align
+ * (deep indenting) with the reference position (
+ * The heuristic calls
+ * The following characters have special meaning: ? => any character * =>
+ * any string
+ *
+ * The following characters have special meaning: ? => any character * =>
+ * any string
+ *
+ * NOTE: Should not be used if this reconciler is installed on a viewer.
+ *
+ * Undo specifications are removed after a number of typing runs.
+ *
+ * Optionally, a child specification can be registered. After executing
+ * the spec, the child spec will be registered with the manager. This
+ * allows to create chains of
+ * In practice, semicolons and braces (and the caret) are moved to the end of
+ * the line if they are typed anywhere except for semicolons in a
+ *
+ * When called on a document with content
+ * XXX to be extended with further information, e.g. offset, length, and content
+ * of the run.
+ *
+ * Listeners are informed about the start and end of a
+ * A tuple is said to match another if their annotations have the same
+ * comment flag and their position offsets are equal.
+ *
+ * If a match is found, the annotation gets removed from
+ *
+ * This method can be called more than once in order to reload from a
+ * changed extension registry.
+ *
+ * Note: this interface is not intended to be implemented.
+ *
+ * This class got moved here form Platform Text since it was not used there and
+ * caused discouraged access warnings. It will be moved down again once
+ * annotation roll-over support is provided by Platform Text.
+ *
+ * Each annotation can have its custom context menu and hover.
+ *
+ * There are the following constraints for linked positions:
+ *
+ * true
, comments will be added.
+ * @param flags
+ * The flags signaling visibility, if static, synchronized or
+ * final
+ * @return Returns the generated stub.
+ * @throws CoreException
+ */
+ public static String getSetterStub(IField field, String setterName,
+ boolean addComments, int flags) throws CoreException {
+
+ String fieldName = field.getElementName();
+ IType parentType = field.getDeclaringType();
+
+ String returnSig = field.getTypeSignature();
+ String typeName = Signature.toString(returnSig);
+
+ IJavaProject project = field.getJavaProject();
+
+ String accessorName = NamingConventions
+ .removePrefixAndSuffixForFieldName(project, fieldName, field
+ .getFlags());
+ String argname = StubUtility.suggestArgumentName(project, accessorName,
+ EMPTY);
+
+ boolean isStatic = Flags.isStatic(flags);
+ // boolean isSync= Flags.isSynchronized(flags);
+ boolean isFinal = Flags.isFinal(flags);
+
+ // create the setter stub
+ StringBuffer buf = new StringBuffer();
+ if (addComments) {
+ String comment = CodeGeneration.getSetterComment(field
+ .getCompilationUnit(),
+ parentType.getTypeQualifiedName('.'), setterName, field
+ .getElementName(), typeName, argname, accessorName,
+ String.valueOf('\n'));
+ if (comment != null) {
+ buf.append(comment);
+ buf.append('\n');
+ }
+ }
+ buf.append(JdtFlags.getVisibilityString(flags));
+ buf.append(' ');
+ if (isStatic)
+ buf.append("static "); //$NON-NLS-1$
+ // if (isSync)
+ // buf.append("synchronized "); //$NON-NLS-1$
+ if (isFinal)
+ buf.append("final "); //$NON-NLS-1$
+
+ buf.append("void "); //$NON-NLS-1$
+ buf.append(setterName);
+ buf.append('(');
+ buf.append(typeName);
+ buf.append(' ');
+ buf.append(argname);
+ buf.append(") {\n"); //$NON-NLS-1$
+
+ boolean useThis = PreferenceConstants.getPreferenceStore().getBoolean(
+ PreferenceConstants.CODEGEN_KEYWORD_THIS);
+ if (argname.equals(fieldName) || (useThis && !isStatic)) {
+ if (isStatic)
+ fieldName = parentType.getElementName() + '.' + fieldName;
+ else
+ fieldName = "this." + fieldName; //$NON-NLS-1$
+ }
+ String body = CodeGeneration.getSetterMethodBodyContent(field
+ .getCompilationUnit(), parentType.getTypeQualifiedName('.'),
+ setterName, fieldName, argname, String.valueOf('\n'));
+ if (body != null) {
+ buf.append(body);
+ }
+ buf.append("}\n"); //$NON-NLS-1$
+ return buf.toString();
+ }
+
+ /**
+ * Create a stub for a getter of the given field using getter/setter
+ * templates. The resulting code has to be formatted and indented.
+ *
+ * @param field
+ * The field to create a getter for
+ * @param getterName
+ * The chosen name for the getter
+ * @param addComments
+ * If true
, comments will be added.
+ * @param flags
+ * The flags signaling visibility, if static, synchronized or
+ * final
+ * @return Returns the generated stub.
+ * @throws CoreException
+ */
+ public static String getGetterStub(IField field, String getterName,
+ boolean addComments, int flags) throws CoreException {
+ String fieldName = field.getElementName();
+ IType parentType = field.getDeclaringType();
+
+ boolean isStatic = Flags.isStatic(flags);
+ // boolean isSync= Flags.isSynchronized(flags);
+ boolean isFinal = Flags.isFinal(flags);
+
+ String typeName = Signature.toString(field.getTypeSignature());
+ String accessorName = NamingConventions
+ .removePrefixAndSuffixForFieldName(field.getJavaProject(),
+ fieldName, field.getFlags());
+
+ // create the getter stub
+ StringBuffer buf = new StringBuffer();
+ if (addComments) {
+ String comment = CodeGeneration.getGetterComment(field
+ .getCompilationUnit(),
+ parentType.getTypeQualifiedName('.'), getterName, field
+ .getElementName(), typeName, accessorName, String
+ .valueOf('\n'));
+ if (comment != null) {
+ buf.append(comment);
+ buf.append('\n');
+ }
+ }
+
+ buf.append(JdtFlags.getVisibilityString(flags));
+ buf.append(' ');
+ if (isStatic)
+ buf.append("static "); //$NON-NLS-1$
+ // if (isSync)
+ // buf.append("synchronized "); //$NON-NLS-1$
+ if (isFinal)
+ buf.append("final "); //$NON-NLS-1$
+
+ buf.append(typeName);
+ buf.append(' ');
+ buf.append(getterName);
+ buf.append("() {\n"); //$NON-NLS-1$
+
+ boolean useThis = PreferenceConstants.getPreferenceStore().getBoolean(
+ PreferenceConstants.CODEGEN_KEYWORD_THIS);
+ if (useThis && !isStatic) {
+ fieldName = "this." + fieldName; //$NON-NLS-1$
+ }
+
+ String body = CodeGeneration.getGetterMethodBodyContent(field
+ .getCompilationUnit(), parentType.getTypeQualifiedName('.'),
+ getterName, fieldName, String.valueOf('\n'));
+ if (body != null) {
+ buf.append(body);
+ }
+ buf.append("}\n"); //$NON-NLS-1$
+ return buf.toString();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/codemanipulation/IRequestQuery.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/codemanipulation/IRequestQuery.java
new file mode 100644
index 0000000..a7b9989
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/codemanipulation/IRequestQuery.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.codemanipulation;
+
+import net.sourceforge.phpdt.core.IMember;
+
+/**
+ * Query object to let operations callback the actions. Example is a callback to
+ * ask if a existing method should be replaced.
+ */
+public interface IRequestQuery {
+
+ // return codes
+ public static final int CANCEL = 0;
+
+ public static final int NO = 1;
+
+ public static final int YES = 2;
+
+ public static final int YES_ALL = 3;
+
+ /**
+ * Do the callback. Returns YES, NO, YES_ALL or CANCEL
+ */
+ int doQuery(IMember member);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/codemanipulation/StubUtility.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/codemanipulation/StubUtility.java
new file mode 100644
index 0000000..cd11e2a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/codemanipulation/StubUtility.java
@@ -0,0 +1,1446 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.corext.codemanipulation;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.ICodeFormatter;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.Signature;
+import net.sourceforge.phpdt.core.ToolFactory;
+import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContext;
+import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContextType;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+import net.sourceforge.phpdt.internal.corext.util.PHPUIStatus;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+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.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateVariable;
+import org.eclipse.swt.SWT;
+
+public class StubUtility {
+
+ public static class GenStubSettings extends CodeGenerationSettings {
+
+ public boolean callSuper;
+
+ public boolean methodOverwrites;
+
+ public boolean noBody;
+
+ public int methodModifiers;
+
+ public GenStubSettings(CodeGenerationSettings settings) {
+ settings.setSettings(this);
+ methodModifiers = -1;
+ }
+
+ }
+
+ private static final String[] EMPTY = new String[0];
+
+ /**
+ * Generates a method stub including the method comment. Given a template
+ * method, a stub with the same signature will be constructed so it can be
+ * added to a type. The method body will be empty or contain a return or
+ * super call.
+ *
+ * @param destTypeName
+ * The name of the type to which the method will be added to
+ * @param method
+ * A method template (method belongs to different type than the
+ * parent)
+ * @param definingType
+ * The type that defines the method.
+ * @param settings
+ * Options as defined above (GenStubSettings
)
+ * @param imports
+ * Imports required by the stub are added to the imports
+ * structure. If imports structure is null
all
+ * type names are qualified.
+ * @throws JavaModelException
+ */
+ public static String genStub(ICompilationUnit cu, String destTypeName,
+ IMethod method, IType definingType, GenStubSettings settings)
+ throws CoreException {
+ // IImportsStructure imports) throws CoreException {
+ String methName = method.getElementName();
+ String[] paramNames = suggestArgumentNames(method.getJavaProject(),
+ method.getParameterNames());
+ String returnType = method.isConstructor() ? null : method
+ .getReturnType();
+ String lineDelimiter = String.valueOf('\n'); // reformatting required
+
+ StringBuffer buf = new StringBuffer();
+ // add method comment
+ if (settings.createComments && cu != null) {
+ IMethod overridden = null;
+ if (settings.methodOverwrites && returnType != null) {
+ overridden = JavaModelUtil.findMethod(methName, method
+ .getParameterTypes(), false, definingType.getMethods());
+ }
+ String comment = getMethodComment(cu, destTypeName, methName,
+ paramNames, method.getExceptionTypes(), returnType,
+ overridden, lineDelimiter);
+ if (comment != null) {
+ buf.append(comment);
+ } else {
+ buf.append("/**").append(lineDelimiter); //$NON-NLS-1$
+ buf.append(" *").append(lineDelimiter); //$NON-NLS-1$
+ buf.append(" */").append(lineDelimiter); //$NON-NLS-1$
+ }
+ buf.append(lineDelimiter);
+ }
+ // add method declaration
+ String bodyContent = null;
+ if (!settings.noBody) {
+ String bodyStatement = getDefaultMethodBodyStatement(methName,
+ paramNames, returnType, settings.callSuper);
+ bodyContent = getMethodBodyContent(returnType == null, method
+ .getJavaProject(), destTypeName, methName, bodyStatement,
+ lineDelimiter);
+ if (bodyContent == null) {
+ bodyContent = ""; //$NON-NLS-1$
+ }
+ }
+ int flags = settings.methodModifiers;
+ if (flags == -1) {
+ flags = method.getFlags();
+ }
+
+ genMethodDeclaration(destTypeName, method, flags, bodyContent, buf); // imports,
+ // buf);
+ return buf.toString();
+ }
+
+ /**
+ * Generates a method stub not including the method comment. Given a
+ * template method and the body content, a stub with the same signature will
+ * be constructed so it can be added to a type.
+ *
+ * @param destTypeName
+ * The name of the type to which the method will be added to
+ * @param method
+ * A method template (method belongs to different type than the
+ * parent)
+ * @param bodyContent
+ * Content of the body
+ * @param imports
+ * Imports required by the stub are added to the imports
+ * structure. If imports structure is null
all
+ * type names are qualified.
+ * @param buf
+ * The buffer to append the gerenated code.
+ * @throws JavaModelException
+ */
+ public static void genMethodDeclaration(String destTypeName,
+ IMethod method, String bodyContent, StringBuffer buf)
+ throws CoreException { // IImportsStructure imports, StringBuffer
+ // buf) throws CoreException {
+ genMethodDeclaration(destTypeName, method, method.getFlags(),
+ bodyContent, buf);
+ }
+
+ /**
+ * Generates a method stub not including the method comment. Given a
+ * template method and the body content, a stub with the same signature will
+ * be constructed so it can be added to a type.
+ *
+ * @param destTypeName
+ * The name of the type to which the method will be added to
+ * @param method
+ * A method template (method belongs to different type than the
+ * parent)
+ * @param bodyContent
+ * Content of the body
+ * @param imports
+ * Imports required by the stub are added to the imports
+ * structure. If imports structure is null
all
+ * type names are qualified.
+ * @param buf
+ * The buffer to append the gerenated code.
+ * @throws JavaModelException
+ */
+ public static void genMethodDeclaration(String destTypeName,
+ IMethod method, int flags, String bodyContent, StringBuffer buf)
+ throws CoreException {
+ // IImportsStructure imports, StringBuffer buf) throws CoreException {
+ IType parentType = method.getDeclaringType();
+ String methodName = method.getElementName();
+ String[] paramTypes = method.getParameterTypes();
+ String[] paramNames = suggestArgumentNames(parentType.getJavaProject(),
+ method.getParameterNames());
+
+ String[] excTypes = method.getExceptionTypes();
+
+ boolean isConstructor = method.isConstructor();
+ String retTypeSig = isConstructor ? null : method.getReturnType();
+
+ int lastParam = paramTypes.length - 1;
+
+ if (Flags.isPublic(flags)
+ || (parentType.isInterface() && bodyContent != null)) {
+ buf.append("public "); //$NON-NLS-1$
+ } else if (Flags.isProtected(flags)) {
+ buf.append("protected "); //$NON-NLS-1$
+ } else if (Flags.isPrivate(flags)) {
+ buf.append("private "); //$NON-NLS-1$
+ }
+ // if (Flags.isSynchronized(flags)) {
+ // buf.append("synchronized "); //$NON-NLS-1$
+ // }
+ // if (Flags.isVolatile(flags)) {
+ // buf.append("volatile "); //$NON-NLS-1$
+ // }
+ // if (Flags.isStrictfp(flags)) {
+ // buf.append("strictfp "); //$NON-NLS-1$
+ // }
+ if (Flags.isStatic(flags)) {
+ buf.append("static "); //$NON-NLS-1$
+ }
+
+ if (isConstructor) {
+ buf.append(destTypeName);
+ } else {
+ String retTypeFrm;
+ if (!isPrimitiveType(retTypeSig)) {
+ retTypeFrm = resolveAndAdd(retTypeSig, parentType);
+ } else {
+ retTypeFrm = Signature.toString(retTypeSig);
+ }
+ buf.append(retTypeFrm);
+ buf.append(' ');
+ buf.append(methodName);
+ }
+ buf.append('(');
+ for (int i = 0; i <= lastParam; i++) {
+ String paramTypeSig = paramTypes[i];
+ String paramTypeFrm;
+
+ if (!isPrimitiveType(paramTypeSig)) {
+ paramTypeFrm = resolveAndAdd(paramTypeSig, parentType);
+ } else {
+ paramTypeFrm = Signature.toString(paramTypeSig);
+ }
+ buf.append(paramTypeFrm);
+ buf.append(' ');
+ buf.append(paramNames[i]);
+ if (i < lastParam) {
+ buf.append(", "); //$NON-NLS-1$
+ }
+ }
+ buf.append(')');
+
+ int lastExc = excTypes.length - 1;
+ if (lastExc >= 0) {
+ buf.append(" throws "); //$NON-NLS-1$
+ for (int i = 0; i <= lastExc; i++) {
+ String excTypeSig = excTypes[i];
+ String excTypeFrm = resolveAndAdd(excTypeSig, parentType);
+ buf.append(excTypeFrm);
+ if (i < lastExc) {
+ buf.append(", "); //$NON-NLS-1$
+ }
+ }
+ }
+ if (bodyContent == null) {
+ buf.append(";\n\n"); //$NON-NLS-1$
+ } else {
+ buf.append(" {\n\t"); //$NON-NLS-1$
+ if ((bodyContent != null) && (bodyContent.length() > 0)) {
+ buf.append(bodyContent);
+ buf.append('\n');
+ }
+ buf.append("}\n"); //$NON-NLS-1$
+ }
+ }
+
+ public static String getDefaultMethodBodyStatement(String methodName,
+ String[] paramNames, String retTypeSig, boolean callSuper) {
+ StringBuffer buf = new StringBuffer();
+ if (callSuper) {
+ if (retTypeSig != null) {
+ if (!Signature.SIG_VOID.equals(retTypeSig)) {
+ buf.append("return "); //$NON-NLS-1$
+ }
+ buf.append("super."); //$NON-NLS-1$
+ buf.append(methodName);
+ } else {
+ buf.append("super"); //$NON-NLS-1$
+ }
+ buf.append('(');
+ for (int i = 0; i < paramNames.length; i++) {
+ if (i > 0) {
+ buf.append(", "); //$NON-NLS-1$
+ }
+ buf.append(paramNames[i]);
+ }
+ buf.append(");"); //$NON-NLS-1$
+ } else {
+ if (retTypeSig != null && !retTypeSig.equals(Signature.SIG_VOID)) {
+ if (!isPrimitiveType(retTypeSig)
+ || Signature.getArrayCount(retTypeSig) > 0) {
+ buf.append("return null;"); //$NON-NLS-1$
+ } else if (retTypeSig.equals(Signature.SIG_BOOLEAN)) {
+ buf.append("return false;"); //$NON-NLS-1$
+ } else {
+ buf.append("return 0;"); //$NON-NLS-1$
+ }
+ }
+ }
+ return buf.toString();
+ }
+
+ public static String getMethodBodyContent(boolean isConstructor,
+ IJavaProject project, String destTypeName, String methodName,
+ String bodyStatement, String lineDelimiter) throws CoreException {
+ String templateName = isConstructor ? CodeTemplateContextType.CONSTRUCTORSTUB
+ : CodeTemplateContextType.METHODSTUB;
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(templateName);
+ if (template == null) {
+ return bodyStatement;
+ }
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), project, lineDelimiter);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD,
+ methodName);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE,
+ destTypeName);
+ context.setVariable(CodeTemplateContextType.BODY_STATEMENT,
+ bodyStatement);
+ String str = evaluateTemplate(context, template);
+ if (str == null && !Strings.containsOnlyWhitespaces(bodyStatement)) {
+ return bodyStatement;
+ }
+ return str;
+ }
+
+ public static String getGetterMethodBodyContent(IJavaProject project,
+ String destTypeName, String methodName, String fieldName,
+ String lineDelimiter) throws CoreException {
+ String templateName = CodeTemplateContextType.GETTERSTUB;
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(templateName);
+ if (template == null) {
+ return null;
+ }
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), project, lineDelimiter);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD,
+ methodName);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE,
+ destTypeName);
+ context.setVariable(CodeTemplateContextType.FIELD, fieldName);
+
+ return evaluateTemplate(context, template);
+ }
+
+ public static String getSetterMethodBodyContent(IJavaProject project,
+ String destTypeName, String methodName, String fieldName,
+ String paramName, String lineDelimiter) throws CoreException {
+ String templateName = CodeTemplateContextType.SETTERSTUB;
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(templateName);
+ if (template == null) {
+ return null;
+ }
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), project, lineDelimiter);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD,
+ methodName);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE,
+ destTypeName);
+ context.setVariable(CodeTemplateContextType.FIELD, fieldName);
+ context.setVariable(CodeTemplateContextType.FIELD_TYPE, fieldName);
+ context.setVariable(CodeTemplateContextType.PARAM, paramName);
+
+ return evaluateTemplate(context, template);
+ }
+
+ public static String getCatchBodyContent(ICompilationUnit cu,
+ String exceptionType, String variableName, String lineDelimiter)
+ throws CoreException {
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(
+ CodeTemplateContextType.CATCHBLOCK);
+ if (template == null) {
+ return null;
+ }
+
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), cu.getJavaProject(), lineDelimiter);
+ context.setVariable(CodeTemplateContextType.EXCEPTION_TYPE,
+ exceptionType);
+ context
+ .setVariable(CodeTemplateContextType.EXCEPTION_VAR,
+ variableName); //$NON-NLS-1$
+ return evaluateTemplate(context, template);
+ }
+
+ /**
+ * @see net.sourceforge.phpdt.ui.CodeGeneration#getTypeComment(ICompilationUnit,
+ * String, String)
+ */
+ public static String getCompilationUnitContent(ICompilationUnit cu,
+ String typeComment, String typeContent, String lineDelimiter)
+ throws CoreException {
+ IPackageFragment pack = (IPackageFragment) cu.getParent();
+ String packDecl = pack.isDefaultPackage() ? "" : "package " + pack.getElementName() + ';'; //$NON-NLS-1$ //$NON-NLS-2$
+
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(
+ CodeTemplateContextType.NEWTYPE);
+ if (template == null) {
+ return null;
+ }
+
+ IJavaProject project = cu.getJavaProject();
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), project, lineDelimiter);
+ context.setCompilationUnitVariables(cu);
+ context.setVariable(CodeTemplateContextType.PACKAGE_DECLARATION,
+ packDecl);
+ context.setVariable(CodeTemplateContextType.TYPE_COMMENT,
+ typeComment != null ? typeComment : ""); //$NON-NLS-1$
+ context.setVariable(CodeTemplateContextType.TYPE_DECLARATION,
+ typeContent);
+ context.setVariable(CodeTemplateContextType.TYPENAME, Signature
+ .getQualifier(cu.getElementName()));
+ return evaluateTemplate(context, template);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.CodeGeneration#getTypeComment(ICompilationUnit,
+ * String, String)
+ */
+ public static String getTypeComment(ICompilationUnit cu,
+ String typeQualifiedName, String lineDelim) throws CoreException {
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(
+ CodeTemplateContextType.TYPECOMMENT);
+ if (template == null) {
+ return null;
+ }
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), cu.getJavaProject(), lineDelim);
+ context.setCompilationUnitVariables(cu);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, Signature
+ .getQualifier(typeQualifiedName));
+ context.setVariable(CodeTemplateContextType.TYPENAME, Signature
+ .getSimpleName(typeQualifiedName));
+ return evaluateTemplate(context, template);
+ }
+
+ // private static String[] getParameterTypesQualifiedNames(IMethodBinding
+ // binding) {
+ // ITypeBinding[] typeBindings= binding.getParameterTypes();
+ // String[] result= new String[typeBindings.length];
+ // for (int i= 0; i < result.length; i++) {
+ // result[i]= typeBindings[i].getQualifiedName();
+ // }
+ // return result;
+ // }
+
+ private static String getSeeTag(String declaringClassQualifiedName,
+ String methodName, String[] parameterTypesQualifiedNames) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("@see "); //$NON-NLS-1$
+ buf.append(declaringClassQualifiedName);
+ buf.append('#');
+ buf.append(methodName);
+ buf.append('(');
+ for (int i = 0; i < parameterTypesQualifiedNames.length; i++) {
+ if (i > 0) {
+ buf.append(", "); //$NON-NLS-1$
+ }
+ buf.append(parameterTypesQualifiedNames[i]);
+ }
+ buf.append(')');
+ return buf.toString();
+ }
+
+ private static String getSeeTag(IMethod overridden)
+ throws JavaModelException {
+ IType declaringType = overridden.getDeclaringType();
+ StringBuffer buf = new StringBuffer();
+ buf.append("@see "); //$NON-NLS-1$
+ buf.append(declaringType.getFullyQualifiedName('.'));
+ buf.append('#');
+ buf.append(overridden.getElementName());
+ buf.append('(');
+ String[] paramTypes = overridden.getParameterTypes();
+ for (int i = 0; i < paramTypes.length; i++) {
+ if (i > 0) {
+ buf.append(", "); //$NON-NLS-1$
+ }
+ String curr = paramTypes[i];
+ buf.append(JavaModelUtil.getResolvedTypeName(curr, declaringType));
+ int arrayCount = Signature.getArrayCount(curr);
+ while (arrayCount > 0) {
+ buf.append("[]"); //$NON-NLS-1$
+ arrayCount--;
+ }
+ }
+ buf.append(')');
+ return buf.toString();
+ }
+
+ /**
+ * @see net.sourceforge.phpdt.ui.CodeGeneration#getMethodComment(IMethod,IMethod,String)
+ */
+ public static String getMethodComment(IMethod method, IMethod overridden,
+ String lineDelimiter) throws CoreException {
+ String retType = method.isConstructor() ? null : method.getReturnType();
+ String[] paramNames = method.getParameterNames();
+
+ return getMethodComment(method.getCompilationUnit(), method
+ .getDeclaringType().getElementName(), method.getElementName(),
+ paramNames, method.getExceptionTypes(), retType, overridden,
+ lineDelimiter);
+ }
+
+ /**
+ * @see net.sourceforge.phpdt.ui.CodeGeneration#getMethodComment(ICompilationUnit,
+ * String, String, String[], String[], String, IMethod, String)
+ */
+ public static String getMethodComment(ICompilationUnit cu, String typeName,
+ String methodName, String[] paramNames, String[] excTypeSig,
+ String retTypeSig, IMethod overridden, String lineDelimiter)
+ throws CoreException {
+ String templateName = CodeTemplateContextType.METHODCOMMENT;
+ if (retTypeSig == null) {
+ templateName = CodeTemplateContextType.CONSTRUCTORCOMMENT;
+ } else if (overridden != null) {
+ templateName = CodeTemplateContextType.OVERRIDECOMMENT;
+ }
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(templateName);
+ if (template == null) {
+ return null;
+ }
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), cu.getJavaProject(), lineDelimiter);
+ context.setCompilationUnitVariables(cu);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD,
+ methodName);
+
+ if (retTypeSig != null) {
+ context.setVariable(CodeTemplateContextType.RETURN_TYPE, Signature
+ .toString(retTypeSig));
+ }
+ if (overridden != null) {
+ context.setVariable(CodeTemplateContextType.SEE_TAG,
+ getSeeTag(overridden));
+ }
+ TemplateBuffer buffer;
+ try {
+ buffer = context.evaluate(template);
+ } catch (BadLocationException e) {
+ throw new CoreException(Status.CANCEL_STATUS);
+ } catch (TemplateException e) {
+ throw new CoreException(Status.CANCEL_STATUS);
+ }
+ if (buffer == null) {
+ return null;
+ }
+
+ String str = buffer.getString();
+ if (Strings.containsOnlyWhitespaces(str)) {
+ return null;
+ }
+ TemplateVariable position = findTagVariable(buffer); // look if
+ // Javadoc tags
+ // have to be
+ // added
+ if (position == null) {
+ return str;
+ }
+
+ IDocument textBuffer = new Document(str);
+ String[] exceptionNames = new String[excTypeSig.length];
+ for (int i = 0; i < excTypeSig.length; i++) {
+ exceptionNames[i] = Signature.toString(excTypeSig[i]);
+ }
+ String returnType = retTypeSig != null ? Signature.toString(retTypeSig)
+ : null;
+ int[] tagOffsets = position.getOffsets();
+ for (int i = tagOffsets.length - 1; i >= 0; i--) { // from last to
+ // first
+ try {
+ insertTag(textBuffer, tagOffsets[i], position.getLength(),
+ paramNames, exceptionNames, returnType, false,
+ lineDelimiter);
+ } catch (BadLocationException e) {
+ throw new CoreException(PHPUIStatus.createError(IStatus.ERROR,
+ e));
+ }
+ }
+ return textBuffer.get();
+ }
+
+ public static String getFieldComment(ICompilationUnit cu, String typeName,
+ String fieldName, String lineDelimiter) throws CoreException {
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(
+ CodeTemplateContextType.FIELDCOMMENT);
+ if (template == null) {
+ return null;
+ }
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), cu.getJavaProject(), lineDelimiter);
+ context.setCompilationUnitVariables(cu);
+ context.setVariable(CodeTemplateContextType.FIELD_TYPE, typeName);
+ context.setVariable(CodeTemplateContextType.FIELD, fieldName);
+
+ return evaluateTemplate(context, template);
+ }
+
+ /**
+ * @see net.sourceforge.phpdt.ui.CodeGeneration#getSetterComment(ICompilationUnit,
+ * String, String, String, String, String, String, String)
+ */
+ public static String getSetterComment(ICompilationUnit cu, String typeName,
+ String methodName, String fieldName, String fieldType,
+ String paramName, String bareFieldName, String lineDelimiter)
+ throws CoreException {
+ String templateName = CodeTemplateContextType.SETTERCOMMENT;
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(templateName);
+ if (template == null) {
+ return null;
+ }
+
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), cu.getJavaProject(), lineDelimiter);
+ context.setCompilationUnitVariables(cu);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD,
+ methodName);
+ context.setVariable(CodeTemplateContextType.FIELD, fieldName);
+ context.setVariable(CodeTemplateContextType.FIELD_TYPE, fieldType);
+ context.setVariable(CodeTemplateContextType.BARE_FIELD_NAME,
+ bareFieldName);
+ context.setVariable(CodeTemplateContextType.PARAM, paramName);
+
+ return evaluateTemplate(context, template);
+ }
+
+ /**
+ * @see net.sourceforge.phpdt.ui.CodeGeneration#getGetterComment(ICompilationUnit,
+ * String, String, String, String, String, String)
+ */
+ public static String getGetterComment(ICompilationUnit cu, String typeName,
+ String methodName, String fieldName, String fieldType,
+ String bareFieldName, String lineDelimiter) throws CoreException {
+ String templateName = CodeTemplateContextType.GETTERCOMMENT;
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(templateName);
+ if (template == null) {
+ return null;
+ }
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), cu.getJavaProject(), lineDelimiter);
+ context.setCompilationUnitVariables(cu);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName);
+ context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD,
+ methodName);
+ context.setVariable(CodeTemplateContextType.FIELD, fieldName);
+ context.setVariable(CodeTemplateContextType.FIELD_TYPE, fieldType);
+ context.setVariable(CodeTemplateContextType.BARE_FIELD_NAME,
+ bareFieldName);
+
+ return evaluateTemplate(context, template);
+ }
+
+ public static String evaluateTemplate(CodeTemplateContext context,
+ Template template) throws CoreException {
+ TemplateBuffer buffer;
+ try {
+ buffer = context.evaluate(template);
+ } catch (BadLocationException e) {
+ throw new CoreException(Status.CANCEL_STATUS);
+ } catch (TemplateException e) {
+ throw new CoreException(Status.CANCEL_STATUS);
+ }
+ if (buffer == null)
+ return null;
+ String str = buffer.getString();
+ if (Strings.containsOnlyWhitespaces(str)) {
+ return null;
+ }
+ return str;
+ }
+
+ /**
+ * @see net.sourceforge.phpdt.ui.CodeGeneration#getMethodComment(ICompilationUnit,
+ * String, MethodDeclaration, IMethodBinding, String)
+ */
+ // public static String getMethodComment(ICompilationUnit cu, String
+ // typeName, IMethodBinding overridden, String lineDelimiter) throws
+ // CoreException {
+ // if (overridden != null) {
+ // String declaringClassQualifiedName=
+ // overridden.getDeclaringClass().getQualifiedName();
+ // String[] parameterTypesQualifiedNames=
+ // getParameterTypesQualifiedNames(overridden);
+ // return getMethodComment(cu, typeName, decl, true,
+ // overridden.isDeprecated(), declaringClassQualifiedName,
+ // parameterTypesQualifiedNames, lineDelimiter);
+ // } else {
+ // return getMethodComment(cu, typeName, decl, false, false, null, null,
+ // lineDelimiter);
+ // }
+ // }
+ /**
+ * Returns the comment for a method using the comment code templates.
+ * null
is returned if the template is empty.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs
+ * @param typeName
+ * Name of the type to which the method belongs.
+ * @param decl
+ * The AST MethodDeclaration node that will be added as new
+ * method.
+ * @param isOverridden
+ * true
iff decl overrides another method
+ * @param isDeprecated
+ * true
iff the method that decl overrides is
+ * deprecated. Note: it must not be true
if
+ * isOverridden is false
.
+ * @param declaringClassQualifiedName
+ * Fully qualified name of the type in which the overriddden
+ * method (if any exists) in declared. If isOverridden is
+ * false
, this is ignored.
+ * @param parameterTypesQualifiedNames
+ * Fully qualified names of parameter types of the type in which
+ * the overriddden method (if any exists) in declared. If
+ * isOverridden is false
, this is ignored.
+ * @return String Returns the method comment or null
if the
+ * configured template is empty. (formatting required)
+ * @throws CoreException
+ */
+ // public static String getMethodComment(ICompilationUnit cu, String
+ // typeName, MethodDeclaration decl, boolean isOverridden, boolean
+ // isDeprecated, String declaringClassQualifiedName, String[]
+ // parameterTypesQualifiedNames, String lineDelimiter) throws CoreException
+ // {
+ // String templateName= CodeTemplateContextType.METHODCOMMENT;
+ // if (decl.isConstructor()) {
+ // templateName= CodeTemplateContextType.CONSTRUCTORCOMMENT;
+ // } else if (isOverridden) {
+ // templateName= CodeTemplateContextType.OVERRIDECOMMENT;
+ // }
+ // Template template=
+ // PHPeclipsePlugin.getDefault().getCodeTemplateStore().findTemplate(templateName);
+ // if (template == null) {
+ // return null;
+ // }
+ // CodeTemplateContext context= new
+ // CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(),
+ // lineDelimiter);
+ // context.setCompilationUnitVariables(cu);
+ // context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName);
+ // context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD,
+ // decl.getName().getIdentifier());
+ // if (!decl.isConstructor()) {
+ // context.setVariable(CodeTemplateContextType.RETURN_TYPE,
+ // ASTNodes.asString(decl.getReturnType()));
+ // }
+ // if (isOverridden) {
+ // String methodName= decl.getName().getIdentifier();
+ // context.setVariable(CodeTemplateContextType.SEE_TAG,
+ // getSeeTag(declaringClassQualifiedName, methodName,
+ // parameterTypesQualifiedNames));
+ // }
+ //
+ // TemplateBuffer buffer;
+ // try {
+ // buffer= context.evaluate(template);
+ // } catch (BadLocationException e) {
+ // throw new CoreException(Status.CANCEL_STATUS);
+ // } catch (TemplateException e) {
+ // throw new CoreException(Status.CANCEL_STATUS);
+ // }
+ // if (buffer == null)
+ // return null;
+ // String str= buffer.getString();
+ // if (Strings.containsOnlyWhitespaces(str)) {
+ // return null;
+ // }
+ // TemplateVariable position= findTagVariable(buffer); // look if Javadoc
+ // tags have to be added
+ // if (position == null) {
+ // return str;
+ // }
+ //
+ // IDocument textBuffer= new Document(str);
+ // List params= decl.parameters();
+ // String[] paramNames= new String[params.size()];
+ // for (int i= 0; i < params.size(); i++) {
+ // SingleVariableDeclaration elem= (SingleVariableDeclaration)
+ // params.get(i);
+ // paramNames[i]= elem.getName().getIdentifier();
+ // }
+ // List exceptions= decl.thrownExceptions();
+ // String[] exceptionNames= new String[exceptions.size()];
+ // for (int i= 0; i < exceptions.size(); i++) {
+ // exceptionNames[i]= ASTNodes.getSimpleNameIdentifier((Name)
+ // exceptions.get(i));
+ // }
+ // String returnType= !decl.isConstructor() ?
+ // ASTNodes.asString(decl.getReturnType()) : null;
+ // int[] tagOffsets= position.getOffsets();
+ // for (int i= tagOffsets.length - 1; i >= 0; i--) { // from last to first
+ // try {
+ // insertTag(textBuffer, tagOffsets[i], position.getLength(), paramNames,
+ // exceptionNames, returnType, isDeprecated, lineDelimiter);
+ // } catch (BadLocationException e) {
+ // throw new CoreException(PHPUIStatus.createError(IStatus.ERROR, e));
+ // }
+ // }
+ // return textBuffer.get();
+ // }
+ private static TemplateVariable findTagVariable(TemplateBuffer buffer) {
+ TemplateVariable[] positions = buffer.getVariables();
+ for (int i = 0; i < positions.length; i++) {
+ TemplateVariable curr = positions[i];
+ if (CodeTemplateContextType.TAGS.equals(curr.getType())) {
+ return curr;
+ }
+ }
+ return null;
+ }
+
+ private static void insertTag(IDocument textBuffer, int offset, int length,
+ String[] paramNames, String[] exceptionNames, String returnType,
+ boolean isDeprecated, String lineDelimiter)
+ throws BadLocationException {
+ IRegion region = textBuffer.getLineInformationOfOffset(offset);
+ if (region == null) {
+ return;
+ }
+ String lineStart = textBuffer.get(region.getOffset(), offset
+ - region.getOffset());
+
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < paramNames.length; i++) {
+ if (buf.length() > 0) {
+ buf.append(lineDelimiter);
+ buf.append(lineStart);
+ }
+ buf.append("@param ");buf.append(paramNames[i]); //$NON-NLS-1$
+ }
+ if (returnType != null && !returnType.equals("void")) { //$NON-NLS-1$
+ if (buf.length() > 0) {
+ buf.append(lineDelimiter);
+ buf.append(lineStart);
+ }
+ buf.append("@return"); //$NON-NLS-1$
+ }
+ if (exceptionNames != null) {
+ for (int i = 0; i < exceptionNames.length; i++) {
+ if (buf.length() > 0) {
+ buf.append(lineDelimiter);
+ buf.append(lineStart);
+ }
+ buf.append("@throws ");buf.append(exceptionNames[i]); //$NON-NLS-1$
+ }
+ }
+ if (isDeprecated) {
+ if (buf.length() > 0) {
+ buf.append(lineDelimiter);
+ buf.append(lineStart);
+ }
+ buf.append("@deprecated"); //$NON-NLS-1$
+ }
+ textBuffer.replace(offset, length, buf.toString());
+ }
+
+ private static boolean isPrimitiveType(String typeName) {
+ char first = Signature.getElementType(typeName).charAt(0);
+ return (first != Signature.C_RESOLVED && first != Signature.C_UNRESOLVED);
+ }
+
+ private static String resolveAndAdd(String refTypeSig, IType declaringType)
+ throws JavaModelException {// , IImportsStructure imports) throws
+ // JavaModelException {
+ String resolvedTypeName = JavaModelUtil.getResolvedTypeName(refTypeSig,
+ declaringType);
+ if (resolvedTypeName != null) {
+ StringBuffer buf = new StringBuffer();
+ // if (imports != null) {
+ // buf.append(imports.addImport(resolvedTypeName));
+ // } else {
+ buf.append(resolvedTypeName);
+ // }
+ int arrayCount = Signature.getArrayCount(refTypeSig);
+ for (int i = 0; i < arrayCount; i++) {
+ buf.append("[]"); //$NON-NLS-1$
+ }
+ return buf.toString();
+ }
+ return Signature.toString(refTypeSig);
+ }
+
+ /**
+ * Finds a method in a list of methods.
+ *
+ * @return The found method or null, if nothing found
+ */
+ private static IMethod findMethod(IMethod method, List allMethods)
+ throws JavaModelException {
+ String name = method.getElementName();
+ String[] paramTypes = method.getParameterTypes();
+ boolean isConstructor = method.isConstructor();
+
+ for (int i = allMethods.size() - 1; i >= 0; i--) {
+ IMethod curr = (IMethod) allMethods.get(i);
+ if (JavaModelUtil.isSameMethodSignature(name, paramTypes,
+ isConstructor, curr)) {
+ return curr;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates needed constructors for a type.
+ *
+ * @param type
+ * The type to create constructors for
+ * @param supertype
+ * The type's super type
+ * @param settings
+ * Options for comment generation
+ * @param imports
+ * Required imports are added to the import structure. Structure
+ * can be null
, types are qualified then.
+ * @return Returns the generated stubs or null
if the
+ * creation has been canceled
+ */
+ // public static String[] evalConstructors(IType type, IType supertype,
+ // IImportsStructure imports) throws CoreException {
+ // IMethod[] superMethods= supertype.getMethods();
+ // String typeName= type.getElementName();
+ // ICompilationUnit cu= type.getCompilationUnit();
+ // IMethod[] methods= type.getMethods();
+ // GenStubSettings genStubSettings= new GenStubSettings(settings);
+ // genStubSettings.callSuper= true;
+ //
+ // ArrayList newMethods= new ArrayList(superMethods.length);
+ // for (int i= 0; i < superMethods.length; i++) {
+ // IMethod curr= superMethods[i];
+ // if (curr.isConstructor() && (JavaModelUtil.isVisibleInHierarchy(curr,
+ // type.getPackageFragment()))) {
+ // if (JavaModelUtil.findMethod(typeName, curr.getParameterTypes(), true,
+ // methods) == null) {
+ // genStubSettings.methodModifiers= Flags.AccPublic |
+ // JdtFlags.clearAccessModifiers(curr.getFlags());
+ // String newStub= genStub(cu, typeName, curr, curr.getDeclaringType(),
+ // genStubSettings, imports);
+ // newMethods.add(newStub);
+ // }
+ // }
+ // }
+ // return (String[]) newMethods.toArray(new String[newMethods.size()]);
+ // }
+ /**
+ * Returns all unimplemented constructors of a type including root type
+ * default constructors if there are no other superclass constructors
+ * unimplemented.
+ *
+ * @param type
+ * The type to create constructors for
+ * @return Returns the generated stubs or null
if the
+ * creation has been canceled
+ */
+ // public static IMethod[] getOverridableConstructors(IType type) throws
+ // CoreException {
+ // List constructorMethods= new ArrayList();
+ // ITypeHierarchy hierarchy= type.newSupertypeHierarchy(null);
+ // IType supertype= hierarchy.getSuperclass(type);
+ // if (supertype == null)
+ // return (new IMethod[0]);
+ //
+ // IMethod[] superMethods= supertype.getMethods();
+ // boolean constuctorFound= false;
+ // String typeName= type.getElementName();
+ // IMethod[] methods= type.getMethods();
+ // for (int i= 0; i < superMethods.length; i++) {
+ // IMethod curr= superMethods[i];
+ // if (curr.isConstructor()) {
+ // constuctorFound= true;
+ // if (JavaModelUtil.isVisibleInHierarchy(curr, type.getPackageFragment()))
+ // if (JavaModelUtil.findMethod(typeName, curr.getParameterTypes(), true,
+ // methods) == null)
+ // constructorMethods.add(curr);
+ //
+ // }
+ // }
+ //
+ // // http://bugs.eclipse.org/bugs/show_bug.cgi?id=38487
+ // if (!constuctorFound) {
+ // IType objectType= type.getJavaProject().findType("java.lang.Object");
+ // //$NON-NLS-1$
+ // IMethod curr= objectType.getMethod("Object", EMPTY); //$NON-NLS-1$
+ // if (JavaModelUtil.findMethod(typeName, curr.getParameterTypes(), true,
+ // methods) == null) {
+ // constructorMethods.add(curr);
+ // }
+ // }
+ // return (IMethod[]) constructorMethods.toArray(new
+ // IMethod[constructorMethods.size()]);
+ // }
+ /**
+ * Returns all overridable methods of a type
+ *
+ * @param type
+ * The type to search the overridable methods for
+ * @param hierarchy
+ * The type hierarchy of the type
+ * @param isSubType
+ * If set, the result can include methods of the passed type, if
+ * not only methods from super types are considered
+ * @return Returns the all methods that can be overridden
+ */
+ // public static IMethod[] getOverridableMethods(IType type, ITypeHierarchy
+ // hierarchy, boolean isSubType) throws JavaModelException {
+ // List allMethods= new ArrayList();
+ //
+ // IMethod[] typeMethods= type.getMethods();
+ // for (int i= 0; i < typeMethods.length; i++) {
+ // IMethod curr= typeMethods[i];
+ // if (!curr.isConstructor() && !Flags.isStatic(curr.getFlags()) &&
+ // !Flags.isPrivate(curr.getFlags())) {
+ // allMethods.add(curr);
+ // }
+ // }
+ //
+ // IType[] superTypes= hierarchy.getAllSuperclasses(type);
+ // for (int i= 0; i < superTypes.length; i++) {
+ // IMethod[] methods= superTypes[i].getMethods();
+ // for (int k= 0; k < methods.length; k++) {
+ // IMethod curr= methods[k];
+ // if (!curr.isConstructor() && !Flags.isStatic(curr.getFlags()) &&
+ // !Flags.isPrivate(curr.getFlags())) {
+ // if (findMethod(curr, allMethods) == null) {
+ // allMethods.add(curr);
+ // }
+ // }
+ // }
+ // }
+ //
+ // IType[] superInterfaces= hierarchy.getAllSuperInterfaces(type);
+ // for (int i= 0; i < superInterfaces.length; i++) {
+ // IMethod[] methods= superInterfaces[i].getMethods();
+ // for (int k= 0; k < methods.length; k++) {
+ // IMethod curr= methods[k];
+ //
+ // // binary interfaces can contain static initializers (variable
+ // intializations)
+ // // 1G4CKUS
+ // if (!Flags.isStatic(curr.getFlags())) {
+ // IMethod impl= findMethod(curr, allMethods);
+ // if (impl == null || !JavaModelUtil.isVisibleInHierarchy(impl,
+ // type.getPackageFragment()) || prefereInterfaceMethod(hierarchy, curr,
+ // impl)) {
+ // if (impl != null) {
+ // allMethods.remove(impl);
+ // }
+ // // implement an interface method when it does not exist in the hierarchy
+ // // or when it throws less exceptions that the implemented
+ // allMethods.add(curr);
+ // }
+ // }
+ // }
+ // }
+ // if (!isSubType) {
+ // allMethods.removeAll(Arrays.asList(typeMethods));
+ // }
+ // // remove finals
+ // for (int i= allMethods.size() - 1; i >= 0; i--) {
+ // IMethod curr= (IMethod) allMethods.get(i);
+ // if (Flags.isFinal(curr.getFlags())) {
+ // allMethods.remove(i);
+ // }
+ // }
+ // return (IMethod[]) allMethods.toArray(new IMethod[allMethods.size()]);
+ // }
+ // private static boolean prefereInterfaceMethod(ITypeHierarchy hierarchy,
+ // IMethod interfaceMethod, IMethod curr) throws JavaModelException {
+ // if (Flags.isFinal(curr.getFlags())) {
+ // return false;
+ // }
+ // IType interfaceType= interfaceMethod.getDeclaringType();
+ // IType[] interfaces=
+ // hierarchy.getAllSuperInterfaces(curr.getDeclaringType());
+ // for (int i= 0; i < interfaces.length; i++) {
+ // if (interfaces[i] == interfaceType) {
+ // return false;
+ // }
+ // }
+ // return curr.getExceptionTypes().length >
+ // interfaceMethod.getExceptionTypes().length;
+ // }
+ /**
+ * Generate method stubs for methods to overrride
+ *
+ * @param type
+ * The type to search the overridable methods for
+ * @param hierarchy
+ * The type hierarchy of the type
+ * @param methodsToImplement
+ * Methods to override or implement
+ * @param settings
+ * Options for comment generation
+ * @param imports
+ * Required imports are added to the import structure. Structure
+ * can be null
, types are qualified then.
+ * @return Returns the generated stubs
+ */
+ // public static String[] genOverrideStubs(IMethod[] methodsToImplement,
+ // IType type, ITypeHierarchy hierarchy, CodeGenerationSettings settings,
+ // IImportsStructure imports) throws CoreException {
+ // GenStubSettings genStubSettings= new GenStubSettings(settings);
+ // genStubSettings.methodOverwrites= true;
+ // ICompilationUnit cu= type.getCompilationUnit();
+ // String[] result= new String[methodsToImplement.length];
+ // for (int i= 0; i < methodsToImplement.length; i++) {
+ // IMethod curr= methodsToImplement[i];
+ // IMethod overrides=
+ // JavaModelUtil.findMethodImplementationInHierarchy(hierarchy, type,
+ // curr.getElementName(), curr.getParameterTypes(), curr.isConstructor());
+ // if (overrides != null) {
+ // genStubSettings.callSuper= true;
+ // curr= overrides;
+ // }
+ // genStubSettings.methodModifiers= curr.getFlags();
+ // IMethod desc= JavaModelUtil.findMethodDeclarationInHierarchy(hierarchy,
+ // type, curr.getElementName(), curr.getParameterTypes(),
+ // curr.isConstructor());
+ // if (desc == null) {
+ // desc= curr;
+ // }
+ // result[i]= genStub(cu, type.getElementName(), curr,
+ // desc.getDeclaringType(), genStubSettings, imports);
+ // }
+ // return result;
+ // }
+ /**
+ * Searches for unimplemented methods of a type.
+ *
+ * @param isSubType
+ * If set, the evaluation is for a subtype of the given type. If
+ * not set, the evaluation is for the type itself.
+ * @param settings
+ * Options for comment generation
+ * @param imports
+ * Required imports are added to the import structure. Structure
+ * can be null
, types are qualified then.
+ * @return Returns the generated stubs or null
if the
+ * creation has been canceled
+ */
+ // public static String[] evalUnimplementedMethods(IType type,
+ // ITypeHierarchy hierarchy, boolean isSubType, CodeGenerationSettings
+ // settings,
+ // IImportsStructure imports) throws CoreException {
+ //
+ // IMethod[] inheritedMethods= getOverridableMethods(type, hierarchy,
+ // isSubType);
+ //
+ // List toImplement= new ArrayList();
+ // for (int i= 0; i < inheritedMethods.length; i++) {
+ // IMethod curr= inheritedMethods[i];
+ // if (JdtFlags.isAbstract(curr)) {
+ // toImplement.add(curr);
+ // }
+ // }
+ // IMethod[] toImplementArray= (IMethod[]) toImplement.toArray(new
+ // IMethod[toImplement.size()]);
+ // return genOverrideStubs(toImplementArray, type, hierarchy, settings,
+ // imports);
+ // }
+ /**
+ * Examines a string and returns the first line delimiter found.
+ */
+ public static String getLineDelimiterUsed(IJavaElement elem)
+ throws JavaModelException {
+ ICompilationUnit cu = (ICompilationUnit) elem
+ .getAncestor(IJavaElement.COMPILATION_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$
+ }
+
+ /**
+ * Embodies the policy which line delimiter to use when inserting into a
+ * document.
+ */
+ public static String getLineDelimiterFor(IDocument doc) {
+ // new for: 1GF5UU0: ITPJUI:WIN2000 - "Organize Imports" in php editor
+ // inserts lines in wrong format
+ String lineDelim = null;
+ try {
+ lineDelim = doc.getLineDelimiter(0);
+ } catch (BadLocationException e) {
+ }
+ if (lineDelim == null) {
+ String systemDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ String[] lineDelims = doc.getLegalLineDelimiters();
+ for (int i = 0; i < lineDelims.length; i++) {
+ if (lineDelims[i].equals(systemDelimiter)) {
+ lineDelim = systemDelimiter;
+ break;
+ }
+ }
+ if (lineDelim == null) {
+ lineDelim = lineDelims.length > 0 ? lineDelims[0]
+ : systemDelimiter;
+ }
+ }
+ return lineDelim;
+ }
+
+ /**
+ * Evaluates the indention used by a Java element. (in tabulators)
+ */
+ // public static int getIndentUsed(IJavaElement elem) throws
+ // JavaModelException {
+ // if (elem instanceof ISourceReference) {
+ // ICompilationUnit cu= (ICompilationUnit)
+ // elem.getAncestor(IJavaElement.COMPILATION_UNIT);
+ // if (cu != null) {
+ // IBuffer buf= cu.getBuffer();
+ // int offset= ((ISourceReference)elem).getSourceRange().getOffset();
+ // int i= offset;
+ // // find beginning of line
+ // while (i > 0 && !Strings.isLineDelimiterChar(buf.getChar(i - 1)) ){
+ // i--;
+ // }
+ // return Strings.computeIndent(buf.getText(i, offset - i),
+ // CodeFormatterUtil.getTabWidth());
+ // }
+ // }
+ // return 0;
+ // }
+ public static String codeFormat(String sourceString,
+ int initialIndentationLevel, String lineDelim) {
+ ICodeFormatter formatter = ToolFactory.createDefaultCodeFormatter(null);
+ return formatter.format(sourceString, initialIndentationLevel, null,
+ lineDelim);
+ }
+
+ /**
+ * Returns the element after the give element.
+ */
+ // public static IJavaElement findNextSibling(IJavaElement member) throws
+ // JavaModelException {
+ // IJavaElement parent= member.getParent();
+ // if (parent instanceof IParent) {
+ // IJavaElement[] elements= ((IParent)parent).getChildren();
+ // for (int i= elements.length - 2; i >= 0 ; i--) {
+ // if (member.equals(elements[i])) {
+ // return elements[i+1];
+ // }
+ // }
+ // }
+ // return null;
+ // }
+ //
+ public static String getTodoTaskTag(IJavaProject project) {
+ String markers = null;
+ if (project == null) {
+ markers = JavaCore.getOption(JavaCore.COMPILER_TASK_TAGS);
+ } else {
+ markers = project.getOption(JavaCore.COMPILER_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 null;
+ }
+
+ /*
+ * Workarounds for bug 38111
+ */
+ // public static String[] getArgumentNameSuggestions(IJavaProject project,
+ // String baseName, int dimensions, String[] excluded) {
+ // String name= workaround38111(baseName);
+ // String[] res= NamingConventions.suggestArgumentNames(project, "", name,
+ // dimensions, excluded); //$NON-NLS-1$
+ // return sortByLength(res); // longest first
+ // }
+ //
+ // public static String[] getFieldNameSuggestions(IJavaProject project,
+ // String baseName, int dimensions, int modifiers, String[] excluded) {
+ // String name= workaround38111(baseName);
+ // String[] res= NamingConventions.suggestFieldNames(project, "", name,
+ // dimensions, modifiers, excluded); //$NON-NLS-1$
+ // return sortByLength(res); // longest first
+ // }
+ //
+ // public static String[] getLocalNameSuggestions(IJavaProject project,
+ // String baseName, int dimensions, String[] excluded) {
+ // String name= workaround38111(baseName);
+ // String[] res= NamingConventions.suggestLocalVariableNames(project, "",
+ // name, dimensions, excluded); //$NON-NLS-1$
+ // return sortByLength(res); // longest first
+ // }
+ private static String[] sortByLength(String[] proposals) {
+ Arrays.sort(proposals, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((String) o2).length() - ((String) o1).length();
+ }
+ });
+ return proposals;
+ }
+
+ private static String workaround38111(String baseName) {
+ if (BASE_TYPES.contains(baseName))
+ return baseName;
+ return Character.toUpperCase(baseName.charAt(0))
+ + baseName.substring(1);
+ }
+
+ private static final List BASE_TYPES = Arrays
+ .asList(new String[] {
+ "boolean", "byte", "char", "double", "float", "int", "long", "short" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+
+ public static String suggestArgumentName(IJavaProject project,
+ String baseName, String[] excluded) {
+ // String[] argnames= getArgumentNameSuggestions(project, baseName, 0,
+ // excluded);
+ // if (argnames.length > 0) {
+ // return argnames[0];
+ // }
+ return baseName;
+ }
+
+ public static String[] suggestArgumentNames(IJavaProject project,
+ String[] paramNames) {
+ String prefixes = project.getOption(
+ JavaCore.CODEASSIST_ARGUMENT_PREFIXES, true);
+ String suffixes = project.getOption(
+ JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, true);
+ if (prefixes.length() + suffixes.length() == 0) {
+ return paramNames;
+ }
+
+ String[] newNames = new String[paramNames.length];
+ // Ensure that the codegeneration preferences are respected
+ for (int i = 0; i < paramNames.length; i++) {
+ String curr = paramNames[i];
+ if (!hasPrefixOrSuffix(prefixes, suffixes, curr)) {
+ newNames[i] = suggestArgumentName(project, paramNames[i], null);
+ } else {
+ newNames[i] = curr;
+ }
+ }
+ return newNames;
+ }
+
+ public static boolean hasFieldName(IJavaProject project, String name) {
+ String prefixes = project.getOption(JavaCore.CODEASSIST_FIELD_PREFIXES,
+ true);
+ String suffixes = project.getOption(JavaCore.CODEASSIST_FIELD_SUFFIXES,
+ true);
+ String staticPrefixes = project.getOption(
+ JavaCore.CODEASSIST_STATIC_FIELD_PREFIXES, true);
+ String staticSuffixes = project.getOption(
+ JavaCore.CODEASSIST_STATIC_FIELD_SUFFIXES, true);
+
+ return hasPrefixOrSuffix(prefixes, suffixes, name)
+ || hasPrefixOrSuffix(staticPrefixes, staticSuffixes, name);
+ }
+
+ public static boolean hasParameterName(IJavaProject project, String name) {
+ String prefixes = project.getOption(
+ JavaCore.CODEASSIST_ARGUMENT_PREFIXES, true);
+ String suffixes = project.getOption(
+ JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, true);
+ return hasPrefixOrSuffix(prefixes, suffixes, name);
+ }
+
+ public static boolean hasLocalVariableName(IJavaProject project, String name) {
+ String prefixes = project.getOption(JavaCore.CODEASSIST_LOCAL_PREFIXES,
+ true);
+ String suffixes = project.getOption(JavaCore.CODEASSIST_LOCAL_SUFFIXES,
+ true);
+ return hasPrefixOrSuffix(prefixes, suffixes, name);
+ }
+
+ public static boolean hasConstantName(String name) {
+ return Character.isUpperCase(name.charAt(0));
+ }
+
+ private static boolean hasPrefixOrSuffix(String prefixes, String suffixes,
+ String name) {
+ final String listSeparartor = ","; //$NON-NLS-1$
+
+ StringTokenizer tok = new StringTokenizer(prefixes, listSeparartor);
+ while (tok.hasMoreTokens()) {
+ String curr = tok.nextToken();
+ if (name.startsWith(curr)) {
+ return true;
+ }
+ }
+
+ tok = new StringTokenizer(suffixes, listSeparartor);
+ while (tok.hasMoreTokens()) {
+ String curr = tok.nextToken();
+ if (name.endsWith(curr)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplateContext.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplateContext.java
new file mode 100644
index 0000000..3cdda81
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplateContext.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+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;
+
+public class CodeTemplateContext extends TemplateContext {
+
+ private String fLineDelimiter;
+
+ private IJavaProject fProject;
+
+ public CodeTemplateContext(String contextTypeName, IJavaProject project,
+ String lineDelim) {
+ super(WebUI.getDefault().getCodeTemplateContextRegistry()
+ .getContextType(contextTypeName));
+ fLineDelimiter = lineDelim;
+ fProject = project;
+ }
+
+ public IJavaProject getJavaProject() {
+ return fProject;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.TemplateContext#evaluate(net.sourceforge.phpdt.internal.corext.template.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 instanceof CodeTemplateContextType.CodeTemplateVariableResolver) {
+ // 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;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.corext.template.TemplateContext#canEvaluate(net.sourceforge.phpdt.internal.corext.template.Template)
+ */
+ public boolean canEvaluate(Template template) {
+ return true;
+ }
+
+ public void setCompilationUnitVariables(ICompilationUnit cu) {
+ setVariable(CodeTemplateContextType.FILENAME, cu.getElementName());
+ setVariable(CodeTemplateContextType.PACKAGENAME, cu.getParent()
+ .getElementName());
+ setVariable(CodeTemplateContextType.PROJECTNAME, cu.getJavaProject()
+ .getElementName());
+ }
+
+ public void setFileNameVariable(String filename, String projectname) {
+ setVariable(CodeTemplateContextType.FILENAME, filename);
+ setVariable(CodeTemplateContextType.PROJECTNAME, projectname);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplateContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplateContextType.java
new file mode 100644
index 0000000..94dd363
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplateContextType.java
@@ -0,0 +1,528 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.ToolFactory;
+import net.sourceforge.phpdt.core.compiler.IScanner;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+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;
+
+/**
+ */
+public class CodeTemplateContextType extends TemplateContextType {
+
+ /* context types */
+ public static final String CATCHBLOCK_CONTEXTTYPE = "php_catchblock_context"; //$NON-NLS-1$
+
+ public static final String METHODBODY_CONTEXTTYPE = "php_methodbody_context"; //$NON-NLS-1$
+
+ public static final String CONSTRUCTORBODY_CONTEXTTYPE = "php_constructorbody_context"; //$NON-NLS-1$
+
+ public static final String GETTERBODY_CONTEXTTYPE = "php_getterbody_context"; //$NON-NLS-1$
+
+ public static final String SETTERBODY_CONTEXTTYPE = "php_setterbody_context"; //$NON-NLS-1$
+
+ public static final String NEWTYPE_CONTEXTTYPE = "php_newtype_context"; //$NON-NLS-1$
+
+ public static final String NEWHTML_CONTEXTTYPE = "php_newhtml_context"; //$NON-NLS-1$
+
+ public static final String TYPECOMMENT_CONTEXTTYPE = "php_typecomment_context"; //$NON-NLS-1$
+
+ public static final String FIELDCOMMENT_CONTEXTTYPE = "php_fieldcomment_context"; //$NON-NLS-1$
+
+ public static final String METHODCOMMENT_CONTEXTTYPE = "php_methodcomment_context"; //$NON-NLS-1$
+
+ public static final String CONSTRUCTORCOMMENT_CONTEXTTYPE = "php_constructorcomment_context"; //$NON-NLS-1$
+
+ public static final String OVERRIDECOMMENT_CONTEXTTYPE = "php_overridecomment_context"; //$NON-NLS-1$
+
+ public static final String GETTERCOMMENT_CONTEXTTYPE = "php_gettercomment_context"; //$NON-NLS-1$
+
+ public static final String SETTERCOMMENT_CONTEXTTYPE = "php_settercomment_context"; //$NON-NLS-1$
+
+ /* templates */
+ public static final String COMMENT_SUFFIX = "comment"; //$NON-NLS-1$
+
+ public static final String CATCHBLOCK = "catchblock"; //$NON-NLS-1$
+
+ public static final String METHODSTUB = "methodbody"; //$NON-NLS-1$
+
+ public static final String NEWTYPE = "newtype"; //$NON-NLS-1$
+
+ public static final String NEWHTML = "newhtml"; //$NON-NLS-1$
+
+ public static final String CONSTRUCTORSTUB = "constructorbody"; //$NON-NLS-1$
+
+ public static final String GETTERSTUB = "getterbody"; //$NON-NLS-1$
+
+ public static final String SETTERSTUB = "setterbody"; //$NON-NLS-1$
+
+ public static final String TYPECOMMENT = "type" + COMMENT_SUFFIX; //$NON-NLS-1$
+
+ public static final String FIELDCOMMENT = "field" + COMMENT_SUFFIX; //$NON-NLS-1$
+
+ public static final String METHODCOMMENT = "method" + COMMENT_SUFFIX; //$NON-NLS-1$
+
+ public static final String CONSTRUCTORCOMMENT = "constructor" + COMMENT_SUFFIX; //$NON-NLS-1$
+
+ public static final String OVERRIDECOMMENT = "override" + COMMENT_SUFFIX; //$NON-NLS-1$
+
+ public static final String GETTERCOMMENT = "getter" + COMMENT_SUFFIX; //$NON-NLS-1$
+
+ public static final String SETTERCOMMENT = "setter" + COMMENT_SUFFIX; //$NON-NLS-1$
+
+ /* resolver types */
+ public static final String EXCEPTION_TYPE = "exception_type"; //$NON-NLS-1$
+
+ public static final String EXCEPTION_VAR = "exception_var"; //$NON-NLS-1$
+
+ 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 BARE_FIELD_NAME = "bare_field_name"; //$NON-NLS-1$
+
+ public static final String PARAM = "param"; //$NON-NLS-1$
+
+ public static final String RETURN_TYPE = "return_type"; //$NON-NLS-1$
+
+ public static final String SEE_TAG = "see_to_overridden"; //$NON-NLS-1$
+
+ public static final String TAGS = "tags"; //$NON-NLS-1$
+
+ public static final String TYPENAME = "type_name"; //$NON-NLS-1$
+
+ public static final String FILENAME = "file_name"; //$NON-NLS-1$
+
+ public static final String PACKAGENAME = "package_name"; //$NON-NLS-1$
+
+ public static final String PROJECTNAME = "project_name"; //$NON-NLS-1$
+
+ public static final String PACKAGE_DECLARATION = "package_declaration"; //$NON-NLS-1$
+
+ public static final String TYPE_DECLARATION = "type_declaration"; //$NON-NLS-1$
+
+ public static final String TYPE_COMMENT = "typecomment"; //$NON-NLS-1$
+
+ /**
+ * Resolver that resolves to the variable defined in the context.
+ */
+ public static class CodeTemplateVariableResolver extends
+ TemplateVariableResolver {
+ public CodeTemplateVariableResolver(String type, String description) {
+ super(type, description);
+ }
+
+ protected String resolve(TemplateContext context) {
+ return context.getVariable(getType());
+ }
+ }
+
+ /**
+ * Resolver for javadoc tags.
+ */
+ public static class TagsVariableResolver extends TemplateVariableResolver {
+ public TagsVariableResolver() {
+ super(
+ TAGS,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.tags")); //$NON-NLS-1$
+ }
+
+ protected String resolve(TemplateContext context) {
+ return "@"; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Resolver for todo tags.
+ */
+ protected static class Todo extends TemplateVariableResolver {
+
+ public Todo() {
+ super(
+ "todo", JavaTemplateMessages.getString("CodeTemplateContextType.variable.description.todo")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected String resolve(TemplateContext context) {
+ String todoTaskTag = StubUtility
+ .getTodoTaskTag(((CodeTemplateContext) context)
+ .getJavaProject());
+ if (todoTaskTag == null)
+ return "XXX"; //$NON-NLS-1$
+
+ return todoTaskTag;
+ }
+ }
+
+ private boolean fIsComment;
+
+ public CodeTemplateContextType(String contextName) {
+ super(contextName);
+
+ fIsComment = false;
+
+ // global
+ addResolver(new GlobalTemplateVariables.Dollar());
+ addResolver(new GlobalTemplateVariables.Date());
+ addResolver(new GlobalTemplateVariables.Year());
+ addResolver(new GlobalTemplateVariables.Time());
+ addResolver(new GlobalTemplateVariables.User());
+ addResolver(new Todo());
+
+ if (CATCHBLOCK_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ EXCEPTION_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.exceptiontype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ EXCEPTION_VAR,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.exceptionvar"))); //$NON-NLS-1$
+ } else if (METHODBODY_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_METHOD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingmethod"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ BODY_STATEMENT,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.bodystatement"))); //$NON-NLS-1$
+ } else if (CONSTRUCTORBODY_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ BODY_STATEMENT,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.bodystatement"))); //$NON-NLS-1$
+ } else if (GETTERBODY_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_METHOD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingmethod"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.getterfieldname"))); //$NON-NLS-1$
+ } else if (SETTERBODY_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_METHOD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingmethod"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.getterfieldname"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ PARAM,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.param"))); //$NON-NLS-1$
+ } else if (NEWTYPE_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ TYPENAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.typename"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ PACKAGE_DECLARATION,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.packdeclaration"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ TYPE_DECLARATION,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.typedeclaration"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ TYPE_COMMENT,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.typecomment"))); //$NON-NLS-1$
+ addCompilationUnitVariables();
+ } else if (NEWHTML_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ TYPENAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.typename"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ PACKAGE_DECLARATION,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.packdeclaration"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ TYPE_DECLARATION,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.typedeclaration"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ TYPE_COMMENT,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.typecomment"))); //$NON-NLS-1$
+ addCompilationUnitVariables();
+ } else if (TYPECOMMENT_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ TYPENAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.typename"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new TagsVariableResolver());
+ addCompilationUnitVariables();
+ fIsComment = true;
+ } else if (FIELDCOMMENT_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.fieldtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.fieldname"))); //$NON-NLS-1$
+ addCompilationUnitVariables();
+ fIsComment = true;
+ } else if (METHODCOMMENT_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_METHOD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingmethod"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ RETURN_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.returntype"))); //$NON-NLS-1$
+ addResolver(new TagsVariableResolver());
+ addCompilationUnitVariables();
+ fIsComment = true;
+ } else if (OVERRIDECOMMENT_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_METHOD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingmethod"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ SEE_TAG,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.seetag"))); //$NON-NLS-1$
+ addResolver(new TagsVariableResolver());
+ addCompilationUnitVariables();
+ fIsComment = true;
+ } else if (CONSTRUCTORCOMMENT_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new TagsVariableResolver());
+ addCompilationUnitVariables();
+ fIsComment = true;
+ } else if (GETTERCOMMENT_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.getterfieldtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.getterfieldname"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_METHOD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingmethod"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ BARE_FIELD_NAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.barefieldname"))); //$NON-NLS-1$
+ addCompilationUnitVariables();
+ fIsComment = true;
+ } else if (SETTERCOMMENT_CONTEXTTYPE.equals(contextName)) {
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD_TYPE,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.getterfieldtype"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ FIELD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.getterfieldname"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ ENCLOSING_METHOD,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.enclosingmethod"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ PARAM,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.param"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ BARE_FIELD_NAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.barefieldname"))); //$NON-NLS-1$
+ addCompilationUnitVariables();
+ fIsComment = true;
+ }
+ }
+
+ private void addCompilationUnitVariables() {
+ addResolver(new CodeTemplateVariableResolver(
+ FILENAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.filename"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ PACKAGENAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.packagename"))); //$NON-NLS-1$
+ addResolver(new CodeTemplateVariableResolver(
+ PROJECTNAME,
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.variable.description.projectname"))); //$NON-NLS-1$
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.ContextType#validateVariables(net.sourceforge.phpdt.internal.corext.template.TemplateVariable[])
+ */
+ protected void validateVariables(TemplateVariable[] variables)
+ throws TemplateException {
+ ArrayList required = new ArrayList(5);
+ String contextName = getId();
+ // if (NEWTYPE_CONTEXTTYPE.equals(contextName)) {
+ // required.add(PACKAGE_DECLARATION);
+ // required.add(TYPE_DECLARATION);
+ // }
+ for (int i = 0; i < variables.length; i++) {
+ String type = variables[i].getType();
+ if (getResolver(type) == null) {
+ throw new TemplateException(
+ JavaTemplateMessages
+ .getFormattedString(
+ "CodeTemplateContextType.validate.unknownvariable", type)); //$NON-NLS-1$
+ }
+ required.remove(type);
+ }
+ if (!required.isEmpty()) {
+ String missing = (String) required.get(0);
+ throw new TemplateException(
+ JavaTemplateMessages
+ .getFormattedString(
+ "CodeTemplateContextType.validate.missingvariable", missing)); //$NON-NLS-1$
+ }
+ super.validateVariables(variables);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.corext.template.ContextType#createContext()
+ */
+ public TemplateContext createContext() {
+ return null;
+ }
+
+ public static void registerContextTypes(ContextTypeRegistry registry) {
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.CATCHBLOCK_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.METHODBODY_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.CONSTRUCTORBODY_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.GETTERBODY_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.SETTERBODY_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.NEWTYPE_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.NEWHTML_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.OVERRIDECOMMENT_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.GETTERCOMMENT_CONTEXTTYPE));
+ registry.addContextType(new CodeTemplateContextType(
+ CodeTemplateContextType.SETTERCOMMENT_CONTEXTTYPE));
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.ContextType#validate(java.lang.String)
+ */
+ public void validate(String pattern) throws TemplateException {
+ super.validate(pattern);
+ if (fIsComment) {
+ if (!isValidComment(pattern)) {
+ throw new TemplateException(
+ JavaTemplateMessages
+ .getString("CodeTemplateContextType.validate.invalidcomment")); //$NON-NLS-1$
+ }
+ }
+ }
+
+ private boolean isValidComment(String template) {
+ IScanner scanner = ToolFactory.createScanner(true, false, false, true);// false);
+ scanner.setSource(template.toCharArray());
+ try {
+ int next = scanner.getNextToken();
+ while (next == ITerminalSymbols.TokenNameCOMMENT_LINE
+ || next == ITerminalSymbols.TokenNameCOMMENT_PHPDOC
+ || next == ITerminalSymbols.TokenNameCOMMENT_BLOCK) {
+ next = scanner.getNextToken();
+ }
+ return next == ITerminalSymbols.TokenNameEOF;
+ } catch (InvalidInputException e) {
+ }
+ return false;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplates.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplates.java
new file mode 100644
index 0000000..668967a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CodeTemplates.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.text.templates.Template;
+
+/**
+ * CodeTemplates
gives access to the available code templates.
+ *
+ * @since 3.0
+ * @deprecated use
+ * {@link net.sourceforge.phpdt.internal.ui.JavaPlugin#getCodeTemplateStore()}
+ * instead
+ */
+public class CodeTemplates extends
+ net.sourceforge.phpdt.internal.corext.template.php.TemplateSet {
+
+ private static final String DEFAULT_FILE = "default-codetemplates.xml"; //$NON-NLS-1$
+
+ private static final String TEMPLATE_FILE = "codetemplates.xml"; //$NON-NLS-1$
+
+ private static final ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(JavaTemplateMessages.class.getName());
+
+ /** Singleton. */
+ private static CodeTemplates fgTemplates;
+
+ public static Template getCodeTemplate(String name) {
+ return getInstance().getFirstTemplate(name);
+ }
+
+ /**
+ * Returns an instance of templates.
+ */
+ public static CodeTemplates getInstance() {
+ if (fgTemplates == null)
+ fgTemplates = new CodeTemplates();
+
+ return fgTemplates;
+ }
+
+ private CodeTemplates() {
+ super(
+ "codetemplate", WebUI.getDefault().getCodeTemplateContextRegistry()); //$NON-NLS-1$
+ create();
+ }
+
+ private void create() {
+
+ try {
+ addFromStream(getDefaultsAsStream(), false, true, fgResourceBundle);
+ File templateFile = getTemplateFile();
+ if (templateFile.exists()) {
+ addFromFile(templateFile, false, fgResourceBundle);
+ }
+ saveToFile(templateFile);
+
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ clear();
+ }
+
+ }
+
+ /**
+ * Resets the template set.
+ */
+ public void reset() throws CoreException {
+ clear();
+ addFromFile(getTemplateFile(), false, fgResourceBundle);
+ }
+
+ /**
+ * Resets the template set with the default templates.
+ */
+ public void restoreDefaults() throws CoreException {
+ clear();
+ addFromStream(getDefaultsAsStream(), false, true, fgResourceBundle);
+ }
+
+ /**
+ * Saves the template set.
+ */
+ public void save() throws CoreException {
+ saveToFile(getTemplateFile());
+ }
+
+ private static InputStream getDefaultsAsStream() {
+ return CodeTemplates.class.getResourceAsStream(DEFAULT_FILE);
+ }
+
+ private static File getTemplateFile() {
+ IPath path = PHPeclipsePlugin.getDefault().getStateLocation();
+ path = path.append(TEMPLATE_FILE);
+
+ return path.toFile();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitCompletion.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitCompletion.java
new file mode 100644
index 0000000..7684b9d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitCompletion.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import net.sourceforge.phpdt.core.CompletionRequestorAdapter;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+/**
+ * A completion requestor to collect informations on local variables. This class
+ * is used for guessing variable names like arrays, collections, etc.
+ */
+class CompilationUnitCompletion extends CompletionRequestorAdapter {
+
+ static class LocalVariable {
+ String name;
+
+ String typePackageName;
+
+ String typeName;
+
+ LocalVariable(String name, String typePackageName, String typeName) {
+ this.name = name;
+ this.typePackageName = typePackageName;
+ this.typeName = typeName;
+ }
+ }
+
+ private ICompilationUnit fUnit;
+
+ private List fLocalVariables = new ArrayList();
+
+ private Map fTypes = new HashMap();
+
+ private boolean fError;
+
+ /**
+ * Creates a compilation unit completion.
+ *
+ * @param unit
+ * the compilation unit, may be null
.
+ */
+ public CompilationUnitCompletion(ICompilationUnit unit) {
+ reset(unit);
+ }
+
+ /**
+ * Resets the completion requestor.
+ *
+ * @param unit
+ * the compilation unit, may be null
.
+ */
+ public void reset(ICompilationUnit unit) {
+ fUnit = unit;
+
+ fLocalVariables.clear();
+ fTypes.clear();
+
+ fError = false;
+ }
+
+ /*
+ * @see ICompletionRequestor#acceptError(IProblem)
+ */
+ public void acceptError(IProblem error) {
+ fError = true;
+ }
+
+ /*
+ * @see ICodeCompletionRequestor#acceptLocalVariable
+ */
+ public void acceptLocalVariable(char[] name, char[] typePackageName,
+ char[] typeName, int modifiers, int completionStart,
+ int completionEnd, int relevance) {
+ fLocalVariables.add(new LocalVariable(new String(name), new String(
+ typePackageName), new String(typeName)));
+ }
+
+ // ---
+
+ /**
+ * Tests if the code completion process produced errors.
+ */
+ public boolean hasErrors() {
+ return fError;
+ }
+
+ boolean existsLocalName(String name) {
+ for (Iterator iterator = fLocalVariables.iterator(); iterator.hasNext();) {
+ LocalVariable localVariable = (LocalVariable) iterator.next();
+
+ if (localVariable.name.equals(name))
+ return true;
+ }
+
+ return false;
+ }
+
+ String[] getLocalVariableNames() {
+ String[] res = new String[fLocalVariables.size()];
+ int i = 0;
+ for (Iterator iterator = fLocalVariables.iterator(); iterator.hasNext();) {
+ LocalVariable localVariable = (LocalVariable) iterator.next();
+ res[i++] = localVariable.name;
+ }
+ return res;
+ }
+
+ LocalVariable[] findLocalArrays() {
+ Vector vector = new Vector();
+
+ for (Iterator iterator = fLocalVariables.iterator(); iterator.hasNext();) {
+ LocalVariable localVariable = (LocalVariable) iterator.next();
+
+ if (isArray(localVariable.typeName))
+ vector.add(localVariable);
+ }
+
+ return (LocalVariable[]) vector
+ .toArray(new LocalVariable[vector.size()]);
+ }
+
+ // LocalVariable[] findLocalCollections() throws JavaModelException {
+ // Vector vector= new Vector();
+ //
+ // for (Iterator iterator= fLocalVariables.iterator(); iterator.hasNext();)
+ // {
+ // LocalVariable localVariable= (LocalVariable) iterator.next();
+ //
+ // String typeName= qualify(localVariable.typeName);
+ //
+ // if (typeName == null)
+ // continue;
+ //
+ // if (isSubclassOf(typeName, "java.util.Collection")) //$NON-NLS-1$
+ // vector.add(localVariable);
+ // }
+ //
+ // return (LocalVariable[]) vector.toArray(new
+ // LocalVariable[vector.size()]);
+ // }
+
+ String simplifyTypeName(String qualifiedName) {
+ return (String) fTypes.get(qualifiedName);
+ }
+
+ private static boolean isArray(String type) {
+ return type.endsWith("[]"); //$NON-NLS-1$
+ }
+
+ // returns fully qualified name if successful
+ // private String qualify(String typeName) throws JavaModelException {
+ // if (fUnit == null)
+ // return null;
+ //
+ // IType[] types= fUnit.getTypes();
+ //
+ // if (types.length == 0)
+ // return null;
+ //
+ // String[][] resolvedTypeNames= types[0].resolveType(typeName);
+ //
+ // if (resolvedTypeNames == null)
+ // return null;
+ //
+ // return resolvedTypeNames[0][0] + '.' + resolvedTypeNames[0][1];
+ // }
+
+ // type names must be fully qualified
+ // private boolean isSubclassOf(String typeName0, String typeName1) throws
+ // JavaModelException {
+ // if (typeName0.equals(typeName1))
+ // return true;
+ //
+ // if (fUnit == null)
+ // return false;
+ //
+ // IJavaProject project= fUnit.getJavaProject();
+ //
+ // IType type0= project.findType(typeName0);
+ // if (type0 == null)
+ // return false;
+ //
+ // IType type1= project.findType(typeName1);
+ // if (type1 == null)
+ // return false;
+ //
+ // ITypeHierarchy hierarchy= type0.newSupertypeHierarchy(null);
+ // IType[] superTypes= hierarchy.getAllSupertypes(type0);
+ //
+ // for (int i= 0; i < superTypes.length; i++)
+ // if (superTypes[i].equals(type1))
+ // return true;
+ //
+ // return false;
+ // }
+
+ /*
+ * @see net.sourceforge.phpdt.core.ICompletionRequestor#acceptClass(char[],
+ * char[], char[], int, int, int, int)
+ */
+ public void acceptClass(char[] packageName, char[] className,
+ char[] completionName, int modifiers, int completionStart,
+ int completionEnd, int relevance) {
+ final String qualifiedName = createQualifiedTypeName(packageName,
+ className);
+ fTypes.put(qualifiedName, String.valueOf(completionName));
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.ICompletionRequestor#acceptInterface(char[],
+ * char[], char[], int, int, int, int)
+ */
+ public void acceptInterface(char[] packageName, char[] interfaceName,
+ char[] completionName, int modifiers, int completionStart,
+ int completionEnd, int relevance) {
+ final String qualifiedName = createQualifiedTypeName(packageName,
+ interfaceName);
+ fTypes.put(qualifiedName, String.valueOf(completionName));
+ }
+
+ private static String createQualifiedTypeName(char[] packageName,
+ char[] className) {
+ StringBuffer buffer = new StringBuffer();
+
+ if (packageName.length != 0) {
+ buffer.append(packageName);
+ buffer.append('.');
+ }
+ buffer.append(className);
+
+ return buffer.toString();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitContext.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitContext.java
new file mode 100644
index 0000000..a7defad
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitContext.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.text.template.contentassist.MultiVariableGuess;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+// import
+// net.sourceforge.phpdt.internal.ui.text.template.contentassist.MultiVariableGuess;
+
+/**
+ * A compilation unit context.
+ */
+public abstract class CompilationUnitContext extends DocumentTemplateContext {
+
+ /** The compilation unit, may be null
. */
+ private final ICompilationUnit fCompilationUnit;
+
+ /** A flag to force evaluation in head-less mode. */
+ protected boolean fForceEvaluation;
+
+ /** A global state for proposals that change if a master proposal changes. */
+ protected MultiVariableGuess fMultiVariableGuess;
+
+ /**
+ * Creates a compilation unit context.
+ *
+ * @param type
+ * the context type
+ * @param document
+ * the document
+ * @param completionOffset
+ * the completion position within the document
+ * @param completionLength
+ * the completion length within the document
+ * @param compilationUnit
+ * the compilation unit (may be null
)
+ */
+ protected CompilationUnitContext(TemplateContextType type,
+ IDocument document, int completionOffset, int completionLength,
+ ICompilationUnit compilationUnit) {
+ super(type, document, completionOffset, completionLength);
+ fCompilationUnit = compilationUnit;
+ }
+
+ /**
+ * Returns the compilation unit if one is associated with this context,
+ * null
otherwise.
+ */
+ public final ICompilationUnit getCompilationUnit() {
+ return fCompilationUnit;
+ }
+
+ /**
+ * Returns the enclosing element of a particular element type,
+ * null
if no enclosing element of that type exists.
+ */
+ public IJavaElement findEnclosingElement(int elementType) {
+ if (fCompilationUnit == null)
+ return null;
+
+ try {
+ IJavaElement element = fCompilationUnit.getElementAt(getStart());
+ if (element == null) {
+ element = fCompilationUnit;
+ }
+
+ return element.getAncestor(elementType);
+
+ } catch (JavaModelException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Forces evaluation.
+ */
+ public void setForceEvaluation(boolean evaluate) {
+ fForceEvaluation = evaluate;
+ }
+
+ /**
+ * Returns the multivariable guess - state
+ *
+ * @return
+ */
+ public MultiVariableGuess getMultiVariableGuess() {
+ return fMultiVariableGuess;
+ }
+
+ /**
+ * @param multiVariableGuess
+ * The multiVariableGuess to set.
+ */
+ public void setMultiVariableGuess(MultiVariableGuess multiVariableGuess) {
+ fMultiVariableGuess = multiVariableGuess;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitContextType.java
new file mode 100644
index 0000000..085d382
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/CompilationUnitContextType.java
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.Signature;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+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;
+
+/**
+ * Compilation unit context type.
+ */
+public abstract class CompilationUnitContextType extends TemplateContextType {
+
+ protected static class ReturnType extends TemplateVariableResolver {
+ public ReturnType() {
+ super(
+ "return_type", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.return.type")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected String resolve(TemplateContext context) {
+ IJavaElement element = ((CompilationUnitContext) context)
+ .findEnclosingElement(IJavaElement.METHOD);
+ if (element == null)
+ return null;
+
+ try {
+ return Signature.toString(((IMethod) element).getReturnType());
+ } catch (JavaModelException e) {
+ return null;
+ }
+ }
+ }
+
+ protected static class File extends TemplateVariableResolver {
+ public File() {
+ super(
+ "file", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.file")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected String resolve(TemplateContext context) {
+ ICompilationUnit unit = ((CompilationUnitContext) context)
+ .getCompilationUnit();
+
+ return (unit == null) ? null : unit.getElementName();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.templates.TemplateVariableResolver#isUnambiguous(org.eclipse.jface.text.templates.TemplateContext)
+ */
+ protected boolean isUnambiguous(TemplateContext context) {
+ return resolve(context) != null;
+ }
+ }
+
+ protected static class PrimaryTypeName extends TemplateVariableResolver {
+ public PrimaryTypeName() {
+ super(
+ "primary_type_name", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.primary.type.name")); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ protected String resolve(TemplateContext context) {
+ ICompilationUnit unit = ((CompilationUnitContext) context)
+ .getCompilationUnit();
+ if (unit == null)
+ return null;
+ String elementName = unit.getElementName();
+ return elementName.substring(0, elementName.lastIndexOf('.'));
+ }
+
+ /*
+ * @see org.eclipse.jface.text.templates.TemplateVariableResolver#isUnambiguous(org.eclipse.jface.text.templates.TemplateContext)
+ */
+ protected boolean isUnambiguous(TemplateContext context) {
+ return resolve(context) != null;
+ }
+ }
+
+ protected static class EnclosingJavaElement extends
+ TemplateVariableResolver {
+ protected final int fElementType;
+
+ public EnclosingJavaElement(String name, String description,
+ int elementType) {
+ super(name, description);
+ fElementType = elementType;
+ }
+
+ protected String resolve(TemplateContext context) {
+ IJavaElement element = ((CompilationUnitContext) context)
+ .findEnclosingElement(fElementType);
+ return (element == null) ? null : element.getElementName();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.templates.TemplateVariableResolver#isUnambiguous(org.eclipse.jface.text.templates.TemplateContext)
+ */
+ protected boolean isUnambiguous(TemplateContext context) {
+ return resolve(context) != null;
+ }
+ }
+
+ protected static class Method extends EnclosingJavaElement {
+ public Method() {
+ super(
+ "enclosing_method", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.enclosing.method"), IJavaElement.METHOD); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ protected static class Type extends EnclosingJavaElement {
+ public Type() {
+ super(
+ "enclosing_type", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.enclosing.type"), IJavaElement.TYPE); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /*
+ * protected static class SuperClass extends EnclosingJavaElement { public
+ * Type() { super("super_class",
+ * TemplateMessages.getString("JavaContextType.variable.description.type"),
+ * IJavaElement.TYPE); } }
+ */
+ protected static class Package extends EnclosingJavaElement {
+ public Package() {
+ super(
+ "enclosing_package", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.enclosing.package"), IJavaElement.PACKAGE_FRAGMENT); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ protected static class Project extends EnclosingJavaElement {
+ public Project() {
+ super(
+ "enclosing_project", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.enclosing.project"), IJavaElement.JAVA_PROJECT); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /*
+ * protected static class Project2 extends TemplateVariableResolver { public
+ * Project2() { super("project",
+ * TemplateMessages.getString("JavaContextType.variable.description.project")); }
+ * public String evaluate(TemplateContext context) { ICompilationUnit unit=
+ * ((JavaContext) context).getUnit(); return (unit == null) ? null :
+ * unit.getJavaProject().getElementName(); } }
+ */
+ protected static class Arguments extends TemplateVariableResolver {
+ public Arguments() {
+ super(
+ "enclosing_method_arguments", JavaTemplateMessages.getString("CompilationUnitContextType.variable.description.enclosing.method.arguments")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected String resolve(TemplateContext context) {
+ IJavaElement element = ((CompilationUnitContext) context)
+ .findEnclosingElement(IJavaElement.METHOD);
+ if (element == null)
+ return null;
+
+ IMethod method = (IMethod) element;
+
+ try {
+ String[] arguments = method.getParameterNames();
+ StringBuffer buffer = new StringBuffer();
+
+ for (int i = 0; i < arguments.length; i++) {
+ if (i > 0)
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append(arguments[i]);
+ }
+
+ return buffer.toString();
+
+ } catch (JavaModelException e) {
+ return null;
+ }
+ }
+ }
+
+ /*
+ * protected static class Line extends TemplateVariableResolver { public
+ * Line() { super("line",
+ * TemplateMessages.getString("CompilationUnitContextType.variable.description.line")); }
+ * public String evaluate(TemplateContext context) { return
+ * ((JavaTemplateContext) context).guessLineNumber(); } }
+ */
+
+ /*
+ * @see ContextType#ContextType(String)
+ */
+ public CompilationUnitContextType(String name) {
+ super(name);
+ }
+
+ public abstract CompilationUnitContext createContext(IDocument document,
+ int completionPosition, int length, ICompilationUnit compilationUnit);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.corext.template.ContextType#validateVariables(net.sourceforge.phpdt.internal.corext.template.TemplateVariable[])
+ */
+ protected void validateVariables(TemplateVariable[] variables)
+ throws TemplateException {
+ // check for multiple cursor variables
+ for (int i = 0; i < variables.length; i++) {
+ TemplateVariable var = variables[i];
+ if (var.getType().equals(GlobalTemplateVariables.Cursor.NAME)) {
+ if (var.getOffsets().length > 1) {
+ throw new TemplateException(
+ JavaTemplateMessages
+ .getString("ContextType.error.multiple.cursor.variables")); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/HTMLContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/HTMLContextType.java
new file mode 100644
index 0000000..b187c3d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/HTMLContextType.java
@@ -0,0 +1,79 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+// import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateVariable;
+
+/**
+ * A context type for javadoc.
+ */
+public class HTMLContextType extends CompilationUnitContextType {
+
+ /**
+ * Creates a java context type.
+ */
+ public HTMLContextType() {
+ super("html"); //$NON-NLS-1$
+
+ // global
+ addResolver(new GlobalTemplateVariables.Cursor());
+ addResolver(new GlobalTemplateVariables.WordSelection());
+ addResolver(new GlobalTemplateVariables.LineSelection());
+ addResolver(new GlobalTemplateVariables.Dollar());
+ addResolver(new GlobalTemplateVariables.Date());
+ addResolver(new GlobalTemplateVariables.Year());
+ addResolver(new GlobalTemplateVariables.Time());
+ addResolver(new GlobalTemplateVariables.User());
+
+ addResolver(new File());
+ }
+
+ /*
+ * @see ContextType#createContext()
+ */
+ public CompilationUnitContext createContext(IDocument document, int offset,
+ int length, ICompilationUnit compilationUnit) {
+ return new HTMLUnitContext(this, document, offset, length,
+ compilationUnit);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.corext.template.java.CompilationUnitContextType#createContext(org.eclipse.jface.text.IDocument,
+ * int, int, net.sourceforge.phpdt.core.ICompilationUnit)
+ */
+ // public CompilationUnitContext createContext(IDocument document, int
+ // offset, int length, ICompilationUnit compilationUnit) {
+ // return new JavaDocContext(this, document, offset, length,
+ // compilationUnit);
+ // }
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.corext.template.ContextType#validateVariables(net.sourceforge.phpdt.internal.corext.template.TemplateVariable[])
+ */
+ protected void validateVariables(TemplateVariable[] variables)
+ throws TemplateException {
+ // check for multiple cursor variables
+ for (int i = 0; i < variables.length; i++) {
+ TemplateVariable var = variables[i];
+ if (var.getType().equals(GlobalTemplateVariables.Cursor.NAME)) {
+ if (var.getOffsets().length > 1) {
+ throw new TemplateException(
+ JavaTemplateMessages
+ .getString("ContextType.error.multiple.cursor.variables")); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/HTMLUnitContext.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/HTMLUnitContext.java
new file mode 100644
index 0000000..bbd35b7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/HTMLUnitContext.java
@@ -0,0 +1,175 @@
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateTranslator;
+
+/**
+ * A context for javadoc.
+ */
+public class HTMLUnitContext extends CompilationUnitContext {
+
+ // tags
+ // private static final char HTML_TAG_BEGIN= '<';
+ // private static final char HTML_TAG_END= '>';
+ // private static final char JAVADOC_TAG_BEGIN= '@';
+ /**
+ * special characters '&' for the start of HTML entities '<' for the start
+ * of HTML tags '#' for the start of colour attributes '{' for the start of
+ * smarty partitions inside HTML code
+ */
+ private static final String specialChars = "&<#{";
+
+ /**
+ * Creates a javadoc template context.
+ *
+ * @param type
+ * the context type.
+ * @param document
+ * the document.
+ * @param completionOffset
+ * the completion offset within the document.
+ * @param completionLength
+ * the completion length within the document.
+ * @param compilationUnit
+ * the compilation unit (may be null
).
+ */
+ public HTMLUnitContext(TemplateContextType type, IDocument document,
+ int completionOffset, int completionLength,
+ ICompilationUnit compilationUnit) {
+ super(type, document, completionOffset, completionLength,
+ compilationUnit);
+ }
+
+ /*
+ * @see TemplateContext#canEvaluate(Template templates)
+ */
+ public boolean canEvaluate(Template template) {
+ String key = getKey();
+
+ if (fForceEvaluation)
+ return true;
+
+ return template.matches(key, getContextType().getId())
+ && (key.length() != 0)
+ && template.getName().toLowerCase().startsWith(
+ key.toLowerCase());
+ }
+
+ /*
+ * @see DocumentTemplateContext#getCompletionPosition();
+ */
+ public int getStart() {
+ IDocument document = getDocument();
+ try {
+ int start = getCompletionOffset();
+ char ch = ' ';
+ while (start != 0) {
+ ch = document.getChar(start - 1);
+ if (specialChars.indexOf(ch) != (-1)) {
+ return --start;
+ }
+ if (Character.isUnicodeIdentifierPart(ch)) {
+ start--;
+ } else {
+ break;
+ }
+ }
+ if ((start != 0)
+ && Character.isUnicodeIdentifierStart(document
+ .getChar(start - 1))) {
+ start--;
+ if ((start != 0)
+ && specialChars.indexOf(document.getChar(start - 1)) != (-1)) {
+ start--;
+ }
+ }
+
+ // while (((start != 0)
+ // && Character.isUnicodeIdentifierPart(document.getChar(start -
+ // 1)))
+ // || ((start != 0)
+ // && specialChars.indexOf(document.getChar(start - 1)) != (-1))) {
+ // start--;
+ // }
+ //
+ // if (((start != 0)
+ // && Character.isUnicodeIdentifierStart(document.getChar(start -
+ // 1)))
+ // || ((start != 0)
+ // && specialChars.indexOf(document.getChar(start - 1)) != (-1))) {
+ // start--;
+ // }
+
+ return start;
+
+ } catch (BadLocationException e) {
+ return getCompletionOffset();
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getEnd()
+ */
+ public int getEnd() {
+
+ if (getCompletionLength() == 0)
+ return super.getEnd();
+
+ try {
+ IDocument document = getDocument();
+
+ int start = getCompletionOffset();
+ int end = getCompletionOffset() + getCompletionLength();
+
+ while (start != end
+ && Character.isWhitespace(document.getChar(end - 1)))
+ end--;
+
+ return end;
+
+ } catch (BadLocationException e) {
+ return super.getEnd();
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getKey()
+ */
+ public String getKey() {
+
+ if (getCompletionLength() == 0)
+ return super.getKey();
+
+ try {
+ IDocument document = getDocument();
+
+ int start = getStart();
+ int end = getCompletionOffset();
+ return start <= end ? document.get(start, end - start) : ""; //$NON-NLS-1$
+
+ } catch (BadLocationException e) {
+ return super.getKey();
+ }
+ }
+
+ /*
+ * @see TemplateContext#evaluate(Template)
+ */
+ public TemplateBuffer evaluate(Template template)
+ throws BadLocationException, TemplateException {
+ TemplateTranslator translator = new TemplateTranslator();
+ TemplateBuffer buffer = translator.translate(template);
+
+ getContextType().resolve(buffer, this);
+
+ return buffer;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaContext.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaContext.java
new file mode 100644
index 0000000..0102646
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaContext.java
@@ -0,0 +1,664 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.internal.corext.Assert;
+import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitCompletion.LocalVariable;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+import net.sourceforge.phpdt.internal.ui.preferences.CodeFormatterPreferencePage;
+import net.sourceforge.phpdt.internal.ui.text.template.contentassist.MultiVariable;
+import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateTranslator;
+import org.eclipse.jface.text.templates.TemplateVariable;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A context for java source.
+ */
+public class JavaContext extends CompilationUnitContext {
+
+ /** The platform default line delimiter. */
+ private static final String PLATFORM_LINE_DELIMITER = System
+ .getProperty("line.separator"); //$NON-NLS-1$
+
+ /** A code completion requestor for guessing local variable names. */
+ private CompilationUnitCompletion fCompletion;
+
+ /**
+ * Creates a java template context.
+ *
+ * @param type
+ * the context type.
+ * @param document
+ * the document.
+ * @param completionOffset
+ * the completion offset within the document.
+ * @param completionLength
+ * the completion length.
+ * @param compilationUnit
+ * the compilation unit (may be null
).
+ */
+ public JavaContext(TemplateContextType type, IDocument document,
+ int completionOffset, int completionLength,
+ ICompilationUnit compilationUnit) {
+ super(type, document, completionOffset, completionLength,
+ compilationUnit);
+ }
+
+ /**
+ * Returns the indentation level at the position of code completion.
+ */
+ private int getIndentation() {
+ int start = getStart();
+ IDocument document = getDocument();
+ try {
+ IRegion region = document.getLineInformationOfOffset(start);
+ String lineContent = document.get(region.getOffset(), region
+ .getLength());
+ return Strings.computeIndent(lineContent,
+ CodeFormatterPreferencePage.getTabSize());
+ // return Strings.computeIndent(lineContent,
+ // CodeFormatterUtil.getTabWidth());
+ } catch (BadLocationException e) {
+ return 0;
+ }
+ }
+
+ /*
+ * @see TemplateContext#evaluate(Template template)
+ */
+ public TemplateBuffer evaluate(Template template)
+ throws BadLocationException, TemplateException {
+
+ if (!canEvaluate(template))
+ throw new TemplateException(JavaTemplateMessages
+ .getString("Context.error.cannot.evaluate")); //$NON-NLS-1$
+
+ TemplateTranslator translator = new TemplateTranslator() {
+ /*
+ * @see org.eclipse.jface.text.templates.TemplateTranslator#createVariable(java.lang.String,
+ * java.lang.String, int[])
+ */
+ protected TemplateVariable createVariable(String type, String name,
+ int[] offsets) {
+ return new MultiVariable(type, name, offsets);
+ }
+ };
+ TemplateBuffer buffer = translator.translate(template);
+
+ getContextType().resolve(buffer, this);
+ String lineDelimiter = null;
+ try {
+ lineDelimiter = getDocument().getLineDelimiter(0);
+ } catch (BadLocationException e) {
+ }
+
+ if (lineDelimiter == null)
+ lineDelimiter = PLATFORM_LINE_DELIMITER;
+ IPreferenceStore prefs = WebUI.getDefault()
+ .getPreferenceStore();
+ // axelcl start
+ // boolean useCodeFormatter =
+ // prefs.getBoolean(PreferenceConstants.TEMPLATES_USE_CODEFORMATTER);
+ boolean useCodeFormatter = false;
+ // axelcl end
+
+ JavaFormatter formatter = new JavaFormatter(lineDelimiter,
+ getIndentation(), useCodeFormatter);
+ formatter.format(buffer, this);
+ // debug start
+ // String res = buffer.getString();
+ // res = res.replaceAll("\n","/n");
+ // res = res.replaceAll("\t","/t");
+ // System.out.println(res);
+ // debug end
+ return buffer;
+ }
+
+ /*
+ * @see TemplateContext#canEvaluate(Template templates)
+ */
+ public boolean canEvaluate(Template template) {
+ String key = getKey();
+
+ if (fForceEvaluation)
+ return true;
+
+ return template.matches(key, getContextType().getId())
+ && key.length() != 0
+ && template.getName().toLowerCase().startsWith(
+ key.toLowerCase());
+ }
+
+ public boolean canEvaluate(String identifier) {
+ String prefix = getKey();
+ return identifier.toLowerCase().startsWith(prefix.toLowerCase());
+ }
+
+ /*
+ * @see DocumentTemplateContext#getCompletionPosition();
+ */
+ public int getStart() {
+
+ try {
+ IDocument document = getDocument();
+
+ if (getCompletionLength() == 0) {
+
+ int start = getCompletionOffset();
+ while ((start != 0)
+ && Character.isUnicodeIdentifierPart(document
+ .getChar(start - 1)))
+ start--;
+
+ if ((start != 0)
+ && (Character.isUnicodeIdentifierStart(document
+ .getChar(start - 1)) || (document
+ .getChar(start - 1) == '$')))
+ start--;
+
+ return start;
+
+ } else {
+
+ int start = getCompletionOffset();
+ int end = getCompletionOffset() + getCompletionLength();
+
+ while (start != 0
+ && Character.isUnicodeIdentifierPart(document
+ .getChar(start - 1)))
+ start--;
+ if ((start != 0)
+ && (Character.isUnicodeIdentifierStart(document
+ .getChar(start - 1)) || (document
+ .getChar(start - 1) == '$')))
+ start--;
+ while (start != end
+ && Character.isWhitespace(document.getChar(start)))
+ start++;
+
+ if (start == end)
+ start = getCompletionOffset();
+
+ return start;
+ }
+
+ } catch (BadLocationException e) {
+ return super.getStart();
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getEnd()
+ */
+ public int getEnd() {
+
+ if (getCompletionLength() == 0)
+ return super.getEnd();
+
+ try {
+ IDocument document = getDocument();
+
+ int start = getCompletionOffset();
+ int end = getCompletionOffset() + getCompletionLength();
+
+ while (start != end
+ && Character.isWhitespace(document.getChar(end - 1)))
+ end--;
+
+ return end;
+
+ } catch (BadLocationException e) {
+ return super.getEnd();
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getKey()
+ */
+ public String getKey() {
+
+ // if (getCompletionLength() == 0) {
+ // return super.getKey();
+ // }
+
+ try {
+ IDocument document = getDocument();
+
+ int start = getStart();
+ int end = getCompletionOffset();
+ return start <= end ? document.get(start, end - start) : ""; //$NON-NLS-1$
+
+ } catch (BadLocationException e) {
+ return super.getKey();
+ }
+ }
+
+ /**
+ * Returns the character before start position of completion.
+ */
+ public char getCharacterBeforeStart() {
+ int start = getStart();
+
+ try {
+ return start == 0 ? ' ' : getDocument().getChar(start - 1);
+
+ } catch (BadLocationException e) {
+ return ' ';
+ }
+ }
+
+ private static void handleException(Shell shell, Exception e) {
+ String title = JavaTemplateMessages
+ .getString("JavaContext.error.title"); //$NON-NLS-1$
+ if (e instanceof CoreException)
+ ExceptionHandler.handle((CoreException) e, shell, title, null);
+ else if (e instanceof InvocationTargetException)
+ ExceptionHandler.handle((InvocationTargetException) e, shell,
+ title, null);
+ else {
+ PHPeclipsePlugin.log(e);
+ MessageDialog.openError(shell, title, e.getMessage());
+ }
+ }
+
+ // private CompilationUnitCompletion getCompletion() {
+ // ICompilationUnit compilationUnit= getCompilationUnit();
+ // if (fCompletion == null) {
+ // fCompletion= new CompilationUnitCompletion(compilationUnit);
+ //
+ // if (compilationUnit != null) {
+ // try {
+ // compilationUnit.codeComplete(getStart(), fCompletion);
+ // } catch (JavaModelException e) {
+ // // ignore
+ // }
+ // }
+ // }
+ //
+ // return fCompletion;
+ // }
+
+ /**
+ * Returns the name of a guessed local array, null
if no
+ * local array exists.
+ */
+ // public String guessArray() {
+ // return firstOrNull(guessArrays());
+ // }
+ /**
+ * Returns the name of a guessed local array, null
if no
+ * local array exists.
+ */
+ // public String[] guessArrays() {
+ // CompilationUnitCompletion completion= getCompletion();
+ // LocalVariable[] localArrays= completion.findLocalArrays();
+ //
+ // String[] ret= new String[localArrays.length];
+ // for (int i= 0; i < ret.length; i++) {
+ // ret[ret.length - i - 1]= localArrays[i].name;
+ // }
+ // return ret;
+ // }
+ /**
+ * Returns the name of the type of a local array, null
if no
+ * local array exists.
+ */
+ // public String guessArrayType() {
+ // return firstOrNull(guessArrayTypes());
+ // }
+ private String firstOrNull(String[] strings) {
+ if (strings.length > 0)
+ return strings[0];
+ else
+ return null;
+ }
+
+ /**
+ * Returns the name of the type of a local array, null
if no
+ * local array exists.
+ */
+ // public String[][] guessGroupedArrayTypes() {
+ // CompilationUnitCompletion completion= getCompletion();
+ // LocalVariable[] localArrays= completion.findLocalArrays();
+ //
+ // String[][] ret= new String[localArrays.length][];
+ //
+ // for (int i= 0; i < localArrays.length; i++) {
+ // String type= getArrayTypeFromLocalArray(completion,
+ // localArrays[localArrays.length - i - 1]);
+ // ret[i]= new String[] {type};
+ // }
+ //
+ // return ret;
+ // }
+ /**
+ * Returns the name of the type of a local array, null
if no
+ * local array exists.
+ */
+ // public String[] guessArrayTypes() {
+ // CompilationUnitCompletion completion= getCompletion();
+ // LocalVariable[] localArrays= completion.findLocalArrays();
+ //
+ // List ret= new ArrayList();
+ //
+ // for (int i= 0; i < localArrays.length; i++) {
+ // String type= getArrayTypeFromLocalArray(completion,
+ // localArrays[localArrays.length - i - 1]);
+ // if (!ret.contains(type))
+ // ret.add(type);
+ // }
+ //
+ // return (String[]) ret.toArray(new String[ret.size()]);
+ // }
+ private String getArrayTypeFromLocalArray(
+ CompilationUnitCompletion completion, LocalVariable array) {
+ String arrayTypeName = array.typeName;
+ String typeName = getScalarType(arrayTypeName);
+ int dimension = getArrayDimension(arrayTypeName) - 1;
+ Assert.isTrue(dimension >= 0);
+
+ String qualifiedName = createQualifiedTypeName(array.typePackageName,
+ typeName);
+ String innerTypeName = completion.simplifyTypeName(qualifiedName);
+
+ return innerTypeName == null ? createArray(typeName, dimension)
+ : createArray(innerTypeName, dimension);
+ }
+
+ private static String createArray(String type, int dimension) {
+ StringBuffer buffer = new StringBuffer(type);
+ for (int i = 0; i < dimension; i++)
+ buffer.append("[]"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+
+ private static String getScalarType(String type) {
+ return type.substring(0, type.indexOf('['));
+ }
+
+ private static int getArrayDimension(String type) {
+
+ int dimension = 0;
+ int index = type.indexOf('[');
+
+ while (index != -1) {
+ dimension++;
+ index = type.indexOf('[', index + 1);
+ }
+
+ return dimension;
+ }
+
+ private static String createQualifiedTypeName(String packageName,
+ String className) {
+ StringBuffer buffer = new StringBuffer();
+
+ if (packageName.length() != 0) {
+ buffer.append(packageName);
+ buffer.append('.');
+ }
+ buffer.append(className);
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns a proposal for a variable name of a local array element,
+ * null
if no local array exists.
+ */
+ // public String guessArrayElement() {
+ // return firstOrNull(guessArrayElements());
+ // }
+ /**
+ * Returns a proposal for a variable name of a local array element,
+ * null
if no local array exists.
+ */
+ // public String[] guessArrayElements() {
+ // ICompilationUnit cu= getCompilationUnit();
+ // if (cu == null) {
+ // return new String[0];
+ // }
+ //
+ // CompilationUnitCompletion completion= getCompletion();
+ // LocalVariable[] localArrays= completion.findLocalArrays();
+ //
+ // List ret= new ArrayList();
+ //
+ // for (int i= 0; i < localArrays.length; i++) {
+ // int idx= localArrays.length - i - 1;
+ //
+ // LocalVariable var= localArrays[idx];
+ //
+ // IJavaProject project= cu.getJavaProject();
+ // String typeName= var.typeName;
+ // String baseTypeName= typeName.substring(0, typeName.lastIndexOf('['));
+ //
+ // String indexName= getIndex();
+ // String[] excludedNames= completion.getLocalVariableNames();
+ // if (indexName != null) {
+ // ArrayList excludedNamesList= new ArrayList(Arrays.asList(excludedNames));
+ // excludedNamesList.add(indexName);
+ // excludedNames= (String[])excludedNamesList.toArray(new
+ // String[excludedNamesList.size()]);
+ // }
+ // String[] proposals= NamingConventions.suggestLocalVariableNames(project,
+ // var.typePackageName, baseTypeName, 0, excludedNames);
+ // for (int j= 0; j < proposals.length; j++) {
+ // if (!ret.contains(proposals[j]))
+ // ret.add(proposals[j]);
+ // }
+ // }
+ //
+ // return (String[]) ret.toArray(new String[ret.size()]);
+ // }
+ /**
+ * Returns a proposal for a variable name of a local array element,
+ * null
if no local array exists.
+ */
+ // public String[][] guessGroupedArrayElements() {
+ // ICompilationUnit cu= getCompilationUnit();
+ // if (cu == null) {
+ // return new String[0][];
+ // }
+ //
+ // CompilationUnitCompletion completion= getCompletion();
+ // LocalVariable[] localArrays= completion.findLocalArrays();
+ //
+ // String[][] ret= new String[localArrays.length][];
+ //
+ // for (int i= 0; i < localArrays.length; i++) {
+ // int idx= localArrays.length - i - 1;
+ //
+ // LocalVariable var= localArrays[idx];
+ //
+ // IJavaProject project= cu.getJavaProject();
+ // String typeName= var.typeName;
+ // int dim= -1; // we expect at least one array
+ // int lastIndex= typeName.length();
+ // int bracket= typeName.lastIndexOf('[');
+ // while (bracket != -1) {
+ // lastIndex= bracket;
+ // dim++;
+ // bracket= typeName.lastIndexOf('[', bracket - 1);
+ // }
+ // typeName= typeName.substring(0, lastIndex);
+ //
+ // String indexName= getIndex();
+ // String[] excludedNames= completion.getLocalVariableNames();
+ // if (indexName != null) {
+ // ArrayList excludedNamesList= new ArrayList(Arrays.asList(excludedNames));
+ // excludedNamesList.add(indexName);
+ // excludedNames= (String[])excludedNamesList.toArray(new
+ // String[excludedNamesList.size()]);
+ // }
+ // String[] proposals= NamingConventions.suggestLocalVariableNames(project,
+ // var.typePackageName, typeName, dim, excludedNames);
+ //
+ // ret[i]= proposals;
+ // }
+ //
+ // return ret;
+ // }
+ /**
+ * Returns an array index name. 'i', 'j', 'k' are tried until no name
+ * collision with an existing local variable occurs. If all names collide,
+ * null
is returned.
+ */
+ // public String getIndex() {
+ // CompilationUnitCompletion completion= getCompletion();
+ // String[] proposals= {"i", "j", "k"}; //$NON-NLS-1$ //$NON-NLS-2$
+ // //$NON-NLS-3$
+ //
+ // for (int i= 0; i != proposals.length; i++) {
+ // String proposal = proposals[i];
+ //
+ // if (!completion.existsLocalName(proposal))
+ // return proposal;
+ // }
+ //
+ // return null;
+ // }
+ /**
+ * Returns the name of a local collection, null
if no local
+ * collection exists.
+ */
+ // public String guessCollection() {
+ // return firstOrNull(guessCollections());
+ // }
+ /**
+ * Returns the names of local collections.
+ */
+ // public String[] guessCollections() {
+ // CompilationUnitCompletion completion= getCompletion();
+ // try {
+ // LocalVariable[] localCollections= completion.findLocalCollections();
+ // String[] ret= new String[localCollections.length];
+ // for (int i= 0; i < ret.length; i++) {
+ // ret[ret.length - i - 1]= localCollections[i].name;
+ // }
+ //
+ // return ret;
+ //
+ // } catch (JavaModelException e) {
+ // JavaPlugin.log(e);
+ // }
+ //
+ // return new String[0];
+ // }
+ /**
+ * Returns an iterator name ('iter'). If 'iter' already exists as local
+ * variable, null
is returned.
+ */
+ // public String getIterator() {
+ // CompilationUnitCompletion completion= getCompletion();
+ // String[] proposals= {"iter"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ //
+ // for (int i= 0; i != proposals.length; i++) {
+ // String proposal = proposals[i];
+ //
+ // if (!completion.existsLocalName(proposal))
+ // return proposal;
+ // }
+ //
+ // return null;
+ // }
+ // public void addIteratorImport() {
+ // ICompilationUnit cu= getCompilationUnit();
+ // if (cu == null) {
+ // return;
+ // }
+ //
+ // try {
+ // Position position= new Position(getCompletionOffset(),
+ // getCompletionLength());
+ // IDocument document= getDocument();
+ // final String category= "__template_position_importer" +
+ // System.currentTimeMillis(); //$NON-NLS-1$
+ // IPositionUpdater updater= new DefaultPositionUpdater(category);
+ // document.addPositionCategory(category);
+ // document.addPositionUpdater(updater);
+ // document.addPosition(position);
+ //
+ // CodeGenerationSettings settings=
+ // JavaPreferencesSettings.getCodeGenerationSettings();
+ // ImportsStructure structure= new ImportsStructure(cu,
+ // settings.importOrder, settings.importThreshold, true);
+ // structure.addImport("java.util.Iterator"); //$NON-NLS-1$
+ // structure.create(false, null);
+ //
+ // document.removePosition(position);
+ // document.removePositionUpdater(updater);
+ // document.removePositionCategory(category);
+ //
+ // setCompletionOffset(position.getOffset());
+ // setCompletionLength(position.getLength());
+ //
+ // } catch (CoreException e) {
+ // handleException(null, e);
+ // } catch (BadLocationException e) {
+ // handleException(null, e);
+ // } catch (BadPositionCategoryException e) {
+ // handleException(null, e);
+ // }
+ // }
+ /**
+ * Evaluates a 'java' template in thecontext of a compilation unit
+ */
+ public static String evaluateTemplate(Template template,
+ ICompilationUnit compilationUnit, int position)
+ throws CoreException, BadLocationException, TemplateException {
+
+ TemplateContextType contextType = WebUI.getDefault()
+ .getTemplateContextRegistry().getContextType("java"); //$NON-NLS-1$
+ if (contextType == null)
+ throw new CoreException(
+ new Status(
+ IStatus.ERROR,
+ PHPeclipsePlugin.PLUGIN_ID,
+ IStatus.ERROR,
+ JavaTemplateMessages
+ .getString("JavaContext.error.message"), null)); //$NON-NLS-1$
+
+ IDocument document = new Document();
+ if (compilationUnit != null && compilationUnit.exists())
+ document.set(compilationUnit.getSource());
+
+ JavaContext context = new JavaContext(contextType, document, position,
+ 0, compilationUnit);
+ context.setForceEvaluation(true);
+
+ TemplateBuffer buffer = context.evaluate(template);
+ if (buffer == null)
+ return null;
+ return buffer.getString();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaContextType.java
new file mode 100644
index 0000000..f121bdf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaContextType.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2000, orporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Sebastian Davids: sdavids@gmx.de - see bug 25376
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateVariableResolver;
+
+/**
+ * A context type for java code.
+ */
+public class JavaContextType extends CompilationUnitContextType {
+
+ public static final String NAME = "php"; //$NON-NLS-1$
+
+ // protected static class Array extends TemplateVariableResolver {
+ // public Array() {
+ // super("array",
+ // TemplateMessages.getString("JavaContextType.variable.description.array"));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ // protected String[] resolveAll(TemplateContext context) {
+ // return ((JavaContext) context).guessArrays();
+ // }
+ // /*
+ // * @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) {
+ // if (variable instanceof MultiVariable) {
+ // JavaContext jc= (JavaContext) context;
+ // MultiVariable mv= (MultiVariable) variable;
+ // String[] bindings= resolveAll(context);
+ // if (bindings.length > 0) {
+ // mv.setValues(bindings);
+ // MultiVariableGuess guess= jc.getMultiVariableGuess();
+ // if (guess == null) {
+ // guess= new MultiVariableGuess(mv);
+ // jc.setMultiVariableGuess(guess);
+ // }
+ // }
+ // if (bindings.length > 1)
+ // variable.setUnambiguous(false);
+ // else
+ // variable.setUnambiguous(isUnambiguous(context));
+ // } else
+ // super.resolve(variable, context);
+ // }
+ // }
+ //
+ // protected static class ArrayType extends TemplateVariableResolver {
+ // public ArrayType() {
+ // super("array_type",
+ // TemplateMessages.getString("JavaContextType.variable.description.array.type"));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ // protected String[] resolveAll(TemplateContext context) {
+ //
+ // String[] arrayTypes= ((JavaContext) context).guessArrayTypes();
+ // if (arrayTypes != null)
+ // return arrayTypes;
+ // else
+ // return super.resolveAll(context);
+ // }
+ //
+ // /*
+ // * @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) {
+ // if (variable instanceof MultiVariable) {
+ // MultiVariable mv= (MultiVariable) variable;
+ // String[] arrays= ((JavaContext) context).guessArrays();
+ // String[][] types= ((JavaContext) context).guessGroupedArrayTypes();
+ //
+ // for (int i= 0; i < arrays.length; i++) {
+ // mv.setValues(arrays[i], types[i]);
+ // }
+ //
+ // if (arrays.length > 1 || types.length == 1 && types[0].length > 1)
+ // variable.setUnambiguous(false);
+ // else
+ // variable.setUnambiguous(isUnambiguous(context));
+ //
+ // } else
+ // super.resolve(variable, context);
+ // }
+ // }
+ //
+ // protected static class ArrayElement extends TemplateVariableResolver {
+ // public ArrayElement() {
+ // super("array_element",
+ // TemplateMessages.getString("JavaContextType.variable.description.array.element"));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ // protected String[] resolveAll(TemplateContext context) {
+ // return ((JavaContext) context).guessArrayElements();
+ // }
+ //
+ // /*
+ // * @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) {
+ // if (variable instanceof MultiVariable) {
+ // MultiVariable mv= (MultiVariable) variable;
+ // String[] arrays= ((JavaContext) context).guessArrays();
+ // String[][] elems= ((JavaContext) context).guessGroupedArrayElements();
+ //
+ // for (int i= 0; i < arrays.length; i++) {
+ // mv.setValues(arrays[i], elems[i]);
+ // }
+ //
+ // if (arrays.length > 1 || elems.length == 1 && elems[0].length > 1)
+ // variable.setUnambiguous(false);
+ // else
+ // variable.setUnambiguous(isUnambiguous(context));
+ //
+ // } else
+ // super.resolve(variable, context);
+ // }
+ // }
+ //
+ // protected static class Index extends TemplateVariableResolver {
+ // public Index() {
+ // super("index",
+ // TemplateMessages.getString("JavaContextType.variable.description.index"));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ // protected String resolve(TemplateContext context) {
+ // return ((JavaContext) context).getIndex();
+ // }
+ // }
+ //
+ // protected static class Collection extends TemplateVariableResolver {
+ // public Collection() {
+ // super("collection",
+ // TemplateMessages.getString("JavaContextType.variable.description.collection"));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ //
+ // protected String[] resolveAll(TemplateContext context) {
+ // String[] collections= ((JavaContext) context).guessCollections();
+ // if (collections.length > 0)
+ // return collections;
+ // else
+ // return super.resolveAll(context);
+ // }
+ // }
+ //
+ // protected static class Iterator extends TemplateVariableResolver {
+ //
+ // public Iterator() {
+ // super("iterator",
+ // TemplateMessages.getString("JavaContextType.variable.description.iterator"));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ // protected String resolve(TemplateContext context) {
+ // JavaContext javaContext= (JavaContext) context;
+ //
+ // if (!context.isReadOnly())
+ // javaContext.addIteratorImport();
+ //
+ // return javaContext.getIterator();
+ // }
+ // }
+ //
+ protected static class Todo extends TemplateVariableResolver {
+
+ public Todo() {
+ super(
+ "todo", JavaTemplateMessages.getString("JavaContextType.variable.description.todo")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected String resolve(TemplateContext context) {
+ JavaContext javaContext = (JavaContext) context;
+ ICompilationUnit compilationUnit = javaContext.getCompilationUnit();
+ if (compilationUnit == null)
+ return "XXX"; //$NON-NLS-1$
+
+ IJavaProject javaProject = compilationUnit.getJavaProject();
+ String todoTaskTag = StubUtility.getTodoTaskTag(javaProject);
+ if (todoTaskTag == null)
+ return "XXX"; //$NON-NLS-1$
+
+ return todoTaskTag;
+ }
+ }
+
+ /*
+ * protected static class Arguments extends SimpleVariableResolver { public
+ * Arguments() { super("arguments",
+ * TemplateMessages.getString("JavaContextType.variable.description.arguments"),
+ * ""); } }
+ */
+
+ /**
+ * Creates a java context type.
+ */
+ public JavaContextType() {
+ super(NAME);
+
+ // global
+ addResolver(new GlobalTemplateVariables.Cursor());
+ addResolver(new GlobalTemplateVariables.WordSelection());
+ addResolver(new GlobalTemplateVariables.LineSelection());
+ addResolver(new GlobalTemplateVariables.Dollar());
+ addResolver(new GlobalTemplateVariables.Date());
+ addResolver(new GlobalTemplateVariables.Year());
+ addResolver(new GlobalTemplateVariables.Time());
+ addResolver(new GlobalTemplateVariables.User());
+
+ // compilation unit
+ addResolver(new File());
+ addResolver(new PrimaryTypeName());
+ addResolver(new ReturnType());
+ addResolver(new Method());
+ addResolver(new Type());
+ addResolver(new Package());
+ addResolver(new Project());
+ addResolver(new Arguments());
+
+ // java
+ // addResolver(new Array());
+ // addResolver(new ArrayType());
+ // addResolver(new ArrayElement());
+ // addResolver(new Index());
+ // addResolver(new Iterator());
+ // addResolver(new Collection());
+ addResolver(new Todo());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.corext.template.java.CompilationUnitContextType#createContext(org.eclipse.jface.text.IDocument,
+ * int, int, net.sourceforge.phpdt.core.ICompilationUnit)
+ */
+ public CompilationUnitContext createContext(IDocument document, int offset,
+ int length, ICompilationUnit compilationUnit) {
+ return new JavaContext(this, document, offset, length, compilationUnit);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaDocContext.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaDocContext.java
new file mode 100644
index 0000000..9377103
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaDocContext.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateTranslator;
+
+/**
+ * A context for javadoc.
+ */
+public class JavaDocContext extends CompilationUnitContext {
+
+ // tags
+ private static final char HTML_TAG_BEGIN = '<';
+
+ private static final char HTML_TAG_END = '>';
+
+ private static final char JAVADOC_TAG_BEGIN = '@';
+
+ /**
+ * Creates a javadoc template context.
+ *
+ * @param type
+ * the context type.
+ * @param document
+ * the document.
+ * @param completionOffset
+ * the completion offset within the document.
+ * @param completionLength
+ * the completion length within the document.
+ * @param compilationUnit
+ * the compilation unit (may be null
).
+ */
+ public JavaDocContext(TemplateContextType type, IDocument document,
+ int completionOffset, int completionLength,
+ ICompilationUnit compilationUnit) {
+ super(type, document, completionOffset, completionLength,
+ compilationUnit);
+ }
+
+ /*
+ * @see TemplateContext#canEvaluate(Template templates)
+ */
+ public boolean canEvaluate(Template template) {
+ String key = getKey();
+
+ if (fForceEvaluation)
+ return true;
+
+ return template.matches(key, getContextType().getId())
+ && (key.length() != 0)
+ && template.getName().toLowerCase().startsWith(
+ key.toLowerCase());
+ }
+
+ /*
+ * @see DocumentTemplateContext#getStart()
+ */
+ public int getStart() {
+ try {
+ IDocument document = getDocument();
+
+ if (getCompletionLength() == 0) {
+ int start = getCompletionOffset();
+
+ if ((start != 0)
+ && (document.getChar(start - 1) == HTML_TAG_END))
+ start--;
+
+ while ((start != 0)
+ && Character.isUnicodeIdentifierPart(document
+ .getChar(start - 1)))
+ start--;
+
+ if ((start != 0)
+ && Character.isUnicodeIdentifierStart(document
+ .getChar(start - 1)))
+ start--;
+
+ // include html and javadoc tags
+ if ((start != 0)
+ && ((document.getChar(start - 1) == HTML_TAG_BEGIN) || (document
+ .getChar(start - 1) == JAVADOC_TAG_BEGIN))) {
+ start--;
+ }
+
+ return start;
+
+ } else {
+
+ int start = getCompletionOffset();
+ int end = getCompletionOffset() + getCompletionLength();
+
+ while (start != 0
+ && Character.isUnicodeIdentifierPart(document
+ .getChar(start - 1)))
+ start--;
+
+ while (start != end
+ && Character.isWhitespace(document.getChar(start)))
+ start++;
+
+ if (start == end)
+ start = getCompletionOffset();
+
+ return start;
+ }
+
+ } catch (BadLocationException e) {
+ return getCompletionOffset();
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getEnd()
+ */
+ public int getEnd() {
+
+ if (getCompletionLength() == 0)
+ return super.getEnd();
+
+ try {
+ IDocument document = getDocument();
+
+ int start = getCompletionOffset();
+ int end = getCompletionOffset() + getCompletionLength();
+
+ while (start != end
+ && Character.isWhitespace(document.getChar(end - 1)))
+ end--;
+
+ return end;
+
+ } catch (BadLocationException e) {
+ return super.getEnd();
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getKey()
+ */
+ public String getKey() {
+
+ if (getCompletionLength() == 0)
+ return super.getKey();
+
+ try {
+ IDocument document = getDocument();
+
+ int start = getStart();
+ int end = getCompletionOffset();
+ return start <= end ? document.get(start, end - start) : ""; //$NON-NLS-1$
+
+ } catch (BadLocationException e) {
+ return super.getKey();
+ }
+ }
+
+ /*
+ * @see TemplateContext#evaluate(Template)
+ */
+ public TemplateBuffer evaluate(Template template)
+ throws BadLocationException, TemplateException {
+ TemplateTranslator translator = new TemplateTranslator();
+ TemplateBuffer buffer = translator.translate(template);
+
+ getContextType().resolve(buffer, this);
+
+ return buffer;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaDocContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaDocContextType.java
new file mode 100644
index 0000000..e41fcc8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaDocContextType.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+
+/**
+ * A context type for javadoc.
+ */
+public class JavaDocContextType extends CompilationUnitContextType {
+
+ public static final String NAME = "phpdoc"; //$NON-NLS-1$
+
+ /**
+ * Creates a java context type.
+ */
+ public JavaDocContextType() {
+ super(NAME);
+
+ // global
+ addResolver(new GlobalTemplateVariables.Cursor());
+ addResolver(new GlobalTemplateVariables.LineSelection());
+ addResolver(new GlobalTemplateVariables.WordSelection());
+ addResolver(new GlobalTemplateVariables.Dollar());
+ addResolver(new GlobalTemplateVariables.Date());
+ addResolver(new GlobalTemplateVariables.Year());
+ addResolver(new GlobalTemplateVariables.Time());
+ addResolver(new GlobalTemplateVariables.User());
+
+ // compilation unit
+ addResolver(new File());
+ addResolver(new PrimaryTypeName());
+ addResolver(new Method());
+ addResolver(new ReturnType());
+ addResolver(new Arguments());
+ addResolver(new Type());
+ addResolver(new Package());
+ addResolver(new Project());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.corext.template.java.CompilationUnitContextType#createContext(org.eclipse.jface.text.IDocument,
+ * int, int, net.sourceforge.phpdt.core.ICompilationUnit)
+ */
+ public CompilationUnitContext createContext(IDocument document, int offset,
+ int length, ICompilationUnit compilationUnit) {
+ return new JavaDocContext(this, document, offset, length,
+ compilationUnit);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaFormatter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaFormatter.java
new file mode 100644
index 0000000..1c815b7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaFormatter.java
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.corext.util.CodeFormatterUtil;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner;
+import net.sourceforge.phpdt.internal.ui.text.JavaIndenter;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+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.ITypedRegion;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateVariable;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.RangeMarker;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * A template editor using the Java formatter to format a template buffer.
+ */
+public class JavaFormatter {
+
+ private static final String MARKER = "/*${" + GlobalTemplateVariables.Cursor.NAME + "}*/"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ /** The line delimiter to use if code formatter is not used. */
+ private final String fLineDelimiter;
+
+ /** The initial indent level */
+ private final int fInitialIndentLevel;
+
+ /** The java partitioner */
+ private boolean fUseCodeFormatter;
+
+ /**
+ * Creates a JavaFormatter with the target line delimiter.
+ *
+ * @param lineDelimiter
+ * the line delimiter to use
+ * @param initialIndentLevel
+ * the initial indentation level
+ * @param useCodeFormatter
+ * true
if the core code formatter should be used
+ */
+ public JavaFormatter(String lineDelimiter, int initialIndentLevel,
+ boolean useCodeFormatter) {
+ fLineDelimiter = lineDelimiter;
+ fUseCodeFormatter = useCodeFormatter;
+ fInitialIndentLevel = initialIndentLevel;
+ }
+
+ /**
+ * Formats the template buffer.
+ *
+ * @param buffer
+ * @param context
+ * @throws BadLocationException
+ */
+ public void format(TemplateBuffer buffer, TemplateContext context)
+ throws BadLocationException {
+ try {
+ if (fUseCodeFormatter)
+ // try to format and fall back to indenting
+ try {
+ format(buffer, (JavaContext) context);
+ } catch (BadLocationException e) {
+ indent(buffer);
+ } catch (MalformedTreeException e) {
+ indent(buffer);
+ }
+ else
+ indent(buffer);
+
+ // don't trim the buffer if the replacement area is empty
+ // case: surrounding empty lines with block
+ if (context instanceof DocumentTemplateContext) {
+ DocumentTemplateContext dtc = (DocumentTemplateContext) context;
+ if (dtc.getStart() == dtc.getCompletionOffset())
+ if (dtc.getDocument().get(dtc.getStart(),
+ dtc.getEnd() - dtc.getEnd()).trim().length() == 0)
+ return;
+ }
+
+ trimBegin(buffer);
+ } catch (MalformedTreeException e) {
+ throw new BadLocationException();
+ }
+ }
+
+ private static int getCaretOffset(TemplateVariable[] variables) {
+ for (int i = 0; i != variables.length; i++) {
+ TemplateVariable variable = variables[i];
+
+ if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME))
+ return variable.getOffsets()[0];
+ }
+
+ return -1;
+ }
+
+ private boolean isInsideCommentOrString(String string, int offset) {
+
+ IDocument document = new Document(string);
+ WebUI.getDefault().getJavaTextTools()
+ .setupJavaDocumentPartitioner(document);
+
+ try {
+ ITypedRegion partition = document.getPartition(offset);
+ String partitionType = partition.getType();
+
+ return partitionType != null
+ && (partitionType
+ .equals(IPHPPartitions.PHP_MULTILINE_COMMENT)
+ || partitionType
+ .equals(IPHPPartitions.PHP_SINGLELINE_COMMENT)
+ || partitionType
+ .equals(IPHPPartitions.PHP_STRING_DQ)
+ || partitionType
+ .equals(IPHPPartitions.PHP_STRING_SQ)
+ || partitionType
+ .equals(IPHPPartitions.PHP_STRING_HEREDOC) || partitionType
+ .equals(IPHPPartitions.PHP_PHPDOC_COMMENT));
+
+ } catch (BadLocationException e) {
+ return false;
+ }
+ }
+
+ private void format(TemplateBuffer templateBuffer, JavaContext context)
+ throws BadLocationException {
+ // XXX 4360, 15247
+ // workaround for code formatter limitations
+ // handle a special case where cursor position is surrounded by
+ // whitespaces
+
+ String string = templateBuffer.getString();
+ TemplateVariable[] variables = templateBuffer.getVariables();
+
+ int caretOffset = getCaretOffset(variables);
+ if ((caretOffset > 0)
+ && Character.isWhitespace(string.charAt(caretOffset - 1))
+ && (caretOffset < string.length())
+ && Character.isWhitespace(string.charAt(caretOffset))
+ && !isInsideCommentOrString(string, caretOffset)) {
+ List positions = variablesToPositions(variables);
+
+ TextEdit insert = new InsertEdit(caretOffset, MARKER);
+ string = edit(string, positions, insert);
+ positionsToVariables(positions, variables);
+ templateBuffer.setContent(string, variables);
+
+ plainFormat(templateBuffer, context);
+
+ string = templateBuffer.getString();
+ variables = templateBuffer.getVariables();
+ caretOffset = getCaretOffset(variables);
+
+ positions = variablesToPositions(variables);
+ TextEdit delete = new DeleteEdit(caretOffset, MARKER.length());
+ string = edit(string, positions, delete);
+ positionsToVariables(positions, variables);
+ templateBuffer.setContent(string, variables);
+
+ } else {
+ plainFormat(templateBuffer, context);
+ }
+ }
+
+ private void plainFormat(TemplateBuffer templateBuffer, JavaContext context)
+ throws BadLocationException {
+ }
+
+ // private void plainFormat(TemplateBuffer templateBuffer, JavaContext
+ // context) throws BadLocationException {
+ //
+ // IDocument doc= new Document(templateBuffer.getString());
+ //
+ // TemplateVariable[] variables= templateBuffer.getVariables();
+ //
+ // List offsets= variablesToPositions(variables);
+ //
+ // Map options;
+ // if (context.getCompilationUnit() != null)
+ // options= context.getCompilationUnit().getJavaProject().getOptions(true);
+ // else
+ // options= JavaCore.getOptions();
+ //
+ // TextEdit edit= CodeFormatterUtil.format2(CodeFormatter.K_UNKNOWN,
+ // doc.get(), fInitialIndentLevel, fLineDelimiter, options);
+ // if (edit == null)
+ // throw new BadLocationException(); // fall back to indenting
+ //
+ // MultiTextEdit root;
+ // if (edit instanceof MultiTextEdit)
+ // root= (MultiTextEdit) edit;
+ // else {
+ // root= new MultiTextEdit(0, doc.getLength());
+ // root.addChild(edit);
+ // }
+ // for (Iterator it= offsets.iterator(); it.hasNext();) {
+ // TextEdit position= (TextEdit) it.next();
+ // try {
+ // root.addChild(position);
+ // } catch (MalformedTreeException e) {
+ // // position conflicts with formatter edit
+ // // ignore this position
+ // }
+ // }
+ //
+ // root.apply(doc, TextEdit.UPDATE_REGIONS);
+ //
+ // positionsToVariables(offsets, variables);
+ //
+ // templateBuffer.setContent(doc.get(), variables);
+ // }
+
+ private void indent(TemplateBuffer templateBuffer)
+ throws BadLocationException, MalformedTreeException {
+
+ TemplateVariable[] variables = templateBuffer.getVariables();
+ List positions = variablesToPositions(variables);
+
+ IDocument document = new Document(templateBuffer.getString());
+ MultiTextEdit root = new MultiTextEdit(0, document.getLength());
+ root.addChildren((TextEdit[]) positions.toArray(new TextEdit[positions
+ .size()]));
+
+ JavaHeuristicScanner scanner = new JavaHeuristicScanner(document);
+ JavaIndenter indenter = new JavaIndenter(document, scanner);
+
+ // first line
+ int offset = document.getLineOffset(0);
+ TextEdit edit = new InsertEdit(offset, CodeFormatterUtil
+ .createIndentString(fInitialIndentLevel));
+ root.addChild(edit);
+ root.apply(document, TextEdit.UPDATE_REGIONS);
+ root.removeChild(edit);
+
+ formatDelimiter(document, root, 0);
+
+ // following lines
+ int lineCount = document.getNumberOfLines();
+
+ for (int line = 1; line < lineCount; line++) {
+ IRegion region = document.getLineInformation(line);
+ offset = region.getOffset();
+ StringBuffer indent = indenter.computeIndentation(offset);
+ if (indent == null)
+ continue;
+ // axelcl delete start
+ // int nonWS =
+ // scanner.findNonWhitespaceForwardInAnyPartition(offset, offset +
+ // region.getLength());
+ // if (nonWS == JavaHeuristicScanner.NOT_FOUND)
+ // continue;
+ // edit = new ReplaceEdit(offset, nonWS - offset,
+ // indent.toString());
+ // axelcl delete end
+ // axelcl insert start
+ int nonWS = offset;
+ edit = new ReplaceEdit(offset, nonWS - offset, CodeFormatterUtil
+ .createIndentString(fInitialIndentLevel));
+ // axelcl insert end
+ root.addChild(edit);
+ root.apply(document, TextEdit.UPDATE_REGIONS);
+ root.removeChild(edit);
+
+ formatDelimiter(document, root, line);
+ }
+
+ positionsToVariables(positions, variables);
+ templateBuffer.setContent(document.get(), variables);
+ }
+
+ /**
+ * Changes the delimiter to the configured line delimiter.
+ *
+ * @param document
+ * the temporary document being edited
+ * @param root
+ * the root edit containing all positions that will be updated
+ * along the way
+ * @param line
+ * the line to format
+ * @throws BadLocationException
+ * if applying the changes fails
+ */
+ private void formatDelimiter(IDocument document, MultiTextEdit root,
+ int line) throws BadLocationException {
+ IRegion region = document.getLineInformation(line);
+ String lineDelimiter = document.getLineDelimiter(line);
+ if (lineDelimiter != null) {
+ TextEdit edit = new ReplaceEdit(region.getOffset()
+ + region.getLength(), lineDelimiter.length(),
+ fLineDelimiter);
+ root.addChild(edit);
+ root.apply(document, TextEdit.UPDATE_REGIONS);
+ root.removeChild(edit);
+ }
+ }
+
+ private static void trimBegin(TemplateBuffer templateBuffer)
+ throws BadLocationException {
+ String string = templateBuffer.getString();
+ TemplateVariable[] variables = templateBuffer.getVariables();
+
+ List positions = variablesToPositions(variables);
+
+ int i = 0;
+ while ((i != string.length())
+ && Character.isWhitespace(string.charAt(i)))
+ i++;
+
+ string = edit(string, positions, new DeleteEdit(0, i));
+ positionsToVariables(positions, variables);
+
+ templateBuffer.setContent(string, variables);
+ }
+
+ private static String edit(String string, List positions, TextEdit edit)
+ throws BadLocationException {
+ MultiTextEdit root = new MultiTextEdit(0, string.length());
+ root.addChildren((TextEdit[]) positions.toArray(new TextEdit[positions
+ .size()]));
+ root.addChild(edit);
+ IDocument document = new Document(string);
+ root.apply(document);
+
+ return document.get();
+ }
+
+ private static List variablesToPositions(TemplateVariable[] variables) {
+ List positions = new ArrayList(5);
+ for (int i = 0; i != variables.length; i++) {
+ int[] offsets = variables[i].getOffsets();
+
+ // trim positions off whitespace
+ String value = variables[i].getDefaultValue();
+ int wsStart = 0;
+ while (wsStart < value.length()
+ && Character.isWhitespace(value.charAt(wsStart))
+ && !Strings.isLineDelimiterChar(value.charAt(wsStart)))
+ wsStart++;
+
+ variables[i].getValues()[0] = value.substring(wsStart);
+
+ for (int j = 0; j != offsets.length; j++) {
+ offsets[j] += wsStart;
+ positions.add(new RangeMarker(offsets[j], 0));
+ }
+ }
+ return positions;
+ }
+
+ private static void positionsToVariables(List positions,
+ TemplateVariable[] variables) {
+ Iterator iterator = positions.iterator();
+
+ for (int i = 0; i != variables.length; i++) {
+ TemplateVariable variable = variables[i];
+
+ int[] offsets = new int[variable.getOffsets().length];
+ for (int j = 0; j != offsets.length; j++)
+ offsets[j] = ((TextEdit) iterator.next()).getOffset();
+
+ variable.setOffsets(offsets);
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaTemplateMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaTemplateMessages.java
new file mode 100644
index 0000000..7756536
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaTemplateMessages.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+class JavaTemplateMessages {
+
+ private static final String RESOURCE_BUNDLE = JavaTemplateMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private JavaTemplateMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaTemplateMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaTemplateMessages.properties
new file mode 100644
index 0000000..bf31395
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/JavaTemplateMessages.properties
@@ -0,0 +1,139 @@
+###############################################################################
+# Copyright (c) 2000, 2004 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+
+ContextType.error.multiple.cursor.variables=Template has multiple cursor variables.
+
+Templates.for_array=iterate over array
+Templates.for_temp=iterate over array with temporary variable
+Templates.for_collection=iterate over collection
+Templates.while_enumeration=iterate with enumeration
+Templates.while_iterator=iterate with iterator
+Templates.do=do while statement
+Templates.switch=switch case statement
+Templates.if=if statement
+Templates.ifelse=if else statement
+Templates.elseif=else if block
+Templates.else=else block
+Templates.try=try catch block
+Templates.catch=catch block
+Templates.main=main method
+Templates.public_method=public method
+Templates.protected_method=protected method
+Templates.private_method=private method
+Templates.private_static_method=private static method
+Templates.instanceof=dynamic type test and cast
+Templates.cast=dynamic cast
+Templates.toarray=convert collection to array
+Templates.test=test method
+Templates.systrace=print current method to standard out
+Templates.sysout=print to standard out
+Templates.syserr=print to standard error
+Templates.code_tag=
+Templates.code_tag_null=
null
+Templates.pre_tag=
+Templates.b_tag=
+Templates.i_tag=
+Templates.author=author name
+Templates.new=create new object
+Templates.lazy=lazy creation
+Templates.while_condition=while loop with condition
+
+# Java Only stuff
+CompilationUnitContextType.variable.description.file=Filename of compilation unit
+CompilationUnitContextType.variable.description.primary.type.name=Filename without extension
+CompilationUnitContextType.variable.description.enclosing.method=Enclosing method name
+CompilationUnitContextType.variable.description.enclosing.type=Enclosing type name
+CompilationUnitContextType.variable.description.enclosing.package=Enclosing package name
+CompilationUnitContextType.variable.description.enclosing.project=Enclosing project name
+CompilationUnitContextType.variable.description.enclosing.method.arguments=Argument names of enclosing method
+CompilationUnitContextType.variable.description.return.type=Enclosing method return type
+
+JavaContextType.variable.description.array=A proposal for an array
+JavaContextType.variable.description.array.type=A proposal for the element type of an array
+JavaContextType.variable.description.array.element=A proposal for the element name of an array
+JavaContextType.variable.description.index=A proposal for an index (int)
+JavaContextType.variable.description.collection=A proposal for a collection (java.util.Collection)
+JavaContextType.variable.description.iterator=A proposal for an iterator (java.util.Iterator)
+JavaContextType.variable.description.todo=Todo task tag
+
+JavaContext.error.title=Template Error
+JavaContext.error.message=Template file incomplete or has errors. You can load the default templates from the template preferences page (Java>Templates).
+
+CodeTemplateContextType.variable.description.todo=Todo task tag
+CodeTemplateContextType.variable.description.packdeclaration=Package declaration of the new type
+CodeTemplateContextType.variable.description.typedeclaration=Generated type declaration
+CodeTemplateContextType.variable.description.getterfieldname=The name of field to set or get
+CodeTemplateContextType.variable.description.getterfieldtype=The type of the field to set or get
+CodeTemplateContextType.variable.description.fieldname=The name of field
+CodeTemplateContextType.variable.description.fieldtype=The type of the field
+CodeTemplateContextType.variable.description.barefieldname=The name of field to set or get without pre- or suffix
+CodeTemplateContextType.variable.description.param=The parameter passed into the setter method
+CodeTemplateContextType.variable.description.typecomment=Content of code template 'typecomment'
+CodeTemplateContextType.variable.description.exceptiontype=The type of the caught exception
+CodeTemplateContextType.variable.description.exceptionvar=The variable name of the caught exception
+CodeTemplateContextType.variable.description.enclosingtype=The type enclosing this method
+CodeTemplateContextType.variable.description.typename=Name of the current type
+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.tags=Generated Javadoc tags (@param, @return...)
+CodeTemplateContextType.variable.description.seetag=See tag pointing to the overridden method (@see T#m())
+
+CodeTemplateContextType.variable.description.filename=Name of the enclosing compilation unit
+CodeTemplateContextType.variable.description.packagename=Name of the enclosing package
+CodeTemplateContextType.variable.description.projectname=Name of the enclosing project
+
+CodeTemplateContextType.validate.unknownvariable=Variable ''{0}'' is unknown.
+CodeTemplateContextType.validate.missingvariable=Variable ''{0}'' is required.
+CodeTemplateContextType.validate.invalidcomment=Pattern is not a valid Java comment.
+
+
+
+CodeTemplates.error.title=Error accessing code templates.
+
+# strings in default templates
+CodeTemplates.constructorcomment=Comment for created constructors
+CodeTemplates.typecomment=Comment for created types
+CodeTemplates.fieldcomment=Comment for fields
+CodeTemplates.nonoverridingcomment=Comment for non-overriding methods
+CodeTemplates.overridecomment=Comment for overriding methods
+CodeTemplates.gettercomment=Comment for getter method
+# ! Do not translate ${bare_field_name} !
+CodeTemplates.gettercomment.returntagcontent=Returns the ${bare_field_name}.
+CodeTemplates.settercomment=Comment for setter method
+# ! Do not translate ${bare_field_name} !
+CodeTemplates.settercomment.paramtagcontent=The ${bare_field_name} to set.
+
+CodeTemplates.newfile=Newly created files
+CodeTemplates.catchblock=Code in new catch blocks
+CodeTemplates.methodstub=Code in created method stubs
+CodeTemplates.constructorstub=Code in created constructor stubs
+CodeTemplates.getterstub=Code in created getters
+CodeTemplates.setterstub=Code in created setters
+
+# ! Do not translate @todo !
+CodeTemplates.typecomment.content1=To change the template for this generated type comment go to
+CodeTemplates.typecomment.content2=Window - Preferences - Java - Code Style - Code Templates
+
+# ! Do not translate ${field} !
+CodeTemplates.fieldcomment.content=Comment for ${field}
+
+CodeTemplates.overridecomment.nonjd=(non-Javadoc)
+
+# ! Do not translate ${date} !
+CodeTemplates.newfile.content1=Created on ${date}
+CodeTemplates.newfile.content2=To change the template for this generated file go to
+CodeTemplates.newfile.content3=Window - Preferences - Java - Code Style - Code Templates
+
+CodeTemplates.catchblock.tododesc=Auto-generated catch block
+CodeTemplates.methodstub.tododesc=Auto-generated method stub
+CodeTemplates.constructorstub.tododesc=Auto-generated constructor stub
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/TemplateSet.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/TemplateSet.java
new file mode 100644
index 0000000..a0d83fa
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/TemplateSet.java
@@ -0,0 +1,422 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+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.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * TemplateSet
manages a collection of templates and makes them
+ * persistent.
+ *
+ * @deprecated use TemplateStore instead
+ * @since 3.0
+ */
+public class TemplateSet {
+
+ private static final String NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
+
+ private static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
+
+ private static final String CONTEXT_ATTRIBUTE = "context"; //$NON-NLS-1$
+
+ private List fTemplates = new ArrayList();
+
+ private String fTemplateTag;
+
+ private static final int TEMPLATE_PARSE_EXCEPTION = 10002;
+
+ private static final int TEMPLATE_IO_EXCEPTION = 10005;
+
+ private ContextTypeRegistry fRegistry;
+
+ public TemplateSet(String templateTag, ContextTypeRegistry registry) {
+ fTemplateTag = templateTag;
+ fRegistry = registry;
+ }
+
+ /**
+ * Convenience method for reading templates from a file.
+ *
+ * @param file
+ * @param allowDuplicates
+ * @param bundle
+ * @see #addFromStream(InputStream, boolean, boolean, ResourceBundle)
+ * @throws CoreException
+ */
+ public void addFromFile(File file, boolean allowDuplicates,
+ ResourceBundle bundle) throws CoreException {
+ InputStream stream = null;
+
+ try {
+ stream = new FileInputStream(file);
+ addFromStream(stream, allowDuplicates, false, bundle);
+
+ } catch (IOException e) {
+ throwReadException(e);
+
+ } finally {
+ try {
+ if (stream != null)
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public String getTemplateTag() {
+ return fTemplateTag;
+ }
+
+ /**
+ * Reads templates from a XML stream and adds them to the templates
+ *
+ * @param stream
+ * @param allowDuplicates
+ * @param bundle
+ * @param doTranslations
+ * @see #addFromStream(InputStream, boolean, boolean, ResourceBundle)
+ * @throws CoreException
+ */
+ public void addFromStream(InputStream stream, boolean allowDuplicates,
+ boolean doTranslations, ResourceBundle bundle) throws CoreException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder parser = factory.newDocumentBuilder();
+ Document document = parser.parse(new InputSource(stream));
+
+ NodeList elements = document.getElementsByTagName(getTemplateTag());
+
+ int count = elements.getLength();
+ for (int i = 0; i != count; i++) {
+ Node node = elements.item(i);
+ NamedNodeMap attributes = node.getAttributes();
+
+ if (attributes == null)
+ continue;
+
+ String name = getAttributeValue(attributes, NAME_ATTRIBUTE);
+ String description = getAttributeValue(attributes,
+ DESCRIPTION_ATTRIBUTE);
+ if (name == null || description == null)
+ continue;
+
+ if (doTranslations) {
+ description = translateString(description, bundle);
+ }
+ String context = getAttributeValue(attributes,
+ CONTEXT_ATTRIBUTE);
+
+ if (name == null || description == null || context == null)
+ throw new SAXException(JavaTemplateMessages
+ .getString("TemplateSet.error.missing.attribute")); //$NON-NLS-1$
+
+ StringBuffer buffer = new StringBuffer();
+ NodeList children = node.getChildNodes();
+ for (int j = 0; j != children.getLength(); j++) {
+ String value = children.item(j).getNodeValue();
+ if (value != null)
+ buffer.append(value);
+ }
+ String pattern = buffer.toString().trim();
+ if (doTranslations) {
+ pattern = translateString(pattern, bundle);
+ }
+
+ Template template = new Template(name, description, context,
+ pattern);
+
+ String message = validateTemplate(template);
+ if (message == null) {
+ if (!allowDuplicates) {
+ Template[] templates = getTemplates(name);
+ for (int k = 0; k < templates.length; k++) {
+ remove(templates[k]);
+ }
+ }
+ add(template);
+ } else {
+ throwReadException(null);
+ }
+ }
+ } catch (ParserConfigurationException e) {
+ throwReadException(e);
+ } catch (IOException e) {
+ throwReadException(e);
+ } catch (SAXException e) {
+ throwReadException(e);
+ }
+ }
+
+ private String translateString(String str, ResourceBundle bundle) {
+ int idx = str.indexOf('%');
+ if (idx == -1) {
+ return str;
+ }
+ StringBuffer buf = new StringBuffer();
+ int k = 0;
+ while (idx != -1) {
+ buf.append(str.substring(k, idx));
+ for (k = idx + 1; k < str.length()
+ && !Character.isWhitespace(str.charAt(k)); k++) {
+ // loop
+ }
+ String key = str.substring(idx + 1, k);
+ buf.append(getBundleString(key, bundle));
+ idx = str.indexOf('%', k);
+ }
+ buf.append(str.substring(k));
+ return buf.toString();
+ }
+
+ private String getBundleString(String key, ResourceBundle bundle) {
+ if (bundle != null) {
+ try {
+ return bundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ } else
+ return JavaTemplateMessages.getString(key); // default messages
+ }
+
+ protected String validateTemplate(Template template) {
+ TemplateContextType type = fRegistry.getContextType(template
+ .getContextTypeId());
+ if (type == null) {
+ return "Unknown context type: " + template.getContextTypeId(); //$NON-NLS-1$
+ }
+ try {
+ type.validate(template.getPattern());
+ return null;
+ } catch (TemplateException e) {
+ return e.getMessage();
+ }
+ }
+
+ private String getAttributeValue(NamedNodeMap attributes, String name) {
+ Node node = attributes.getNamedItem(name);
+
+ return node == null ? null : node.getNodeValue();
+ }
+
+ /**
+ * Convenience method for saving to a file.
+ *
+ * @see #saveToStream(OutputStream)
+ */
+ public void saveToFile(File file) throws CoreException {
+ OutputStream stream = null;
+
+ try {
+ stream = new FileOutputStream(file);
+ saveToStream(stream);
+
+ } catch (IOException e) {
+ throwWriteException(e);
+
+ } finally {
+ try {
+ if (stream != null)
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ /**
+ * Saves the template set as XML.
+ */
+ public void saveToStream(OutputStream stream) throws CoreException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document document = builder.newDocument();
+
+ Node root = document.createElement("templates"); //$NON-NLS-1$
+ document.appendChild(root);
+
+ for (int i = 0; i != fTemplates.size(); i++) {
+ Template template = (Template) fTemplates.get(i);
+
+ Node node = document.createElement(getTemplateTag());
+ root.appendChild(node);
+
+ NamedNodeMap attributes = node.getAttributes();
+
+ Attr name = document.createAttribute(NAME_ATTRIBUTE);
+ name.setValue(template.getName());
+ attributes.setNamedItem(name);
+
+ Attr description = document
+ .createAttribute(DESCRIPTION_ATTRIBUTE);
+ description.setValue(template.getDescription());
+ attributes.setNamedItem(description);
+
+ Attr context = document.createAttribute(CONTEXT_ATTRIBUTE);
+ context.setValue(template.getContextTypeId());
+ attributes.setNamedItem(context);
+
+ Text pattern = document.createTextNode(template.getPattern());
+ node.appendChild(pattern);
+ }
+
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(stream);
+
+ transformer.transform(source, result);
+
+ } catch (ParserConfigurationException e) {
+ throwWriteException(e);
+ } catch (TransformerException e) {
+ throwWriteException(e);
+ }
+ }
+
+ private static void throwReadException(Throwable t) throws CoreException {
+ int code;
+ if (t instanceof SAXException)
+ code = TEMPLATE_PARSE_EXCEPTION;
+ else
+ code = TEMPLATE_IO_EXCEPTION;
+ // IStatus status= JavaUIStatus.createError(code,
+ // TemplateMessages.getString("TemplateSet.error.read"), t);
+ // //$NON-NLS-1$
+ // throw new JavaUIException(status);
+ throw new CoreException(
+ new Status(
+ IStatus.ERROR,
+ "org.eclipse.jface.text", code, JavaTemplateMessages.getString("TemplateSet.error.read"), t)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private static void throwWriteException(Throwable t) throws CoreException {
+ // IStatus status=
+ // JavaUIStatus.createError(IJavaStatusConstants.TEMPLATE_IO_EXCEPTION,
+ // TemplateMessages.getString("TemplateSet.error.write"), t);
+ // //$NON-NLS-1$
+ // throw new JavaUIException(status);
+ throw new CoreException(
+ new Status(
+ IStatus.ERROR,
+ "org.eclipse.jface.text", TEMPLATE_IO_EXCEPTION, JavaTemplateMessages.getString("TemplateSet.error.write"), t)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Adds a template to the set.
+ */
+ public void add(Template template) {
+ if (exists(template))
+ return; // ignore duplicate
+
+ fTemplates.add(template);
+ }
+
+ private boolean exists(Template template) {
+ for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) {
+ Template anotherTemplate = (Template) iterator.next();
+
+ if (template.equals(anotherTemplate))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes a template to the set.
+ */
+ public void remove(Template template) {
+ fTemplates.remove(template);
+ }
+
+ /**
+ * Empties the set.
+ */
+ public void clear() {
+ fTemplates.clear();
+ }
+
+ /**
+ * Returns all templates.
+ */
+ public Template[] getTemplates() {
+ return (Template[]) fTemplates.toArray(new Template[fTemplates.size()]);
+ }
+
+ /**
+ * Returns all templates with a given name.
+ */
+ public Template[] getTemplates(String name) {
+ ArrayList res = new ArrayList();
+ for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) {
+ Template curr = (Template) iterator.next();
+ if (curr.getName().equals(name)) {
+ res.add(curr);
+ }
+ }
+ return (Template[]) res.toArray(new Template[res.size()]);
+ }
+
+ /**
+ * Returns the first templates with the given name.
+ */
+ public Template getFirstTemplate(String name) {
+ for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) {
+ Template curr = (Template) iterator.next();
+ if (curr.getName().equals(name)) {
+ return curr;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/Templates.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/Templates.java
new file mode 100644
index 0000000..b520985
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/corext/template/php/Templates.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.template.php;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Templates
gives access to the available templates.
+ *
+ * @deprecated As of 3.0, replaced by
+ * {@link org.eclipse.jface.text.templates.persistence.TemplateStore}
+ */
+public class Templates extends
+ net.sourceforge.phpdt.internal.corext.template.php.TemplateSet {
+
+ private static final String DEFAULT_FILE = "default-templates.xml"; //$NON-NLS-1$
+
+ private static final String TEMPLATE_FILE = "templates.xml"; //$NON-NLS-1$
+
+ private static final ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(JavaTemplateMessages.class.getName());
+
+ /** Singleton. */
+ private static Templates fgTemplates;
+
+ /**
+ * Returns an instance of templates.
+ *
+ * @deprecated As of 3.0, replaced by
+ * {@link net.sourceforge.phpdt.internal.ui.JavaPlugin#getTemplateStore()}
+ */
+ public static Templates getInstance() {
+ if (fgTemplates == null)
+ fgTemplates = new Templates();
+
+ return fgTemplates;
+ }
+
+ public Templates() {
+ super(
+ "template", WebUI.getDefault().getTemplateContextRegistry()); //$NON-NLS-1$
+ create();
+ }
+
+ private void create() {
+
+ try {
+ File templateFile = getTemplateFile();
+ if (templateFile.exists()) {
+ addFromFile(templateFile, true, fgResourceBundle);
+ }
+
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ clear();
+ }
+
+ }
+
+ /**
+ * Resets the template set.
+ */
+ public void reset() throws CoreException {
+ clear();
+ addFromFile(getTemplateFile(), true, fgResourceBundle);
+ }
+
+ /**
+ * Resets the template set with the default templates.
+ */
+ public void restoreDefaults() throws CoreException {
+ clear();
+ addFromStream(getDefaultsAsStream(), true, true, fgResourceBundle);
+ }
+
+ /**
+ * Saves the template set.
+ */
+ public void save() throws CoreException {
+ saveToFile(getTemplateFile());
+ }
+
+ private static InputStream getDefaultsAsStream() {
+ return Templates.class.getResourceAsStream(DEFAULT_FILE);
+ }
+
+ private static File getTemplateFile() {
+ IPath path = PHPeclipsePlugin.getDefault().getStateLocation();
+ path = path.append(TEMPLATE_FILE);
+
+ return path.toFile();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/IJavaHelpContextIds.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/IJavaHelpContextIds.java
new file mode 100644
index 0000000..7b6eaa6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/IJavaHelpContextIds.java
@@ -0,0 +1,763 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+/**
+ * Help context ids for the Java UI.
+ * MessageFormat
is used to format the
+ * message. If there isn't any value under the given key, the key is
+ * returned.
+ *
+ * @param key
+ * the resource key
+ * @param arg
+ * the message argument
+ * @return the string
+ */
+ public static String getFormattedString(String key, Object arg) {
+ return getFormattedString(key, new Object[] { arg });
+ }
+
+ /**
+ * Returns the formatted resource string associated with the given key in
+ * the resource bundle. MessageFormat
is used to format the
+ * message. If there isn't any value under the given key, the key is
+ * returned.
+ *
+ * @param key
+ * the resource key
+ * @param args
+ * the message arguments
+ * @return the string
+ */
+ public static String getFormattedString(String key, Object[] args) {
+ return MessageFormat.format(getString(key), args);
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.properties
new file mode 100644
index 0000000..bc3ebe5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.properties
@@ -0,0 +1,235 @@
+################################################################################
+# Copyright (c) 2002 International Business Machines Corp. and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v0.5
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v05.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+################################################################################
+
+OpenWithMenu.label=Open Wit&h
+RefactorMenu.label=Re&factor
+SourceMenu.label=&Source
+NavigateMenu.label=&Navigate
+
+BuildAction.label=&Build Project
+RebuildAction.label=Rebuild Pro&ject
+
+SelectionConverter.codeResolveOrInput_failed=Couldn't convert text selection into a PHP element
+SelectionConverter.codeResolve_failed=Couldn't convert text selection into a PHP element
+
+OpenAction.label=&Open
+OpenAction.tooltip=Open an editor on the selected element
+OpenAction.description=Open an editor on the selected element
+OpenAction.declaration.label=&Open Declaration@F3
+OpenAction.select_element=&Select or enter the element to open:
+
+OpenAction.error.title=Open
+OpenAction.error.message=Cannot open default editor.
+OpenAction.error.messageArgs=Cannot open default editor on {0}. {1}
+OpenAction.error.messageProblems=Problems Opening Editor
+OpenAction.error.messageBadSelection=Current text selection doesn't resolve to a PHP element
+
+OpenSuperImplementationAction.label=Open S&uper Implementation
+OpenSuperImplementationAction.tooltip=Open the Implementation in the Super Type
+OpenSuperImplementationAction.description=Open the Implementation in the Super Type
+OpenSuperImplementationAction.error.title=Open Super Implementation
+OpenSuperImplementationAction.error.message=Opening failed. Check log for details.
+OpenSuperImplementationAction.not_applicable=Operation not applicable to current text selection. Please position the cursor inside a method.
+OpenSuperImplementationAction.no_super_implementation=There isn''t any super implementation for method ''{0}''.
+
+OpenTypeHierarchyAction.label=Open Type Hie&rarchy
+OpenTypeHierarchyAction.tooltip=Open a type hierarchy on the selected element
+OpenTypeHierarchyAction.description=Open a type hierarchy on the selected element
+OpenTypeHierarchyAction.dialog.title=Open Type Hierarchy
+OpenTypeHierarchyAction.messages.title=Can\'t create type hierarchy
+OpenTypeHierarchyAction.messages.no_php_element=No PHP element selected.
+OpenTypeHierarchyAction.messages.no_php_resources=Selected package fragment doesn\'t contain any PHP resource.
+OpenTypeHierarchyAction.messages.no_types=Selected compilation unit doesn\'t contain a type.
+OpenTypeHierarchyAction.messages.no_valid_php_element=No valid PHP element selected.
+
+ShowInPackageViewAction.label=Show in Pac&kage Explorer
+ShowInPackageViewAction.description=Show the selected element in Package Explorer
+ShowInPackageViewAction.tooltip=Show in Package Explorer
+ShowInPackageViewAction.select_name=&Select or enter the element to reveal:
+ShowInPackageViewAction.dialog.title=Show In Package Explorer
+ShowInPackageViewAction.error.message=Internal error. Please see log for details.
+ShowInPackageViewAction.not_found=Couldn\'t reveal the selected element in Package Explorer. May be the element is filtered out.
+
+ShowInNavigatorView.label=Show in &Navigator View
+ShowInNavigatorView.dialog.title=Show in Navigator View
+ShowInNavigatorView.dialog.message=Select the element to be opened in the navigator view:
+ShowInNavigatorView.error.activation_failed=Unable to activate Resource Navigator
+ShowInNavigatorView.error.conversion_failed=Unable to convert PHP element into a resource
+
+OverrideMethodsAction.label=O&verride/Implement Methods...
+OverrideMethodsAction.description=Override or Implement Methods from super types.
+OverrideMethodsAction.tooltip=Override/Implement Methods
+
+OverrideMethodsAction.error.title=Override/Implement Methods
+OverrideMethodsAction.error.nothing_found=No methods to override found for this type.
+OverrideMethodsAction.error.type_removed_in_editor=Input type has been removed in editor.
+OverrideMethodsAction.not_applicable=Operation not applicable to current text selection. Please position the cursor inside a type.
+
+AddGetterSetterAction.label=Gene&rate Getter and Setter...
+AddGetterSetterAction.description=Generate Getter and Setter methods for the field
+AddGetterSetterAction.tooltip=Generate Getter and Setter methods for the Field
+
+AddGetterSetterAction.error.title=Generate Getter and Setter
+AddGetterSetterAction.error.actionfailed=Generating Getter and Setter Failed.
+AddGetterSetterAction.error.fieldNotExisting=The field ''{0}'' has been removed in the editor.
+AddGetterSetterAction.not_applicable=Operation not applicable to current text selection. Please select a field or a type that declares some fields.
+AddGetterSetterAction.read_only=The compilation unit in which the field ''{0}'' is declared is read only.
+
+AddGetterSetterAction.QueryDialog.title=Generate Getter and Setter
+AddGetterSetterAction.SkipSetterForFinalDialog.message=Field ''{0}'' is final.\nOK to skip creation of the setter method?
+AddGetterSetterAction.SkipExistingDialog.message=Method ''{0}'' already exists.\nSkip creation?
+AddGetterSetterAction.SkipExistingDialog.skip.label=&Skip
+AddGetterSetterAction.SkipExistingDialog.replace.label=&Replace
+AddGetterSetterAction.SkipExistingDialog.skipAll.label=Skip &All
+
+AddUnimplementedConstructorsAction.label=Add &Constructors from Superclass
+AddUnimplementedConstructorsAction.description=Evaluate and add constructors from superclass
+AddUnimplementedConstructorsAction.tooltip=Add Constructors from Superclass
+
+AddUnimplementedConstructorsAction.error.title=Add Constructors from Superclass
+AddUnimplementedConstructorsAction.error.nothing_found=No unimplemented constructors found.
+AddUnimplementedConstructorsAction.error.type_removed_in_editor=Input type has been removed in editor.
+AddUnimplementedConstructorsAction.not_applicable=Operation not applicable to current text selection. Please position the cursor inside a type.
+
+AddJavaDocStubAction.label=Add &Javadoc Comment
+AddJavaDocStubAction.description=Add a Javadoc comment stub to the member element
+AddJavaDocStubAction.tooltip=Add a Javadoc comment stub to the member element
+
+AddJavaDocStubsAction.error.dialogTitle=Add Javadoc Comment
+AddJavaDocStubsAction.error.noWorkingCopy=Could not find working copy.
+AddJavaDocStubsAction.error.memberNotExisting=Member has been removed in editor.
+AddJavaDocStubsAction.error.actionFailed=Error while adding Javadoc comment
+AddJavaDocStubsAction.not_applicable=Operation not applicable to current text selection. Please position the cursor inside a type or method.
+
+ExternalizeStringsAction.label= &Externalize Strings...
+ExternalizeStringsAction.dialog.title= Externalize Strings
+ExternalizeStringsAction.dialog.message=Couldn't open Externalize String Wizard
+
+FindStringsToExternalizeAction.label= &Find Strings to Externalize...
+FindStringsToExternalizeAction.dialog.title= Find Strings to Externalize
+FindStringsToExternalizeAction.error.message=Unexpected Exception. See log.
+FindStringsToExternalizeAction.foundStrings= {0} in {1}
+FindStringsToExternalizeAction.noStrings= No strings to externalize were found.
+FindStringsToExternalizeAction.not_externalized= {0} ¬ externalized string(s) found.
+FindStringsToExternalizeAction.button.label= &Externalize...
+FindStringsToExternalizeAction.hide= &Hide compilation units with no strings to externalize
+FindStringsToExternalizeAction.find_strings=Finding not externalized strings...
+
+OpenExternalJavadocAction.label=Open E&xternal Javadoc
+OpenExternalJavadocAction.description=Opens the Javadoc of the selected element in an external browser
+OpenExternalJavadocAction.tooltip=Opens the Javadoc of the selected element in an external browser
+OpenExternalJavadocAction.help_not_available=Help support not available
+OpenExternalJavadocAction.select_element=&Select or enter the element to open:
+OpenExternalJavadocAction.libraries.no_location=The documentation location for ''{0}'' has not been configured. For elements from libraries specify the Javadoc location URL on the property page of the parent JAR (''{1}'')
+OpenExternalJavadocAction.source.no_location=The documentation location for ''{0}'' has not been configured. For elements from source specify the Javadoc location URL on the property page of the parent project (''{1}'')
+OpenExternalJavadocAction.no_entry=The documentation does not contain an entry for ''{0}''.\n(File ''{1}'' does not exist.)
+OpenExternalJavadocAction.opening_failed=Opening Javadoc failed. See log for details
+OpenExternalJavadocAction.dialog.title=Open External Javadoc
+OpenExternalJavadocAction.code_resolve_failed=Couldn't convert text selection into a PHP element
+
+SelfEncapsulateFieldAction.label=&Self Encapsulate...
+SelfEncapsulateFieldAction.dialog.title=Self Encapsulate Field
+SelfEncapsulateFieldAction.dialog.unavailable=Operation unavailable on the current selection. Select a field.
+SelfEncapsulateFieldAction.dialog.cannot_perform=Cannot perform refactoring. See log for more details.
+SelfEncapsulateFieldAction.dialog.field_doesnot_exit=Field {0} doesn't exist in editor buffer anymore.
+
+OrganizeImportsAction.label=Or&ganize Imports@Ctrl+Shift+O
+OrganizeImportsAction.tooltip=Evaluate All Required Imports and Replace the Current Imports
+OrganizeImportsAction.description=Evaluate all required imports and replace the current imports
+
+OrganizeImportsAction.multi.op.description=Organizing imports...
+OrganizeImportsAction.multi.error.parse={0}: Compilation unit has parse errors. No changes applied.
+OrganizeImportsAction.multi.error.readonly={0}: Compilation unit is read-only. No changes applied.
+OrganizeImportsAction.multi.error.unresolvable={0}: Compilation unit contains ambiguous references. User interaction required.
+OrganizeImportsAction.multi.error.unexpected={0}: Unexpected error. See log for details.
+
+OrganizeImportsAction.selectiondialog.title=Organize Imports
+OrganizeImportsAction.selectiondialog.message=&Choose type to import:
+
+OrganizeImportsAction.error.title=Organize Imports
+OrganizeImportsAction.error.message=Unexpected error in organize imports. See log for details.
+
+OrganizeImportsAction.single.error.parse=Compilation unit has parse errors. No changes applied.
+
+OrganizeImportsAction.summary_added={0} import(s) added.
+OrganizeImportsAction.summary_removed={0} import(s) removed.
+
+OrganizeImportsAction.multi.status.title=Organize Imports
+OrganizeImportsAction.multi.status.description=Problems while organizing imports on some compilation units. See 'Details' for more information.
+
+OpenBrowserUtil.help_not_available=Help support not available
+
+MemberFilterActionGroup.hide_fields.label=Hide Fields
+MemberFilterActionGroup.hide_fields.tooltip=Hide Fields
+MemberFilterActionGroup.hide_fields.description=Toggles the visibility of fields
+
+MemberFilterActionGroup.hide_static.label=Hide Static Members
+MemberFilterActionGroup.hide_static.tooltip=Hide Static Members
+MemberFilterActionGroup.hide_static.description=Toggles the visibility of static members
+
+MemberFilterActionGroup.hide_nonpublic.label=Hide Non-Public Members
+MemberFilterActionGroup.hide_nonpublic.tooltip=Hide Non-Public Members
+MemberFilterActionGroup.hide_nonpublic.description=Toggles the visibility of non-public members
+
+NewWizardsActionGroup.new=Ne&w
+
+OpenProjectAction.dialog.title=Open Project
+OpenProjectAction.dialog.message=Select project(s) to be opened
+OpenProjectAction.error.message=Problems while opening projects
+OpenProjectAction.no_php_nature.one=The following project doesn't have a PHP nature and is therefore not present in the Package Explorer:
+OpenProjectAction.no_php_nature.multiple=The following projects don't have a PHP nature and are therefore not present in the Package Explorer:
+
+AddGetterSetterAction.dialog.title=&Select Methods to Create in Type ''{0}'':
+AddGetterSetterAction.one_selected=1 method selected
+AddGetterSetterAction.methods_selected={0} methods selected
+AddGettSetterAction.typeContainsNoFields.message=The type contains no fields or all fields have getters/setters already.
+
+OpenJavaPerspectiveAction.dialog.title=Open PHP Perspective
+OpenJavaPerspectiveAction.error.open_failed=Couldn\'t open PHP perspective
+
+OpenJavaBrowsingPerspectiveAction.dialog.title=Open PHP Browsing Perspective
+OpenJavaBrowsingPerspectiveAction.error.open_failed=Couldn\'t open PHP browsing perspective
+
+OpenTypeInHierarchyAction.label=Open Type in Hierarchy...@Ctrl+Shift+H
+OpenTypeInHierarchyAction.description=Open a type a the type hierarchy
+OpenTypeInHierarchyAction.tooltip=Open a type in a type hierarchy
+OpenTypeInHierarchyAction.dialogMessage=&Choose a type (? = any character, * = any string):
+OpenTypeInHierarchyAction.dialogTitle=Open Type in Hierarchy
+
+RefreshAction.label= Re&fresh
+RefreshAction.toolTip= Refresh
+RefreshAction.progressMessage= Refreshing...
+RefreshAction.error.title= Refresh Problems
+RefreshAction.error.message= Problems occurred refreshing the selected resources.
+RefreshAction.locationDeleted.title= Project location has been deleted
+RefreshAction.locationDeleted.message= The location for project {0} ({1}) has been deleted.\n Delete {0} from the workspace?
+
+ModifyParameterAction.problem.title=Refactoring
+ModifyParameterAction.problem.message=Operation not possible.
+
+PullUpAction.problem.title=Refactoring
+PullUpAction.problem.message=Operation not possible.
+
+OverrideMethodQuery.groupMethodsByTypes=Group methods by &types
+OverrideMethodQuery.dialog.title=Override/Implement Methods
+OverrideMethodQuery.dialog.description=&Select methods to override or implement:
+OverrideMethodQuery.selectioninfo.one={0} method selected.
+OverrideMethodQuery.selectioninfo.more={0} methods selected.
+
+ActionUtil.notOnBuildPath.title=Operation Cannot be Performed
+ActionUtil.notOnBuildPath.message=The resource is not on the build path of a PHP project.
+
+SelectAllAction.label= Select A&ll
+SelectAllAction.tooltip= Select All
+
+ToggleLinkingAction.label=Lin&k With Editor
+ToggleLinkingAction.tooltip=Link with Editor
+ToggleLinkingAction.description=Link with active editor
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/ActionUtil.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/ActionUtil.java
new file mode 100644
index 0000000..5c19554
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/ActionUtil.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.internal.corext.refactoring.util.ResourceUtil;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Shell;
+
+/*
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=19104
+ */
+public class ActionUtil {
+
+ private ActionUtil() {
+ }
+
+ // bug 31998 we will have to disable renaming of linked packages (and cus)
+ public static boolean mustDisableJavaModelAction(Shell shell, Object element) {
+ if (!(element instanceof IPackageFragment)
+ && !(element instanceof IPackageFragmentRoot))
+ return false;
+
+ IResource resource = ResourceUtil.getResource(element);
+ if ((resource == null) || (!(resource instanceof IFolder))
+ || (!resource.isLinked()))
+ return false;
+
+ MessageDialog
+ .openInformation(
+ shell,
+ ActionMessages.getString("ActionUtil.not_possible"), ActionMessages.getString("ActionUtil.no_linked")); //$NON-NLS-1$ //$NON-NLS-2$
+ return true;
+ }
+
+ public static boolean isProcessable(Shell shell, PHPEditor editor) {
+ if (editor == null)
+ return true;
+ IJavaElement input = SelectionConverter.getInput(editor);
+ // if a Java editor doesn't have an input of type Java element
+ // then it is for sure not on the build path
+ if (input == null) {
+ MessageDialog.openInformation(shell, ActionMessages
+ .getString("ActionUtil.notOnBuildPath.title"), //$NON-NLS-1$
+ ActionMessages
+ .getString("ActionUtil.notOnBuildPath.message")); //$NON-NLS-1$
+ return false;
+ }
+ return isProcessable(shell, input);
+ }
+
+ public static boolean isProcessable(Shell shell, Object element) {
+ if (!(element instanceof IJavaElement))
+ return true;
+
+ if (isOnBuildPath((IJavaElement) element))
+ return true;
+ MessageDialog.openInformation(shell, ActionMessages
+ .getString("ActionUtil.notOnBuildPath.title"), //$NON-NLS-1$
+ ActionMessages.getString("ActionUtil.notOnBuildPath.message")); //$NON-NLS-1$
+ return false;
+ }
+
+ public static boolean isOnBuildPath(IJavaElement element) {
+ // fix for bug http://dev.eclipse.org/bugs/show_bug.cgi?id=20051
+ if (element.getElementType() == IJavaElement.JAVA_PROJECT)
+ return true;
+ IJavaProject project = element.getJavaProject();
+ try {
+ // if (!project.isOnClasspath(element))
+ // return false;
+ IProject resourceProject = project.getProject();
+ if (resourceProject == null)
+ return false;
+ IProjectNature nature = resourceProject
+ .getNature(/*WebUI*/PHPeclipsePlugin.PHP_NATURE_ID);
+ // We have a Java project
+ if (nature != null)
+ return true;
+ } catch (CoreException e) {
+ }
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java
new file mode 100644
index 0000000..1d2f1c7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPartitioningException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Action that encloses the editor's current selection with Java block comment
+ * terminators (/*
and */
).
+ *
+ * @since 3.0
+ */
+public class AddBlockCommentAction extends BlockCommentAction {
+
+ /**
+ * Creates a new instance.
+ *
+ * @param bundle
+ * the resource bundle
+ * @param prefix
+ * a prefix to be prepended to the various resource keys
+ * (described in ResourceAction
constructor), or
+ * null
if none
+ * @param editor
+ * the text editor
+ */
+ public AddBlockCommentAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.actions.BlockCommentAction#runInternal(org.eclipse.jface.text.ITextSelection,
+ * org.eclipse.jface.text.IDocumentExtension3,
+ * net.sourceforge.phpdt.internal.ui.actions.BlockCommentAction.Edit.EditFactory)
+ */
+ protected void runInternal(ITextSelection selection,
+ IDocumentExtension3 docExtension, Edit.EditFactory factory)
+ throws BadLocationException, BadPartitioningException {
+ int selectionOffset = selection.getOffset();
+ int selectionEndOffset = selectionOffset + selection.getLength();
+ List edits = new LinkedList();
+ ITypedRegion partition = docExtension.getPartition(
+ IPHPPartitions.PHP_PARTITIONING, selectionOffset, false);
+
+ handleFirstPartition(partition, edits, factory, selectionOffset);
+
+ while (partition.getOffset() + partition.getLength() < selectionEndOffset) {
+ partition = handleInteriorPartition(partition, edits, factory,
+ docExtension);
+ }
+
+ handleLastPartition(partition, edits, factory, selectionEndOffset);
+
+ executeEdits(edits);
+ }
+
+ /**
+ * Handle the first partition of the selected text.
+ *
+ * @param partition
+ * @param edits
+ * @param factory
+ * @param offset
+ */
+ private void handleFirstPartition(ITypedRegion partition, List edits,
+ Edit.EditFactory factory, int offset) throws BadLocationException {
+
+ int partOffset = partition.getOffset();
+ String partType = partition.getType();
+
+ Assert.isTrue(partOffset <= offset, "illegal partition"); //$NON-NLS-1$
+
+ // first partition: mark start of comment
+ if (partType == IDocument.DEFAULT_CONTENT_TYPE
+ || partType == PHPDocumentPartitioner.PHP_SCRIPT_CODE) {
+ // Java code: right where selection starts
+ edits.add(factory.createEdit(offset, 0, getCommentStart()));
+ } else if (isSpecialPartition(partType)) {
+ // special types: include the entire partition
+ edits.add(factory.createEdit(partOffset, 0, getCommentStart()));
+ } // javadoc: no mark, will only start after comment
+
+ }
+
+ /**
+ * Handles the end of the given partition and the start of the next
+ * partition, which is returned.
+ *
+ * @param partition
+ * @param edits
+ * @param factory
+ * @param docExtension
+ * @return
+ * @throws BadLocationException
+ * @throws BadPartitioningException
+ */
+ private ITypedRegion handleInteriorPartition(ITypedRegion partition,
+ List edits, Edit.EditFactory factory,
+ IDocumentExtension3 docExtension) throws BadPartitioningException,
+ BadLocationException {
+
+ // end of previous partition
+ String partType = partition.getType();
+ int partEndOffset = partition.getOffset() + partition.getLength();
+ int tokenLength = getCommentStart().length();
+
+ boolean wasJavadoc = false; // true if the previous partition is javadoc
+
+ if (partType == IPHPPartitions.PHP_PHPDOC_COMMENT) {
+
+ wasJavadoc = true;
+
+ } else if (partType == IPHPPartitions.PHP_MULTILINE_COMMENT) {
+
+ // already in a comment - remove ending mark
+ edits.add(factory.createEdit(partEndOffset - tokenLength,
+ tokenLength, "")); //$NON-NLS-1$
+
+ }
+
+ // advance to next partition
+ partition = docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING,
+ partEndOffset, false);
+ partType = partition.getType();
+
+ // start of next partition
+ if (wasJavadoc) {
+
+ // if previous was javadoc, and the current one is not, then add
+ // block comment start
+ if (partType == IDocument.DEFAULT_CONTENT_TYPE
+ || partType == PHPDocumentPartitioner.PHP_SCRIPT_CODE
+ || isSpecialPartition(partType)) {
+ edits.add(factory.createEdit(partition.getOffset(), 0,
+ getCommentStart()));
+ }
+
+ } else { // !wasJavadoc
+
+ if (partType == IPHPPartitions.PHP_PHPDOC_COMMENT) {
+ // if next is javadoc, end block comment before
+ edits.add(factory.createEdit(partition.getOffset(), 0,
+ getCommentEnd()));
+ } else if (partType == IPHPPartitions.PHP_MULTILINE_COMMENT) {
+ // already in a comment - remove startToken
+ edits.add(factory.createEdit(partition.getOffset(),
+ getCommentStart().length(), "")); //$NON-NLS-1$
+ }
+ }
+
+ return partition;
+ }
+
+ /**
+ * Handles the end of the last partition.
+ *
+ * @param partition
+ * @param edits
+ * @param factory
+ * @param endOffset
+ */
+ private void handleLastPartition(ITypedRegion partition, List edits,
+ Edit.EditFactory factory, int endOffset)
+ throws BadLocationException {
+
+ String partType = partition.getType();
+
+ if (partType == IDocument.DEFAULT_CONTENT_TYPE
+ || partType == PHPDocumentPartitioner.PHP_SCRIPT_CODE) {
+ // normal java: end comment where selection ends
+ edits.add(factory.createEdit(endOffset, 0, getCommentEnd()));
+ } else if (isSpecialPartition(partType)) {
+ // special types: consume entire partition
+ edits.add(factory.createEdit(partition.getOffset()
+ + partition.getLength(), 0, getCommentEnd()));
+ }
+
+ }
+
+ /**
+ * Returns whether partType
is special, i.e. a Java
+ * String
,Character
, or
+ * Line End Comment
partition.
+ *
+ * @param partType
+ * the partition type to check
+ * @return true
if partType
is special,
+ * false
otherwise
+ */
+ private boolean isSpecialPartition(String partType) {
+ // return partType == IJavaPartitions.JAVA_CHARACTER
+ return partType == IPHPPartitions.PHP_STRING_DQ
+ || partType == IPHPPartitions.PHP_STRING_SQ
+ || partType == IPHPPartitions.PHP_STRING_HEREDOC
+ || partType == IPHPPartitions.PHP_SINGLELINE_COMMENT;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.actions.BlockCommentAction#validSelection(org.eclipse.jface.text.ITextSelection)
+ */
+ protected boolean isValidSelection(ITextSelection selection) {
+ return selection != null && !selection.isEmpty()
+ && selection.getLength() > 0;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/AddTaskAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/AddTaskAction.java
new file mode 100644
index 0000000..b885182
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/AddTaskAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import net.sourceforge.phpdt.ui.actions.SelectionDispatchAction;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.views.tasklist.TaskPropertiesDialog;
+
+public class AddTaskAction extends SelectionDispatchAction {
+
+ public AddTaskAction(IWorkbenchSite site) {
+ super(site);
+ setEnabled(false);
+ // WorkbenchHelp.setHelp(this, IJavaHelpContextIds.ADD_TASK_ACTION);
+ }
+
+ protected void selectionChanged(IStructuredSelection selection) {
+ setEnabled(getElement(selection) != null);
+ }
+
+ protected void run(IStructuredSelection selection) {
+ IResource resource = getElement(selection);
+ if (resource == null)
+ return;
+
+ TaskPropertiesDialog dialog = new TaskPropertiesDialog(getShell());
+ dialog.setResource(resource);
+ dialog.open();
+ }
+
+ private IResource getElement(IStructuredSelection selection) {
+ if (selection.size() != 1)
+ return null;
+
+ Object element = selection.getFirstElement();
+ if (!(element instanceof IAdaptable))
+ return null;
+ return (IResource) ((IAdaptable) element).getAdapter(IResource.class);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/BlockCommentAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/BlockCommentAction.java
new file mode 100644
index 0000000..1f037a8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/BlockCommentAction.java
@@ -0,0 +1,373 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPartitioningException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultPositionUpdater;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.IRewriteTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension2;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * Common block comment code.
+ *
+ * @since 3.0
+ */
+public abstract class BlockCommentAction extends TextEditorAction {
+
+ /**
+ * Creates a new instance.
+ *
+ * @param bundle
+ * @param prefix
+ * @param editor
+ */
+ public BlockCommentAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ /**
+ * An edit is a kind of DocumentEvent
, in this case an edit
+ * instruction, that is affilitated with a Position
on a
+ * document. The offset of the document event is not stored statically, but
+ * taken from the affiliated Position
, which gets updated
+ * when other edits occurr.
+ */
+ static class Edit extends DocumentEvent {
+
+ /**
+ * Factory for edits which manages the creation, installation and
+ * destruction of position categories, position updaters etc. on a
+ * certain document. Once a factory has been obtained, Edit
+ * objects can be obtained from it which will be linked to the document
+ * by positions of one position category.
+ * release
once the
+ * Edit
s are not used any more, so the positions can be
+ * discarded.
+ * EditFactory
with an unambiguous
+ * position category name.
+ *
+ * @param document
+ * the document that is being edited.
+ */
+ public EditFactory(IDocument document) {
+ fCategory = CATEGORY + fgCount++;
+ fDocument = document;
+ }
+
+ /**
+ * Creates a new edition on the document of this factory.
+ *
+ * @param offset
+ * the offset of the edition at the point when is
+ * created.
+ * @param length
+ * the length of the edition (not updated via the
+ * position update mechanism)
+ * @param text
+ * the text to be replaced on the document
+ * @return an Edit
reflecting the edition on the
+ * document
+ */
+ public Edit createEdit(int offset, int length, String text)
+ throws BadLocationException {
+
+ if (!fDocument.containsPositionCategory(fCategory)) {
+ fDocument.addPositionCategory(fCategory);
+ fUpdater = new DefaultPositionUpdater(fCategory);
+ fDocument.addPositionUpdater(fUpdater);
+ }
+
+ Position position = new Position(offset);
+ try {
+ fDocument.addPosition(fCategory, position);
+ } catch (BadPositionCategoryException e) {
+ Assert.isTrue(false);
+ }
+ return new Edit(fDocument, length, text, position);
+ }
+
+ /**
+ * Releases the position category on the document and uninstalls the
+ * position updater. Edit
s managed by this factory
+ * are not updated after this call.
+ */
+ public void release() {
+ if (fDocument != null
+ && fDocument.containsPositionCategory(fCategory)) {
+ fDocument.removePositionUpdater(fUpdater);
+ try {
+ fDocument.removePositionCategory(fCategory);
+ } catch (BadPositionCategoryException e) {
+ Assert.isTrue(false);
+ }
+ fDocument = null;
+ fUpdater = null;
+ }
+ }
+ }
+
+ /** The position in the document where this edit be executed. */
+ private Position fPosition;
+
+ /**
+ * Creates a new edition on document
, taking its offset
+ * from position
.
+ *
+ * @param document
+ * the document being edited
+ * @param length
+ * the length of the edition
+ * @param text
+ * the replacement text of the edition
+ * @param position
+ * the position keeping the edition's offset
+ */
+ protected Edit(IDocument document, int length, String text,
+ Position position) {
+ super(document, 0, length, text);
+ fPosition = position;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.DocumentEvent#getOffset()
+ */
+ public int getOffset() {
+ return fPosition.getOffset();
+ }
+
+ /**
+ * Executes the edition on document. The offset is taken from the
+ * position.
+ *
+ * @throws BadLocationException
+ * if the execution of the document fails.
+ */
+ public void perform() throws BadLocationException {
+ getDocument().replace(getOffset(), getLength(), getText());
+ }
+
+ }
+
+ public void run() {
+ if (!isEnabled())
+ return;
+
+ ITextEditor editor = getTextEditor();
+ if (editor == null || !ensureEditable(editor))
+ return;
+
+ ITextSelection selection = getCurrentSelection();
+ if (!isValidSelection(selection))
+ return;
+
+ if (!validateEditorInputState())
+ return;
+
+ IDocumentProvider docProvider = editor.getDocumentProvider();
+ IEditorInput input = editor.getEditorInput();
+ if (docProvider == null || input == null)
+ return;
+
+ IDocument document = docProvider.getDocument(input);
+ if (document == null)
+ return;
+
+ IDocumentExtension3 docExtension;
+ if (document instanceof IDocumentExtension3)
+ docExtension = (IDocumentExtension3) document;
+ else
+ return;
+
+ IRewriteTarget target = (IRewriteTarget) editor
+ .getAdapter(IRewriteTarget.class);
+ if (target != null) {
+ target.beginCompoundChange();
+ }
+
+ Edit.EditFactory factory = new Edit.EditFactory(document);
+
+ try {
+ runInternal(selection, docExtension, factory);
+
+ } catch (BadLocationException e) {
+ // can happen on concurrent modification, deletion etc. of the
+ // document
+ // -> don't complain, just bail out
+ } catch (BadPartitioningException e) {
+ // should not happen
+ Assert.isTrue(false, "bad partitioning"); //$NON-NLS-1$
+ } finally {
+ factory.release();
+
+ if (target != null) {
+ target.endCompoundChange();
+ }
+ }
+ }
+
+ /**
+ * Calls perform
on all Edit
s in
+ * edits
.
+ *
+ * @param edits
+ * a list of Edit
s
+ * @throws BadLocationException
+ * if an Edit
threw such an exception.
+ */
+ protected void executeEdits(List edits) throws BadLocationException {
+ for (Iterator it = edits.iterator(); it.hasNext();) {
+ Edit edit = (Edit) it.next();
+ edit.perform();
+ }
+ }
+
+ /**
+ * Ensures that the editor is modifyable. If the editor is an instance of
+ * ITextEditorExtension2
, its
+ * validateEditorInputState
method is called, otherwise, the
+ * result of isEditable
is returned.
+ *
+ * @param editor
+ * the editor to be checked
+ * @return true
if the editor is editable, false
+ * otherwise
+ */
+ protected boolean ensureEditable(ITextEditor editor) {
+ Assert.isNotNull(editor);
+
+ if (editor instanceof ITextEditorExtension2) {
+ ITextEditorExtension2 ext = (ITextEditorExtension2) editor;
+ return ext.validateEditorInputState();
+ }
+
+ return editor.isEditable();
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ super.update();
+
+ if (isEnabled()) {
+ if (!canModifyEditor() || !isValidSelection(getCurrentSelection()))
+ setEnabled(false);
+ }
+ }
+
+ /**
+ * Returns the editor's selection, or null
if no selection
+ * can be obtained or the editor is null
.
+ *
+ * @return the selection of the action's editor, or null
+ */
+ protected ITextSelection getCurrentSelection() {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ ISelectionProvider provider = editor.getSelectionProvider();
+ if (provider != null) {
+ ISelection selection = provider.getSelection();
+ if (selection instanceof ITextSelection)
+ return (ITextSelection) selection;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Runs the real command once all the editor, document, and selection checks
+ * have succeeded.
+ *
+ * @param selection
+ * the current selection we are being called for
+ * @param docExtension
+ * the document extension where we get the partitioning from
+ * @param factory
+ * the edit factory we can use to create Edit
s
+ * @throws BadLocationException
+ * if an edition fails
+ * @throws BadPartitioningException
+ * if a partitioning call fails
+ */
+ protected abstract void runInternal(ITextSelection selection,
+ IDocumentExtension3 docExtension, Edit.EditFactory factory)
+ throws BadLocationException, BadPartitioningException;
+
+ /**
+ * Checks whether selection
is valid.
+ *
+ * @param selection
+ * the selection to check
+ * @return true
if the selection is valid, false
+ * otherwise
+ */
+ protected abstract boolean isValidSelection(ITextSelection selection);
+
+ /**
+ * Returns the text to be inserted at the selection start.
+ *
+ * @return the text to be inserted at the selection start
+ */
+ protected String getCommentStart() {
+ // for now: no space story
+ return "/*"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the text to be inserted at the selection end.
+ *
+ * @return the text to be inserted at the selection end
+ */
+ protected String getCommentEnd() {
+ // for now: no space story
+ return "*/"; //$NON-NLS-1$
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/CompositeActionGroup.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/CompositeActionGroup.java
new file mode 100644
index 0000000..ab643ef
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/CompositeActionGroup.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.actions.ActionContext;
+import org.eclipse.ui.actions.ActionGroup;
+
+public class CompositeActionGroup extends ActionGroup {
+
+ private ActionGroup[] fGroups;
+
+ public CompositeActionGroup() {
+ }
+
+ public CompositeActionGroup(ActionGroup[] groups) {
+ setGroups(groups);
+ }
+
+ protected void setGroups(ActionGroup[] groups) {
+ Assert.isTrue(fGroups == null);
+ Assert.isNotNull(groups);
+ fGroups = groups;
+ }
+
+ public ActionGroup get(int index) {
+ if (fGroups == null)
+ return null;
+ return fGroups[index];
+ }
+
+ public void addGroup(ActionGroup group) {
+ if (fGroups == null) {
+ fGroups = new ActionGroup[] { group };
+ } else {
+ ActionGroup[] newGroups = new ActionGroup[fGroups.length + 1];
+ System.arraycopy(fGroups, 0, newGroups, 0, fGroups.length);
+ newGroups[fGroups.length] = group;
+ fGroups = newGroups;
+ }
+ }
+
+ public void dispose() {
+ super.dispose();
+ if (fGroups == null)
+ return;
+ for (int i = 0; i < fGroups.length; i++) {
+ fGroups[i].dispose();
+ }
+ }
+
+ public void fillActionBars(IActionBars actionBars) {
+ super.fillActionBars(actionBars);
+ if (fGroups == null)
+ return;
+ for (int i = 0; i < fGroups.length; i++) {
+ fGroups[i].fillActionBars(actionBars);
+ }
+ }
+
+ public void fillContextMenu(IMenuManager menu) {
+ super.fillContextMenu(menu);
+ if (fGroups == null)
+ return;
+ for (int i = 0; i < fGroups.length; i++) {
+ fGroups[i].fillContextMenu(menu);
+ }
+ }
+
+ public void setContext(ActionContext context) {
+ super.setContext(context);
+ if (fGroups == null)
+ return;
+ for (int i = 0; i < fGroups.length; i++) {
+ fGroups[i].setContext(context);
+ }
+ }
+
+ public void updateActionBars() {
+ super.updateActionBars();
+ if (fGroups == null)
+ return;
+ for (int i = 0; i < fGroups.length; i++) {
+ fGroups[i].updateActionBars();
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java
new file mode 100644
index 0000000..844fe84
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.source.projection.IProjectionListener;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.editors.text.IFoldingCommandIds;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextOperationAction;
+
+/**
+ * Groups the JDT folding actions.
+ *
+ * @since 3.0
+ */
+public class FoldingActionGroup extends ActionGroup {
+ private ProjectionViewer fViewer;
+
+ private TextOperationAction fToggle;
+
+ private TextOperationAction fExpand;
+
+ private TextOperationAction fCollapse;
+
+ private TextOperationAction fExpandAll;
+
+ private IProjectionListener fProjectionListener;
+
+ /**
+ * Creates a new projection action group for editor
. If the
+ * supplied viewer is not an instance of ProjectionViewer
,
+ * the action group is disabled.
+ *
+ * @param editor
+ * the text editor to operate on
+ * @param viewer
+ * the viewer of the editor
+ */
+ public FoldingActionGroup(ITextEditor editor, ITextViewer viewer) {
+ if (viewer instanceof ProjectionViewer) {
+ fViewer = (ProjectionViewer) viewer;
+
+ fProjectionListener = new IProjectionListener() {
+
+ public void projectionEnabled() {
+ update();
+ }
+
+ public void projectionDisabled() {
+ update();
+ }
+ };
+
+ fViewer.addProjectionListener(fProjectionListener);
+
+ fToggle = new TextOperationAction(ActionMessages
+ .getResourceBundle(),
+ "Projection.Toggle.", editor, ProjectionViewer.TOGGLE, true); //$NON-NLS-1$
+ fToggle.setChecked(true);
+ fToggle.setActionDefinitionId(IFoldingCommandIds.FOLDING_TOGGLE);
+ editor.setAction("FoldingToggle", fToggle); //$NON-NLS-1$
+
+ fExpandAll = new TextOperationAction(
+ ActionMessages.getResourceBundle(),
+ "Projection.ExpandAll.", editor, ProjectionViewer.EXPAND_ALL, true); //$NON-NLS-1$
+ fExpandAll
+ .setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND_ALL);
+ editor.setAction("FoldingExpandAll", fExpandAll); //$NON-NLS-1$
+
+ fExpand = new TextOperationAction(ActionMessages
+ .getResourceBundle(),
+ "Projection.Expand.", editor, ProjectionViewer.EXPAND, true); //$NON-NLS-1$
+ fExpand.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND);
+ editor.setAction("FoldingExpand", fExpand); //$NON-NLS-1$
+
+ fCollapse = new TextOperationAction(
+ ActionMessages.getResourceBundle(),
+ "Projection.Collapse.", editor, ProjectionViewer.COLLAPSE, true); //$NON-NLS-1$
+ fCollapse
+ .setActionDefinitionId(IFoldingCommandIds.FOLDING_COLLAPSE);
+ editor.setAction("FoldingCollapse", fCollapse); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Returns true
if the group is enabled.
+ *
+ *
+ * Invariant: isEnabled() <=> fViewer and all actions are != null.
+ *
+ *
+ * @return true
if the group is enabled
+ */
+ protected boolean isEnabled() {
+ return fViewer != null;
+ }
+
+ /*
+ * @see org.eclipse.ui.actions.ActionGroup#dispose()
+ */
+ public void dispose() {
+ if (isEnabled()) {
+ fViewer.removeProjectionListener(fProjectionListener);
+ fViewer = null;
+ }
+ super.dispose();
+ }
+
+ /**
+ * Updates the actions.
+ */
+ protected void update() {
+ if (isEnabled()) {
+ fToggle.update();
+ fToggle.setChecked(fViewer.getProjectionAnnotationModel() != null);
+ fExpand.update();
+ fExpandAll.update();
+ fCollapse.update();
+ }
+ }
+
+ /**
+ * Fills the menu with all folding actions.
+ *
+ * @param manager
+ * the menu manager for the folding submenu
+ */
+ public void fillMenu(IMenuManager manager) {
+ if (isEnabled()) {
+ update();
+ manager.add(fToggle);
+ manager.add(fExpandAll);
+ manager.add(fExpand);
+ manager.add(fCollapse);
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.actions.ActionGroup#updateActionBars()
+ */
+ public void updateActionBars() {
+ update();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java
new file mode 100644
index 0000000..9cbd454
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.ui.editors.text.IFoldingCommandIds;
+import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextOperationAction;
+
+/**
+ * Groups the JDT folding actions.
+ *
+ * @since 3.0
+ */
+public class FoldingExpandAllRulerAction extends AbstractRulerActionDelegate {
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#createAction(org.eclipse.ui.texteditor.ITextEditor,
+ * org.eclipse.jface.text.source.IVerticalRulerInfo)
+ */
+ protected IAction createAction(ITextEditor editor,
+ IVerticalRulerInfo rulerInfo) {
+ TextOperationAction action = new TextOperationAction(
+ ActionMessages.getResourceBundle(),
+ "Projection.ExpandAll.", editor, ProjectionViewer.EXPAND_ALL, true); //$NON-NLS-1$
+ action.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND_ALL);
+ return action;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java
new file mode 100644
index 0000000..49502ea
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.editors.text.IFoldingCommandIds;
+import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextOperationAction;
+
+/**
+ * Groups the JDT folding actions.
+ *
+ * @since 3.0
+ */
+public class FoldingToggleRulerAction extends AbstractRulerActionDelegate {
+
+ private IAction fUIAction;
+
+ private TextOperationAction fAction;
+
+ private ITextEditor fTextEditor;
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#createAction(org.eclipse.ui.texteditor.ITextEditor,
+ * org.eclipse.jface.text.source.IVerticalRulerInfo)
+ */
+ protected IAction createAction(ITextEditor editor,
+ IVerticalRulerInfo rulerInfo) {
+ fTextEditor = editor;
+ fAction = new TextOperationAction(ActionMessages.getResourceBundle(),
+ "Projection.Toggle.", editor, ProjectionViewer.TOGGLE, true); //$NON-NLS-1$
+ fAction.setActionDefinitionId(IFoldingCommandIds.FOLDING_TOGGLE);
+
+ return fAction;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IEditorPart)
+ */
+ public void setActiveEditor(IAction callerAction, IEditorPart targetEditor) {
+ fUIAction = callerAction;
+ super.setActiveEditor(callerAction, targetEditor);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
+ */
+ public void menuAboutToShow(IMenuManager manager) {
+ update();
+ super.menuAboutToShow(manager);
+ }
+
+ private void update() {
+ if (fTextEditor instanceof PHPEditor) {
+ ISourceViewer viewer = ((PHPEditor) fTextEditor).getViewer();
+ if (viewer instanceof ProjectionViewer) {
+ boolean enabled = ((ProjectionViewer) viewer)
+ .getProjectionAnnotationModel() != null;
+ fUIAction.setChecked(enabled);
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/IndentAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/IndentAction.java
new file mode 100644
index 0000000..0e133f0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/IndentAction.java
@@ -0,0 +1,562 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.formatter.DefaultCodeFormatterConstants;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner;
+import net.sourceforge.phpdt.internal.ui.text.JavaIndenter;
+import net.sourceforge.phpdt.internal.ui.text.SmartBackspaceManager;
+import net.sourceforge.phpdt.internal.ui.text.SmartBackspaceManager.UndoSpec;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.JavaDocAutoIndentStrategy;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.IRewriteTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * Indents a line or range of lines in a Java document to its correct position.
+ * No complete AST must be present, the indentation is computed using
+ * heuristics. The algorith used is fast for single lines, but does not store
+ * any information and therefore not so efficient for large line ranges.
+ *
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaIndenter
+ * @since 3.0
+ */
+public class IndentAction extends TextEditorAction {
+
+ /** The caret offset after an indent operation. */
+ private int fCaretOffset;
+
+ /**
+ * Whether this is the action invoked by TAB. When true
,
+ * indentation behaves differently to accomodate normal TAB operation.
+ */
+ private final boolean fIsTabAction;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param bundle
+ * the resource bundle
+ * @param prefix
+ * the prefix to use for keys in bundle
+ * @param editor
+ * the text editor
+ * @param isTabAction
+ * whether the action should insert tabs if over the indentation
+ */
+ public IndentAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor, boolean isTabAction) {
+ super(bundle, prefix, editor);
+ fIsTabAction = isTabAction;
+ }
+
+ /*
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ // update has been called by the framework
+ if (!isEnabled() || !validateEditorInputState())
+ return;
+
+ ITextSelection selection = getSelection();
+ final IDocument document = getDocument();
+
+ if (document != null) {
+
+ final int offset = selection.getOffset();
+ final int length = selection.getLength();
+ final Position end = new Position(offset + length);
+ final int firstLine, nLines;
+ fCaretOffset = -1;
+
+ try {
+ document.addPosition(end);
+ firstLine = document.getLineOfOffset(offset);
+ // check for marginal (zero-length) lines
+ int minusOne = length == 0 ? 0 : 1;
+ nLines = document.getLineOfOffset(offset + length - minusOne)
+ - firstLine + 1;
+ } catch (BadLocationException e) {
+ // will only happen on concurrent modification
+ WebUI.log(new Status(IStatus.ERROR, WebUI
+ .getPluginId(), IStatus.OK, "", e)); //$NON-NLS-1$
+ return;
+ }
+
+ Runnable runnable = new Runnable() {
+ public void run() {
+ IRewriteTarget target = (IRewriteTarget) getTextEditor()
+ .getAdapter(IRewriteTarget.class);
+ if (target != null) {
+ target.beginCompoundChange();
+ target.setRedraw(false);
+ }
+
+ try {
+ JavaHeuristicScanner scanner = new JavaHeuristicScanner(
+ document);
+ JavaIndenter indenter = new JavaIndenter(document,
+ scanner);
+ boolean hasChanged = false;
+ for (int i = 0; i < nLines; i++) {
+ hasChanged |= indentLine(document, firstLine + i,
+ offset, indenter, scanner);
+ }
+
+ // update caret position: move to new position when
+ // indenting just one line
+ // keep selection when indenting multiple
+ int newOffset, newLength;
+ if (fIsTabAction) {
+ newOffset = fCaretOffset;
+ newLength = 0;
+ } else if (nLines > 1) {
+ newOffset = offset;
+ newLength = end.getOffset() - offset;
+ } else {
+ newOffset = fCaretOffset;
+ newLength = 0;
+ }
+
+ // always reset the selection if anything was replaced
+ // but not when we had a singleline nontab invocation
+ if (newOffset != -1
+ && (hasChanged || newOffset != offset || newLength != length))
+ selectAndReveal(newOffset, newLength);
+
+ document.removePosition(end);
+ } catch (BadLocationException e) {
+ // will only happen on concurrent modification
+ WebUI.log(new Status(IStatus.ERROR,
+ WebUI.getPluginId(), IStatus.OK,
+ "ConcurrentModification in IndentAction", e)); //$NON-NLS-1$
+
+ } finally {
+
+ if (target != null) {
+ target.endCompoundChange();
+ target.setRedraw(true);
+ }
+ }
+ }
+ };
+
+ if (nLines > 50) {
+ Display display = getTextEditor().getEditorSite()
+ .getWorkbenchWindow().getShell().getDisplay();
+ BusyIndicator.showWhile(display, runnable);
+ } else
+ runnable.run();
+
+ }
+ }
+
+ /**
+ * Selects the given range on the editor.
+ *
+ * @param newOffset
+ * the selection offset
+ * @param newLength
+ * the selection range
+ */
+ private void selectAndReveal(int newOffset, int newLength) {
+ Assert.isTrue(newOffset >= 0);
+ Assert.isTrue(newLength >= 0);
+ ITextEditor editor = getTextEditor();
+ if (editor instanceof PHPEditor) {
+ ISourceViewer viewer = ((PHPEditor) editor).getViewer();
+ if (viewer != null)
+ viewer.setSelectedRange(newOffset, newLength);
+ } else
+ // this is too intrusive, but will never get called anyway
+ getTextEditor().selectAndReveal(newOffset, newLength);
+
+ }
+
+ /**
+ * Indents a single line using the java heuristic scanner. Javadoc and
+ * multiline comments are indented as specified by the
+ * JavaDocAutoIndentStrategy
.
+ *
+ * @param document
+ * the document
+ * @param line
+ * the line to be indented
+ * @param caret
+ * the caret position
+ * @param indenter
+ * the java indenter
+ * @param scanner
+ * the heuristic scanner
+ * @return true
if document
was modified,
+ * false
otherwise
+ * @throws BadLocationException
+ * if the document got changed concurrently
+ */
+ private boolean indentLine(IDocument document, int line, int caret,
+ JavaIndenter indenter, JavaHeuristicScanner scanner)
+ throws BadLocationException {
+ IRegion currentLine = document.getLineInformation(line);
+ int offset = currentLine.getOffset();
+ int wsStart = offset; // where we start searching for non-WS; after
+ // the "//" in single line comments
+
+ String indent = null;
+ if (offset < document.getLength()) {
+ ITypedRegion partition = TextUtilities.getPartition(document,
+ IPHPPartitions.PHP_PARTITIONING, offset, true);
+ String type = partition.getType();
+ if (type.equals(IPHPPartitions.PHP_PHPDOC_COMMENT)
+ || type.equals(IPHPPartitions.PHP_MULTILINE_COMMENT)) {
+
+ // TODO this is a hack
+ // what I want to do
+ // new JavaDocAutoIndentStrategy().indentLineAtOffset(document,
+ // offset);
+ // return;
+
+ int start = 0;
+ if (line > 0) {
+
+ IRegion previousLine = document
+ .getLineInformation(line - 1);
+ start = previousLine.getOffset() + previousLine.getLength();
+ }
+
+ DocumentCommand command = new DocumentCommand() {
+ };
+ command.text = "\n"; //$NON-NLS-1$
+ command.offset = start;
+ new JavaDocAutoIndentStrategy(IPHPPartitions.PHP_PARTITIONING)
+ .customizeDocumentCommand(document, command);
+ int to = 1;
+ while (to < command.text.length()
+ && Character.isWhitespace(command.text.charAt(to)))
+ to++;
+ indent = command.text.substring(1, to);
+
+// omit Java style
+// } else if (!fIsTabAction && partition.getOffset() == offset
+// && type.equals(IPHPPartitions.PHP_SINGLELINE_COMMENT)) {
+//
+// // line comment starting at position 0 -> indent inside
+// int slashes = 2;
+// while (slashes < document.getLength() - 1
+// && document.get(offset + slashes, 2).equals("//")) //$NON-NLS-1$
+// slashes += 2;
+//
+// wsStart = offset + slashes;
+//
+// StringBuffer computed = indenter.computeIndentation(offset);
+// int tabSize = PHPeclipsePlugin
+// .getDefault()
+// .getPreferenceStore()
+// .getInt(
+// AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
+// while (slashes > 0 && computed.length() > 0) {
+// char c = computed.charAt(0);
+// if (c == '\t')
+// if (slashes > tabSize)
+// slashes -= tabSize;
+// else
+// break;
+// else if (c == ' ')
+// slashes--;
+// else
+// break;
+//
+// computed.deleteCharAt(0);
+// }
+//
+// indent = document.get(offset, wsStart - offset) + computed;
+
+ }
+ }
+
+ // standard java indentation
+ if (indent == null) {
+ StringBuffer computed = indenter.computeIndentation(offset);
+ if (computed != null)
+ indent = computed.toString();
+ else
+ //indent = new String();
+ return true; // prevent affecting html part
+ }
+
+ // change document:
+ // get current white space
+ int lineLength = currentLine.getLength();
+ int end = scanner.findNonWhitespaceForwardInAnyPartition(wsStart,
+ offset + lineLength);
+ if (end == JavaHeuristicScanner.NOT_FOUND)
+ end = offset + lineLength;
+ int length = end - offset;
+ String currentIndent = document.get(offset, length);
+
+ // if we are right before the text start / line end, and already after
+ // the insertion point
+ // then just insert a tab.
+ if (fIsTabAction && caret == end
+ && whiteSpaceLength(currentIndent) >= whiteSpaceLength(indent)) {
+ String tab = getTabEquivalent();
+ document.replace(caret, 0, tab);
+ fCaretOffset = caret + tab.length();
+ return true;
+ }
+
+ // set the caret offset so it can be used when setting the selection
+ if (caret >= offset && caret <= end)
+ fCaretOffset = offset + indent.length();
+ else
+ fCaretOffset = -1;
+
+ // only change the document if it is a real change
+ if (!indent.equals(currentIndent)) {
+ String deletedText = document.get(offset, length);
+ document.replace(offset, length, indent);
+
+ if (fIsTabAction
+ && indent.length() > currentIndent.length()
+ && WebUI.getDefault().getPreferenceStore()
+ .getBoolean(
+ PreferenceConstants.EDITOR_SMART_BACKSPACE)) {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ final SmartBackspaceManager manager = (SmartBackspaceManager) editor
+ .getAdapter(SmartBackspaceManager.class);
+ if (manager != null) {
+ try {
+ // restore smart portion
+ ReplaceEdit smart = new ReplaceEdit(offset, indent
+ .length(), deletedText);
+
+ final UndoSpec spec = new UndoSpec(offset
+ + indent.length(), new Region(caret, 0),
+ new TextEdit[] { smart }, 2, null);
+ manager.register(spec);
+ } catch (MalformedTreeException e) {
+ // log & ignore
+ WebUI.log(new Status(IStatus.ERROR,
+ WebUI.getPluginId(), IStatus.OK,
+ "Illegal smart backspace action", e)); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ return true;
+ } else
+ return false;
+ }
+
+ /**
+ * Returns the size in characters of a string. All characters count one,
+ * tabs count the editor's preference for the tab display
+ *
+ * @param indent
+ * the string to be measured.
+ * @return
+ */
+ private int whiteSpaceLength(String indent) {
+ if (indent == null)
+ return 0;
+ else {
+ int size = 0;
+ int l = indent.length();
+ int tabSize = WebUI.getDefault().getPreferenceStore().getInt(
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
+
+ for (int i = 0; i < l; i++)
+ size += indent.charAt(i) == '\t' ? tabSize : 1;
+ return size;
+ }
+ }
+
+ /**
+ * Returns a tab equivalent, either as a tab character or as spaces,
+ * depending on the editor and formatter preferences.
+ *
+ * @return a string representing one tab in the editor, never
+ * null
+ */
+ private String getTabEquivalent() {
+ String tab;
+ if (WebUI.getDefault().getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_SPACES_FOR_TABS)) {
+ int size = JavaCore.getPlugin().getPluginPreferences().getInt(
+ DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < size; i++)
+ buf.append(' ');
+ tab = buf.toString();
+ } else
+ tab = "\t"; //$NON-NLS-1$
+
+ return tab;
+ }
+
+ /**
+ * Returns the editor's selection provider.
+ *
+ * @return the editor's selection provider or null
+ */
+ private ISelectionProvider getSelectionProvider() {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ return editor.getSelectionProvider();
+ }
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ super.update();
+
+ if (isEnabled())
+ if (fIsTabAction)
+ setEnabled(canModifyEditor() && isSmartMode()
+ && isValidSelection());
+ else
+ setEnabled(canModifyEditor() && !getSelection().isEmpty());
+ }
+
+ /**
+ * Returns if the current selection is valid, i.e. whether it is empty and
+ * the caret in the whitespace at the start of a line, or covers multiple
+ * lines.
+ *
+ * @return true
if the selection is valid for an indent
+ * operation
+ */
+ private boolean isValidSelection() {
+ ITextSelection selection = getSelection();
+ if (selection.isEmpty())
+ return false;
+
+ int offset = selection.getOffset();
+ int length = selection.getLength();
+
+ IDocument document = getDocument();
+ if (document == null)
+ return false;
+
+ try {
+ IRegion firstLine = document.getLineInformationOfOffset(offset);
+ int lineOffset = firstLine.getOffset();
+
+ // either the selection has to be empty and the caret in the WS at
+ // the line start
+ // or the selection has to extend over multiple lines
+ if (length == 0)
+ return document.get(lineOffset, offset - lineOffset).trim()
+ .length() == 0;
+ else
+ // return lineOffset + firstLine.getLength() < offset + length;
+ return false; // only enable for empty selections for now
+
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the smart preference state.
+ *
+ * @return true
if smart mode is on, false
+ * otherwise
+ */
+ private boolean isSmartMode() {
+ ITextEditor editor = getTextEditor();
+
+ if (editor instanceof ITextEditorExtension3)
+ return ((ITextEditorExtension3) editor).getInsertMode() == ITextEditorExtension3.SMART_INSERT;
+
+ return false;
+ }
+
+ /**
+ * Returns the document currently displayed in the editor, or
+ * null
if none can be obtained.
+ *
+ * @return the current document or null
+ */
+ private IDocument getDocument() {
+
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+
+ IDocumentProvider provider = editor.getDocumentProvider();
+ IEditorInput input = editor.getEditorInput();
+ if (provider != null && input != null)
+ return provider.getDocument(input);
+
+ }
+ return null;
+ }
+
+ /**
+ * Returns the selection on the editor or an invalid selection if none can
+ * be obtained. Returns never null
.
+ *
+ * @return the current selection, never null
+ */
+ private ITextSelection getSelection() {
+ ISelectionProvider provider = getSelectionProvider();
+ if (provider != null) {
+
+ ISelection selection = provider.getSelection();
+ if (selection instanceof ITextSelection)
+ return (ITextSelection) selection;
+ }
+
+ // null object
+ return TextSelection.emptySelection();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/OpenActionUtil.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/OpenActionUtil.java
new file mode 100644
index 0000000..02c7b6b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/OpenActionUtil.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.ui.JavaElementLabelProvider;
+import net.sourceforge.phpeclipse.phpeditor.EditorUtility;
+
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+
+public class OpenActionUtil {
+
+ private OpenActionUtil() {
+ // no instance.
+ }
+
+ /**
+ * Opens the editor on the given element and subsequently selects it.
+ */
+ public static void open(Object element) throws JavaModelException,
+ PartInitException {
+ open(element, true);
+ }
+
+ /**
+ * Opens the editor on the given element and subsequently selects it.
+ */
+ public static void open(Object element, boolean activate)
+ throws JavaModelException, PartInitException {
+ IEditorPart part = EditorUtility.openInEditor(element, activate);
+ if (element instanceof IJavaElement)
+ EditorUtility.revealInEditor(part, (IJavaElement) element);
+ }
+
+ /**
+ * Filters out source references from the given code resolve results. A
+ * utility method that can be called by subclassers.
+ */
+ public static List filterResolveResults(IJavaElement[] codeResolveResults) {
+ int nResults = codeResolveResults.length;
+ List refs = new ArrayList(nResults);
+ for (int i = 0; i < nResults; i++) {
+ if (codeResolveResults[i] instanceof ISourceReference)
+ refs.add(codeResolveResults[i]);
+ }
+ return refs;
+ }
+
+ /**
+ * Shows a dialog for resolving an ambigous java element. Utility method
+ * that can be called by subclassers.
+ */
+ public static IJavaElement selectJavaElement(IJavaElement[] elements,
+ Shell shell, String title, String message) {
+
+ int nResults = elements.length;
+
+ if (nResults == 0)
+ return null;
+
+ if (nResults == 1)
+ return elements[0];
+
+ int flags = JavaElementLabelProvider.SHOW_DEFAULT
+ | JavaElementLabelProvider.SHOW_QUALIFIED
+ | JavaElementLabelProvider.SHOW_ROOT;
+
+ ElementListSelectionDialog dialog = new ElementListSelectionDialog(
+ shell, new JavaElementLabelProvider(flags));
+ dialog.setTitle(title);
+ dialog.setMessage(message);
+ dialog.setElements(elements);
+
+ if (dialog.open() == ElementListSelectionDialog.OK) {
+ Object[] selection = dialog.getResult();
+ if (selection != null && selection.length > 0) {
+ nResults = selection.length;
+ for (int i = 0; i < nResults; i++) {
+ Object current = selection[i];
+ if (current instanceof IJavaElement)
+ return (IJavaElement) current;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java
new file mode 100644
index 0000000..f1709fc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPartitioningException;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Action that removes the enclosing comment marks from a Java block comment.
+ *
+ * @since 3.0
+ */
+public class RemoveBlockCommentAction extends BlockCommentAction {
+
+ /**
+ * Creates a new instance.
+ *
+ * @param bundle
+ * the resource bundle
+ * @param prefix
+ * a prefix to be prepended to the various resource keys
+ * (described in ResourceAction
constructor), or
+ * null
if none
+ * @param editor
+ * the text editor
+ */
+ public RemoveBlockCommentAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.actions.AddBlockCommentAction#runInternal(org.eclipse.jface.text.ITextSelection,
+ * org.eclipse.jface.text.IDocumentExtension3,
+ * net.sourceforge.phpdt.internal.ui.actions.AddBlockCommentAction.Edit.EditFactory)
+ */
+ protected void runInternal(ITextSelection selection,
+ IDocumentExtension3 docExtension, Edit.EditFactory factory)
+ throws BadPartitioningException, BadLocationException {
+ List edits = new LinkedList();
+ int tokenLength = getCommentStart().length();
+
+ int offset = selection.getOffset();
+ int endOffset = offset + selection.getLength();
+
+ ITypedRegion partition = docExtension.getPartition(
+ IPHPPartitions.PHP_PARTITIONING, offset, false);
+ int partOffset = partition.getOffset();
+ int partEndOffset = partOffset + partition.getLength();
+
+ while (partEndOffset < endOffset) {
+
+ if (partition.getType() == IPHPPartitions.PHP_MULTILINE_COMMENT) {
+ edits.add(factory.createEdit(partOffset, tokenLength, "")); //$NON-NLS-1$
+ edits.add(factory.createEdit(partEndOffset - tokenLength,
+ tokenLength, "")); //$NON-NLS-1$
+ }
+
+ partition = docExtension.getPartition(
+ IPHPPartitions.PHP_PARTITIONING, partEndOffset, false);
+ partOffset = partition.getOffset();
+ partEndOffset = partOffset + partition.getLength();
+ }
+
+ if (partition.getType() == IPHPPartitions.PHP_MULTILINE_COMMENT) {
+ edits.add(factory.createEdit(partOffset, tokenLength, "")); //$NON-NLS-1$
+ edits.add(factory.createEdit(partEndOffset - tokenLength,
+ tokenLength, "")); //$NON-NLS-1$
+ }
+
+ executeEdits(edits);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.actions.AddBlockCommentAction#validSelection(org.eclipse.jface.text.ITextSelection)
+ */
+ protected boolean isValidSelection(ITextSelection selection) {
+ return selection != null && !selection.isEmpty();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/SelectionConverter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/SelectionConverter.java
new file mode 100644
index 0000000..7fb9328
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/SelectionConverter.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class SelectionConverter {
+
+ private static final IJavaElement[] EMPTY_RESULT = new IJavaElement[0];
+
+ private SelectionConverter() {
+ // no instance
+ }
+
+ /**
+ * Converts the selection provided by the given part into a structured
+ * selection. The following conversion rules are used:
+ *
+ *
+ */
+ public static IStructuredSelection getStructuredSelection(
+ IWorkbenchPart part) throws JavaModelException {
+ if (part instanceof PHPEditor)
+ return new StructuredSelection(codeResolve((PHPEditor) part));
+ ISelectionProvider provider = part.getSite().getSelectionProvider();
+ if (provider != null) {
+ ISelection selection = provider.getSelection();
+ if (selection instanceof IStructuredSelection)
+ return (IStructuredSelection) selection;
+ }
+ return StructuredSelection.EMPTY;
+ }
+
+ /**
+ * Converts the given structured selection into an array of Java elements.
+ * An empty array is returned if one of the elements stored in the
+ * structured selection is not of tupe part instanceof PHPEditor
: returns a structured
+ * selection using code resolve to convert the editor's text selection.part instanceof IWorkbenchPart
: returns the part's
+ * selection if it is a structured selection.default
: returns an empty structured selection.IJavaElement
+ */
+ public static IJavaElement[] getElements(IStructuredSelection selection) {
+ if (!selection.isEmpty()) {
+ IJavaElement[] result = new IJavaElement[selection.size()];
+ int i = 0;
+ for (Iterator iter = selection.iterator(); iter.hasNext(); i++) {
+ Object element = (Object) iter.next();
+ if (!(element instanceof IJavaElement))
+ return EMPTY_RESULT;
+ result[i] = (IJavaElement) element;
+ }
+ return result;
+ }
+ return EMPTY_RESULT;
+ }
+
+ public static boolean canOperateOn(PHPEditor editor) {
+ if (editor == null)
+ return false;
+ return getInput(editor) != null;
+
+ }
+
+ /**
+ * Converts the text selection provided by the given editor into an array of
+ * Java elements. If the selection doesn't cover a Java element and the
+ * selection's length is greater than 0 the methods returns the editor's
+ * input element.
+ */
+ public static IJavaElement[] codeResolveOrInput(PHPEditor editor)
+ throws JavaModelException {
+ IJavaElement input = getInput(editor);
+ ITextSelection selection = (ITextSelection) editor
+ .getSelectionProvider().getSelection();
+ IJavaElement[] result = codeResolve(input, selection);
+ if (result.length == 0) {
+ result = new IJavaElement[] { input };
+ }
+ return result;
+ }
+
+ public static IJavaElement[] codeResolveOrInputHandled(PHPEditor editor,
+ Shell shell, String title) {
+ try {
+ return codeResolveOrInput(editor);
+ } catch (JavaModelException e) {
+ ExceptionHandler.handle(e, shell, title, ActionMessages
+ .getString("SelectionConverter.codeResolve_failed")); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ /**
+ * Converts the text selection provided by the given editor a Java element
+ * by asking the user if code reolve returned more than one result. If the
+ * selection doesn't cover a Java element and the selection's length is
+ * greater than 0 the methods returns the editor's input element.
+ */
+ public static IJavaElement codeResolveOrInput(PHPEditor editor,
+ Shell shell, String title, String message)
+ throws JavaModelException {
+ IJavaElement[] elements = codeResolveOrInput(editor);
+ if (elements == null || elements.length == 0)
+ return null;
+ IJavaElement candidate = elements[0];
+ if (elements.length > 1) {
+ candidate = OpenActionUtil.selectJavaElement(elements, shell,
+ title, message);
+ }
+ return candidate;
+ }
+
+ public static IJavaElement codeResolveOrInputHandled(PHPEditor editor,
+ Shell shell, String title, String message) {
+ try {
+ return codeResolveOrInput(editor, shell, title, message);
+ } catch (JavaModelException e) {
+ ExceptionHandler.handle(e, shell, title, ActionMessages
+ .getString("SelectionConverter.codeResolveOrInput_failed")); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ public static IJavaElement[] codeResolve(PHPEditor editor)
+ throws JavaModelException {
+ return codeResolve(getInput(editor), (ITextSelection) editor
+ .getSelectionProvider().getSelection());
+ }
+
+ /**
+ * Converts the text selection provided by the given editor a Java element
+ * by asking the user if code reolve returned more than one result. If the
+ * selection doesn't cover a Java element null
is returned.
+ */
+ public static IJavaElement codeResolve(PHPEditor editor, Shell shell,
+ String title, String message) throws JavaModelException {
+ IJavaElement[] elements = codeResolve(editor);
+ if (elements == null || elements.length == 0)
+ return null;
+ IJavaElement candidate = elements[0];
+ if (elements.length > 1) {
+ candidate = OpenActionUtil.selectJavaElement(elements, shell,
+ title, message);
+ }
+ return candidate;
+ }
+
+ public static IJavaElement[] codeResolveHandled(PHPEditor editor,
+ Shell shell, String title) {
+ try {
+ return codeResolve(editor);
+ } catch (JavaModelException e) {
+ ExceptionHandler.handle(e, shell, title, ActionMessages
+ .getString("SelectionConverter.codeResolve_failed")); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ public static IJavaElement getElementAtOffset(PHPEditor editor)
+ throws JavaModelException {
+ return getElementAtOffset(getInput(editor), (ITextSelection) editor
+ .getSelectionProvider().getSelection());
+ }
+
+ public static IType getTypeAtOffset(PHPEditor editor)
+ throws JavaModelException {
+ IJavaElement element = SelectionConverter.getElementAtOffset(editor);
+ IType type = (IType) element.getAncestor(IJavaElement.TYPE);
+ if (type == null) {
+ ICompilationUnit unit = SelectionConverter
+ .getInputAsCompilationUnit(editor);
+ if (unit != null)
+ type = unit.findPrimaryType();
+ }
+ return type;
+ }
+
+ public static IJavaElement getInput(PHPEditor editor) {
+ if (editor == null)
+ return null;
+ IEditorInput input = editor.getEditorInput();
+ // if (input instanceof IClassFileEditorInput)
+ // return ((IClassFileEditorInput)input).getClassFile();
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ return manager.getWorkingCopy(input);
+ }
+
+ public static ICompilationUnit getInputAsCompilationUnit(PHPEditor editor) {
+ Object editorInput = SelectionConverter.getInput(editor);
+ if (editorInput instanceof ICompilationUnit)
+ return (ICompilationUnit) editorInput;
+ else
+ return null;
+ }
+
+ private static IJavaElement[] codeResolve(IJavaElement input,
+ ITextSelection selection) throws JavaModelException {
+ // if (input instanceof ICodeAssist) {
+ // IJavaElement[] elements=
+ // ((ICodeAssist)input).codeSelect(selection.getOffset(),
+ // selection.getLength());
+ // if (elements != null && elements.length > 0)
+ // return elements;
+ // }
+ return EMPTY_RESULT;
+ }
+
+ private static IJavaElement getElementAtOffset(IJavaElement input,
+ ITextSelection selection) throws JavaModelException {
+ if (input instanceof ICompilationUnit) {
+ ICompilationUnit cunit = (ICompilationUnit) input;
+ if (cunit.isWorkingCopy()) {
+ synchronized (cunit) {
+ cunit.reconcile();
+ }
+ }
+ IJavaElement ref = cunit.getElementAt(selection.getOffset());
+ if (ref == null)
+ return input;
+ else
+ return ref;
+ }
+ // else if (input instanceof IClassFile) {
+ // IJavaElement ref=
+ // ((IClassFile)input).getElementAt(selection.getOffset());
+ // if (ref == null)
+ // return input;
+ // else
+ // return ref;
+ // }
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/SelectionDispatchAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/SelectionDispatchAction.java
new file mode 100644
index 0000000..6f71be1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/SelectionDispatchAction.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchSite;
+
+/**
+ * Action that dispatches the IAction#run()
and the
+ * ISelectionChangedListener#selectionChanged
according to the
+ * type of the selection.
+ *
+ *
+ *
+ *
+ * ITextSelection
then
+ * run(ITextSelection)
and
+ * selectionChanged(ITextSelection)
is called.IStructuredSelection
then
+ * run(IStructuredSelection)
and
+ * selectionChanged(IStructuredSelection)
+ * is called.run(ISelection)
and
+ * selectionChanged(ISelection)
.selectionChanged
methods depending on the type of the
+ * passed selection.
+ *
+ * @param selection
+ * the selection this action is working on
+ */
+ public void update(ISelection selection) {
+ dispatchSelectionChanged(selection);
+ }
+
+ /**
+ * Notifies this action that the given structured selection has changed.
+ * This default implementation calls
+ * selectionChanged(ISelection selection)
.
+ *
+ * @param selection
+ * the new selection
+ */
+ protected void selectionChanged(IStructuredSelection selection) {
+ selectionChanged((ISelection) selection);
+ }
+
+ /**
+ * Executes this actions with the given structured selection. This default
+ * implementation calls run(ISelection selection)
.
+ */
+ protected void run(IStructuredSelection selection) {
+ run((ISelection) selection);
+ }
+
+ /**
+ * Notifies this action that the given text selection has changed. This
+ * default implementation calls
+ * selectionChanged(ISelection selection)
.
+ *
+ * @param selection
+ * the new selection
+ */
+ protected void selectionChanged(ITextSelection selection) {
+ selectionChanged((ISelection) selection);
+ }
+
+ /**
+ * Executes this actions with the given text selection. This default
+ * implementation calls run(ISelection selection)
.
+ */
+ protected void run(ITextSelection selection) {
+ run((ISelection) selection);
+ }
+
+ /**
+ * Notifies this action that the given selection has changed. This default
+ * implementation sets the action's enablement state to false
.
+ *
+ * @param selection
+ * the new selection
+ */
+ protected void selectionChanged(ISelection selection) {
+ setEnabled(false);
+ }
+
+ /**
+ * Executes this actions with the given selection. This default
+ * implementation does nothing.
+ */
+ protected void run(ISelection selection) {
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IAction.
+ */
+ public void run() {
+ dispatchRun(getSelection());
+ }
+
+ /*
+ * (non-Javadoc) Method declared on ISelectionChangedListener.
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ dispatchSelectionChanged(event.getSelection());
+ }
+
+ private void dispatchSelectionChanged(ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ selectionChanged((IStructuredSelection) selection);
+ } else if (selection instanceof ITextSelection) {
+ selectionChanged((ITextSelection) selection);
+ } else {
+ selectionChanged(selection);
+ }
+ }
+
+ private void dispatchRun(ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ run((IStructuredSelection) selection);
+ } else if (selection instanceof ITextSelection) {
+ run((ITextSelection) selection);
+ } else {
+ run(selection);
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/WorkbenchRunnableAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/WorkbenchRunnableAdapter.java
new file mode 100644
index 0000000..6a85665
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/actions/WorkbenchRunnableAdapter.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import java.lang.reflect.InvocationTargetException;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+
+/**
+ * An IRunnableWithProgress
that adapts and
+ * IWorkspaceRunnable
so that is can be executed inside
+ * IRunnableContext
. OperationCanceledException
+ * thrown by the apapted runnabled are cought and rethrown as a
+ * InterruptedException
.
+ */
+public class WorkbenchRunnableAdapter implements IRunnableWithProgress {
+
+ private IWorkspaceRunnable fWorkspaceRunnable;
+
+ public WorkbenchRunnableAdapter(IWorkspaceRunnable runnable) {
+ fWorkspaceRunnable = runnable;
+ }
+
+ /*
+ * @see IRunnableWithProgress#run(IProgressMonitor)
+ */
+ public void run(IProgressMonitor monitor) throws InvocationTargetException,
+ InterruptedException {
+ try {
+ PHPeclipsePlugin.run(fWorkspaceRunnable, monitor);
+ } catch (OperationCanceledException e) {
+ throw new InterruptedException(e.getMessage());
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/AbstractElementListSelectionDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/AbstractElementListSelectionDialog.java
new file mode 100644
index 0000000..103f5e5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/AbstractElementListSelectionDialog.java
@@ -0,0 +1,460 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import net.sourceforge.phpdt.internal.ui.util.FilteredList;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * An abstract class to select elements out of a list of elements.
+ */
+public abstract class AbstractElementListSelectionDialog extends
+ SelectionStatusDialog {
+
+ private ILabelProvider fRenderer;
+
+ private boolean fIgnoreCase = true;
+
+ private boolean fIsMultipleSelection = false;
+
+ private boolean fMatchEmptyString = true;
+
+ private boolean fAllowDuplicates = true;
+
+ private Label fMessage;
+
+ protected FilteredList fFilteredList;
+
+ private Text fFilterText;
+
+ private ISelectionValidator fValidator;
+
+ private String fFilter = null;
+
+ private String fEmptyListMessage = ""; //$NON-NLS-1$
+
+ private String fEmptySelectionMessage = ""; //$NON-NLS-1$
+
+ private int fWidth = 60;
+
+ private int fHeight = 18;
+
+ private Object[] fSelection = new Object[0];
+
+ /**
+ * Constructs a list selection dialog.
+ *
+ * @param renderer
+ * The label renderer used
+ * @param ignoreCase
+ * Decides if the match string ignores lower/upppr case
+ * @param multipleSelection
+ * Allow multiple selection
+ */
+ protected AbstractElementListSelectionDialog(Shell parent,
+ ILabelProvider renderer) {
+ super(parent);
+ fRenderer = renderer;
+
+ int shellStyle = getShellStyle();
+ setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
+ }
+
+ /**
+ * Handles default selection (double click). By default, the OK button is
+ * pressed.
+ */
+ protected void handleDefaultSelected() {
+ if (validateCurrentSelection())
+ buttonPressed(IDialogConstants.OK_ID);
+ }
+
+ /**
+ * Specifies if sorting, filtering and folding is case sensitive.
+ */
+ public void setIgnoreCase(boolean ignoreCase) {
+ fIgnoreCase = ignoreCase;
+ }
+
+ /**
+ * Returns if sorting, filtering and folding is case sensitive.
+ */
+ public boolean isCaseIgnored() {
+ return fIgnoreCase;
+ }
+
+ /**
+ * Specifies whether everything or nothing should be filtered on empty
+ * filter string.
+ */
+ public void setMatchEmptyString(boolean matchEmptyString) {
+ fMatchEmptyString = matchEmptyString;
+ }
+
+ /**
+ * Specifies if multiple selection is allowed.
+ */
+ public void setMultipleSelection(boolean multipleSelection) {
+ fIsMultipleSelection = multipleSelection;
+ }
+
+ /**
+ * Specifies whether duplicate entries are displayed or not.
+ */
+ public void setAllowDuplicates(boolean allowDuplicates) {
+ fAllowDuplicates = allowDuplicates;
+ }
+
+ /**
+ * Sets the list size in unit of characters.
+ *
+ * @param width
+ * the width of the list.
+ * @param height
+ * the height of the list.
+ */
+ public void setSize(int width, int height) {
+ fWidth = width;
+ fHeight = height;
+ }
+
+ /**
+ * Sets the message to be displayed if the list is empty.
+ *
+ * @param message
+ * the message to be displayed.
+ */
+ public void setEmptyListMessage(String message) {
+ fEmptyListMessage = message;
+ }
+
+ /**
+ * Sets the message to be displayed if the selection is empty.
+ *
+ * @param message
+ * the message to be displayed.
+ */
+ public void setEmptySelectionMessage(String message) {
+ fEmptySelectionMessage = message;
+ }
+
+ /**
+ * Sets an optional validator to check if the selection is valid. The
+ * validator is invoked whenever the selection changes.
+ *
+ * @param validator
+ * the validator to validate the selection.
+ */
+ public void setValidator(ISelectionValidator validator) {
+ fValidator = validator;
+ }
+
+ /**
+ * Sets the elements of the list (widget). To be called within open().
+ *
+ * @param elements
+ * the elements of the list.
+ */
+ protected void setListElements(Object[] elements) {
+ Assert.isNotNull(fFilteredList);
+ fFilteredList.setElements(elements);
+ }
+
+ /**
+ * Sets the filter pattern.
+ *
+ * @param filter
+ * the filter pattern.
+ */
+ public void setFilter(String filter) {
+ if (fFilterText == null)
+ fFilter = filter;
+ else
+ fFilterText.setText(filter);
+ }
+
+ /**
+ * Returns the current filter pattern.
+ *
+ * @return returns the current filter pattern or
+ * null
.
+ *
+ * @author author
+ */
+class ClassName extends SuperClass {
+ /* This comment may span multiple lines. */
+ private $integer = 0;
+ // This comment may span only this line
+ private $string = "zero";
+
+ public function info() {
+ # call a predefined php function
+ phpinfo();
+ return "test";
+ }
+}
+?>
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerConfigurationBlock.java
new file mode 100644
index 0000000..05e76f8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerConfigurationBlock.java
@@ -0,0 +1,772 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.internal.ui.util.TabFolderLayout;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.SWT;
+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.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ */
+public class CompilerConfigurationBlock extends OptionsConfigurationBlock {
+
+ // Preference store keys, see JavaCore.getOptions
+ private static final String PREF_PB_PHP_VAR_DEPRECATED = JavaCore.COMPILER_PB_PHP_VAR_DEPRECATED;
+
+ private static final String PREF_PB_PHP_KEYWORD = JavaCore.COMPILER_PB_PHP_KEYWORD;
+
+ private static final String PREF_PB_PHP_UPPERCASE_IDENTIFIER = JavaCore.COMPILER_PB_PHP_UPPERCASE_IDENTIFIER;
+
+ private static final String PREF_PB_PHP_FILE_NOT_EXIST = JavaCore.COMPILER_PB_PHP_FILE_NOT_EXIST;
+
+ private static final String PREF_PB_UNREACHABLE_CODE = JavaCore.COMPILER_PB_UNREACHABLE_CODE;
+
+ private static final String PREF_PB_UNINITIALIZED_LOCAL_VARIABLE = JavaCore.COMPILER_PB_UNINITIALIZED_LOCAL_VARIABLE;
+
+ // private static final String PREF_LOCAL_VARIABLE_ATTR=
+ // JavaCore.COMPILER_LOCAL_VARIABLE_ATTR;
+ // private static final String PREF_LINE_NUMBER_ATTR=
+ // JavaCore.COMPILER_LINE_NUMBER_ATTR;
+ // private static final String PREF_SOURCE_FILE_ATTR=
+ // JavaCore.COMPILER_SOURCE_FILE_ATTR;
+ // private static final String PREF_CODEGEN_UNUSED_LOCAL=
+ // JavaCore.COMPILER_CODEGEN_UNUSED_LOCAL;
+ // private static final String PREF_CODEGEN_TARGET_PLATFORM=
+ // JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM;
+ // private static final String PREF_PB_UNREACHABLE_CODE=
+ // JavaCore.COMPILER_PB_UNREACHABLE_CODE;
+ // private static final String PREF_PB_INVALID_IMPORT=
+ // JavaCore.COMPILER_PB_INVALID_IMPORT;
+ // private static final String PREF_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD=
+ // JavaCore.COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD;
+ // private static final String PREF_PB_METHOD_WITH_CONSTRUCTOR_NAME=
+ // JavaCore.COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME;
+ // private static final String PREF_PB_DEPRECATION=
+ // JavaCore.COMPILER_PB_DEPRECATION;
+ // private static final String PREF_PB_DEPRECATION_WHEN_OVERRIDING=
+ // JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD;
+
+ // private static final String PREF_PB_HIDDEN_CATCH_BLOCK=
+ // JavaCore.COMPILER_PB_HIDDEN_CATCH_BLOCK;
+ // private static final String PREF_PB_UNUSED_LOCAL=
+ // JavaCore.COMPILER_PB_UNUSED_LOCAL;
+ // private static final String PREF_PB_UNUSED_PARAMETER=
+ // JavaCore.COMPILER_PB_UNUSED_PARAMETER;
+ // private static final String PREF_PB_SIGNAL_PARAMETER_IN_OVERRIDING=
+ // JavaCore.COMPILER_PB_UNUSED_PARAMETER_WHEN_OVERRIDING_CONCRETE;
+ // private static final String PREF_PB_SIGNAL_PARAMETER_IN_ABSTRACT=
+ // JavaCore.COMPILER_PB_UNUSED_PARAMETER_WHEN_IMPLEMENTING_ABSTRACT;
+ // private static final String PREF_PB_SYNTHETIC_ACCESS_EMULATION=
+ // JavaCore.COMPILER_PB_SYNTHETIC_ACCESS_EMULATION;
+ // private static final String PREF_PB_NON_EXTERNALIZED_STRINGS=
+ // JavaCore.COMPILER_PB_NON_NLS_STRING_LITERAL;
+ // private static final String PREF_PB_ASSERT_AS_IDENTIFIER=
+ // JavaCore.COMPILER_PB_ASSERT_IDENTIFIER;
+ private static final String PREF_PB_MAX_PER_UNIT = JavaCore.COMPILER_PB_MAX_PER_UNIT;
+
+ // private static final String PREF_PB_UNUSED_IMPORT=
+ // JavaCore.COMPILER_PB_UNUSED_IMPORT;
+ // private static final String PREF_PB_UNUSED_PRIVATE=
+ // JavaCore.COMPILER_PB_UNUSED_PRIVATE_MEMBER;
+ // private static final String PREF_PB_STATIC_ACCESS_RECEIVER=
+ // JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER;
+ // private static final String PREF_PB_NO_EFFECT_ASSIGNMENT=
+ // JavaCore.COMPILER_PB_NO_EFFECT_ASSIGNMENT;
+ // private static final String PREF_PB_CHAR_ARRAY_IN_CONCAT=
+ // JavaCore.COMPILER_PB_CHAR_ARRAY_IN_STRING_CONCATENATION;
+ // private static final String
+ // PREF_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT=
+ // JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT;
+ // private static final String PREF_PB_LOCAL_VARIABLE_HIDING=
+ // JavaCore.COMPILER_PB_LOCAL_VARIABLE_HIDING;
+ // private static final String PREF_PB_FIELD_HIDING=
+ // JavaCore.COMPILER_PB_FIELD_HIDING;
+ // private static final String PREF_PB_SPECIAL_PARAMETER_HIDING_FIELD=
+ // JavaCore.COMPILER_PB_SPECIAL_PARAMETER_HIDING_FIELD;
+ // private static final String PREF_PB_INDIRECT_STATIC_ACCESS=
+ // JavaCore.COMPILER_PB_INDIRECT_STATIC_ACCESS;
+ // private static final String PREF_PB_SUPERFLUOUS_SEMICOLON=
+ // JavaCore.COMPILER_PB_SUPERFLUOUS_SEMICOLON;
+ // private static final String PREF_PB_UNNECESSARY_TYPE_CHECK=
+ // JavaCore.COMPILER_PB_UNNECESSARY_TYPE_CHECK;
+
+ // private static final String PREF_PB_INVALID_JAVADOC=
+ // JavaCore.COMPILER_PB_INVALID_JAVADOC;
+ // private static final String PREF_PB_INVALID_JAVADOC_TAGS=
+ // JavaCore.COMPILER_PB_INVALID_JAVADOC_TAGS;
+ // private static final String PREF_PB_INVALID_JAVADOC_TAGS_VISIBILITY=
+ // JavaCore.COMPILER_PB_INVALID_JAVADOC_TAGS_VISIBILITY;
+ //
+ // private static final String PREF_PB_MISSING_JAVADOC_TAGS=
+ // JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS;
+ // private static final String PREF_PB_MISSING_JAVADOC_TAGS_VISIBILITY=
+ // JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS_VISIBILITY;
+ // private static final String PREF_PB_MISSING_JAVADOC_TAGS_OVERRIDING=
+ // JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS_OVERRIDING;
+ //
+ // private static final String PREF_PB_MISSING_JAVADOC_COMMENTS=
+ // JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS;
+ // private static final String PREF_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY=
+ // JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY;
+ // private static final String PREF_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING=
+ // JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING;
+ //
+ // private static final String PREF_SOURCE_COMPATIBILITY=
+ // JavaCore.COMPILER_SOURCE;
+ // private static final String PREF_COMPLIANCE=
+ // JavaCore.COMPILER_COMPLIANCE;
+ //
+ // private static final String PREF_RESOURCE_FILTER=
+ // JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER;
+ // private static final String PREF_BUILD_INVALID_CLASSPATH=
+ // JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH;
+ // private static final String PREF_BUILD_CLEAN_OUTPUT_FOLDER=
+ // JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER;
+ // private static final String PREF_ENABLE_EXCLUSION_PATTERNS=
+ // JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS;
+ // private static final String PREF_ENABLE_MULTIPLE_OUTPUT_LOCATIONS=
+ // JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS;
+ //
+ // private static final String PREF_PB_INCOMPLETE_BUILDPATH=
+ // JavaCore.CORE_INCOMPLETE_CLASSPATH;
+ // private static final String PREF_PB_CIRCULAR_BUILDPATH=
+ // JavaCore.CORE_CIRCULAR_CLASSPATH;
+ // // private static final String PREF_PB_INCOMPATIBLE_JDK_LEVEL=
+ // JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL;
+ // private static final String PREF_PB_DEPRECATION_IN_DEPRECATED_CODE=
+ // JavaCore.COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE;
+ // private static final String PREF_PB_DUPLICATE_RESOURCE=
+ // JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE;
+ // private static final String PREF_PB_INCOMPATIBLE_INTERFACE_METHOD=
+ // JavaCore.COMPILER_PB_INCOMPATIBLE_NON_INHERITED_INTERFACE_METHOD;
+
+ // private static final String PREF_PB_UNDOCUMENTED_EMPTY_BLOCK=
+ // JavaCore.COMPILER_PB_UNDOCUMENTED_EMPTY_BLOCK;
+ // private static final String PREF_PB_FINALLY_BLOCK_NOT_COMPLETING=
+ // JavaCore.COMPILER_PB_FINALLY_BLOCK_NOT_COMPLETING;
+ // private static final String PREF_PB_UNUSED_DECLARED_THROWN_EXCEPTION=
+ // JavaCore.COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION;
+ // private static final String
+ // PREF_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING=
+ // JavaCore.COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING;
+ // private static final String PREF_PB_UNQUALIFIED_FIELD_ACCESS=
+ // JavaCore.COMPILER_PB_UNQUALIFIED_FIELD_ACCESS;
+
+ // private static final String INTR_DEFAULT_COMPLIANCE=
+ // "internal.default.compliance"; //$NON-NLS-1$
+
+ // values
+ private static final String GENERATE = JavaCore.GENERATE;
+
+ private static final String DO_NOT_GENERATE = JavaCore.DO_NOT_GENERATE;
+
+ private static final String PRESERVE = JavaCore.PRESERVE;
+
+ private static final String OPTIMIZE_OUT = JavaCore.OPTIMIZE_OUT;
+
+ private static final String VERSION_1_1 = JavaCore.VERSION_1_1;
+
+ private static final String VERSION_1_2 = JavaCore.VERSION_1_2;
+
+ private static final String VERSION_1_3 = JavaCore.VERSION_1_3;
+
+ private static final String VERSION_1_4 = JavaCore.VERSION_1_4;
+
+ private static final String ERROR = JavaCore.ERROR;
+
+ private static final String WARNING = JavaCore.WARNING;
+
+ private static final String IGNORE = JavaCore.IGNORE;
+
+ private static final String ABORT = JavaCore.ABORT;
+
+ private static final String CLEAN = JavaCore.CLEAN;
+
+ private static final String ENABLED = JavaCore.ENABLED;
+
+ private static final String DISABLED = JavaCore.DISABLED;
+
+ // private static final String PUBLIC= JavaCore.PUBLIC;
+ // private static final String PROTECTED= JavaCore.PROTECTED;
+ // private static final String DEFAULT= JavaCore.DEFAULT;
+ // private static final String PRIVATE= JavaCore.PRIVATE;
+
+ private static final String DEFAULT_CONF = "default"; //$NON-NLS-1$
+
+ private static final String USER_CONF = "user"; //$NON-NLS-1$
+
+ private ArrayList fComplianceControls;
+
+ private PixelConverter fPixelConverter;
+
+ private IStatus fMaxNumberProblemsStatus;
+
+ // private IStatus fComplianceStatus, fMaxNumberProblemsStatus,
+ // fResourceFilterStatus;
+
+ public CompilerConfigurationBlock(IStatusChangeListener context,
+ IJavaProject project) {
+ super(context, project, getKeys());
+
+ fComplianceControls = new ArrayList();
+
+ // fComplianceStatus= new StatusInfo();
+ fMaxNumberProblemsStatus = new StatusInfo();
+ // fResourceFilterStatus= new StatusInfo();
+
+ // compatibilty code for the merge of the two option
+ // PB_SIGNAL_PARAMETER:
+ // if
+ // (ENABLED.equals(fWorkingValues.get(PREF_PB_SIGNAL_PARAMETER_IN_ABSTRACT)))
+ // {
+ // fWorkingValues.put(PREF_PB_SIGNAL_PARAMETER_IN_OVERRIDING, ENABLED);
+ // }
+
+ }
+
+ private final static String[] KEYS = new String[] {
+ PREF_PB_PHP_FILE_NOT_EXIST, PREF_PB_PHP_VAR_DEPRECATED,
+ PREF_PB_PHP_KEYWORD, PREF_PB_PHP_UPPERCASE_IDENTIFIER,
+ PREF_PB_UNREACHABLE_CODE, PREF_PB_UNINITIALIZED_LOCAL_VARIABLE,
+ // PREF_LOCAL_VARIABLE_ATTR,
+ // PREF_LINE_NUMBER_ATTR, PREF_SOURCE_FILE_ATTR,
+ // PREF_CODEGEN_UNUSED_LOCAL,
+ // PREF_CODEGEN_TARGET_PLATFORM,
+ // PREF_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD,
+ // PREF_PB_METHOD_WITH_CONSTRUCTOR_NAME,
+ // PREF_PB_DEPRECATION,
+ // PREF_PB_HIDDEN_CATCH_BLOCK, PREF_PB_UNUSED_LOCAL,
+ // PREF_PB_UNUSED_PARAMETER,
+ // PREF_PB_SYNTHETIC_ACCESS_EMULATION,
+ // PREF_PB_NON_EXTERNALIZED_STRINGS,
+ // PREF_PB_ASSERT_AS_IDENTIFIER,
+ // PREF_PB_UNUSED_IMPORT,
+ PREF_PB_MAX_PER_UNIT,
+ // PREF_SOURCE_COMPATIBILITY,
+ // PREF_COMPLIANCE,
+ // PREF_RESOURCE_FILTER, PREF_BUILD_INVALID_CLASSPATH,
+ // PREF_PB_STATIC_ACCESS_RECEIVER, PREF_PB_INCOMPLETE_BUILDPATH,
+ // PREF_PB_CIRCULAR_BUILDPATH, PREF_PB_DEPRECATION_IN_DEPRECATED_CODE,
+ // PREF_BUILD_CLEAN_OUTPUT_FOLDER,
+ // PREF_PB_DUPLICATE_RESOURCE, PREF_PB_NO_EFFECT_ASSIGNMENT,
+ // PREF_PB_INCOMPATIBLE_INTERFACE_METHOD,
+ // PREF_PB_UNUSED_PRIVATE, PREF_PB_CHAR_ARRAY_IN_CONCAT,
+ // PREF_ENABLE_EXCLUSION_PATTERNS, PREF_ENABLE_MULTIPLE_OUTPUT_LOCATIONS,
+ // PREF_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT,
+ // PREF_PB_LOCAL_VARIABLE_HIDING,
+ // PREF_PB_FIELD_HIDING,
+ // PREF_PB_SPECIAL_PARAMETER_HIDING_FIELD,
+ // PREF_PB_INCOMPATIBLE_JDK_LEVEL,
+ // PREF_PB_INDIRECT_STATIC_ACCESS,
+ // PREF_PB_SUPERFLUOUS_SEMICOLON,
+ // PREF_PB_SIGNAL_PARAMETER_IN_OVERRIDING,
+ // PREF_PB_SIGNAL_PARAMETER_IN_ABSTRACT,
+ // PREF_PB_UNNECESSARY_TYPE_CHECK,
+ // PREF_PB_UNUSED_DECLARED_THROWN_EXCEPTION,
+ // PREF_PB_UNQUALIFIED_FIELD_ACCESS,
+ // PREF_PB_UNDOCUMENTED_EMPTY_BLOCK,
+ // PREF_PB_FINALLY_BLOCK_NOT_COMPLETING,
+ // PREF_PB_DEPRECATION_WHEN_OVERRIDING,
+ // PREF_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING,
+
+ // PREF_PB_INVALID_JAVADOC,
+ // PREF_PB_INVALID_JAVADOC_TAGS_VISIBILITY,
+ // PREF_PB_INVALID_JAVADOC_TAGS_VISIBILITY,
+ // PREF_PB_MISSING_JAVADOC_TAGS,
+ // PREF_PB_MISSING_JAVADOC_TAGS_VISIBILITY,
+ // PREF_PB_MISSING_JAVADOC_TAGS_OVERRIDING,
+ // PREF_PB_MISSING_JAVADOC_COMMENTS,
+ // PREF_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY,
+ // PREF_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING
+ };
+
+ private static String[] getKeys() {
+ return KEYS;
+ }
+
+ protected final Map getOptions(boolean inheritJavaCoreOptions) {
+ Map map = super.getOptions(inheritJavaCoreOptions);
+ // map.put(INTR_DEFAULT_COMPLIANCE, getCurrentCompliance(map));
+ return map;
+ }
+
+ protected final Map getDefaultOptions() {
+ Map map = super.getDefaultOptions();
+ // map.put(INTR_DEFAULT_COMPLIANCE, getCurrentCompliance(map));
+ return map;
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ fPixelConverter = new PixelConverter(parent);
+ setShell(parent.getShell());
+
+ TabFolder folder = new TabFolder(parent, SWT.NONE);
+ folder.setLayout(new TabFolderLayout());
+ folder.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Composite commonComposite = createStyleTabContent(folder);
+ // Composite unusedComposite= createUnusedCodeTabContent(folder);
+ Composite advancedComposite = createAdvancedTabContent(folder);
+ // Composite javadocComposite= createJavadocTabContent(folder);
+ // Composite complianceComposite= createComplianceTabContent(folder);
+ // Composite othersComposite= createBuildPathTabContent(folder);
+
+ TabItem item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("CompilerConfigurationBlock.common.tabtitle")); //$NON-NLS-1$
+ item.setControl(commonComposite);
+
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("CompilerConfigurationBlock.advanced.tabtitle")); //$NON-NLS-1$
+ item.setControl(advancedComposite);
+
+ // item= new TabItem(folder, SWT.NONE);
+ // item.setText(PreferencesMessages.getString("CompilerConfigurationBlock.unused.tabtitle"));
+ // //$NON-NLS-1$
+ // item.setControl(unusedComposite);
+
+ // item= new TabItem(folder, SWT.NONE);
+ // item.setText(PreferencesMessages.getString("CompilerConfigurationBlock.javadoc.tabtitle"));
+ // //$NON-NLS-1$
+ // item.setControl(javadocComposite);
+
+ // item= new TabItem(folder, SWT.NONE);
+ // item.setText(PreferencesMessages.getString("CompilerConfigurationBlock.compliance.tabtitle"));
+ // //$NON-NLS-1$
+ // item.setControl(complianceComposite);
+
+ // item= new TabItem(folder, SWT.NONE);
+ // item.setText(PreferencesMessages.getString("CompilerConfigurationBlock.others.tabtitle"));
+ // //$NON-NLS-1$
+ // item.setControl(othersComposite);
+
+ validateSettings(null, null);
+
+ return folder;
+ }
+
+ private Composite createStyleTabContent(Composite folder) {
+ String[] errorWarningIgnore = new String[] { ERROR, WARNING, IGNORE };
+
+ String[] errorWarningIgnoreLabels = new String[] {
+ PreferencesMessages
+ .getString("CompilerConfigurationBlock.error"), //$NON-NLS-1$
+ PreferencesMessages
+ .getString("CompilerConfigurationBlock.warning"), //$NON-NLS-1$
+ PreferencesMessages
+ .getString("CompilerConfigurationBlock.ignore") //$NON-NLS-1$
+ };
+
+ int nColumns = 3;
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = nColumns;
+
+ Composite composite = new Composite(folder, SWT.NULL);
+ composite.setLayout(layout);
+
+ Label description = new Label(composite, SWT.WRAP);
+ description.setText(PreferencesMessages
+ .getString("CompilerConfigurationBlock.common.description")); //$NON-NLS-1$
+ GridData gd = new GridData();
+ gd.horizontalSpan = nColumns;
+ gd.widthHint = fPixelConverter.convertWidthInCharsToPixels(50);
+ description.setLayoutData(gd);
+
+ String label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_file_not_exist.label"); //$NON-NLS-1$
+ addComboBox(composite, label, PREF_PB_PHP_FILE_NOT_EXIST,
+ errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_var_deprecated.label"); //$NON-NLS-1$
+ addComboBox(composite, label, PREF_PB_PHP_VAR_DEPRECATED,
+ errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_keyword.label"); //$NON-NLS-1$
+ addComboBox(composite, label, PREF_PB_PHP_KEYWORD, errorWarningIgnore,
+ errorWarningIgnoreLabels, 0);
+
+ label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_uppercase_identifier.label"); //$NON-NLS-1$
+ addComboBox(composite, label, PREF_PB_PHP_UPPERCASE_IDENTIFIER,
+ errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_unreachable_code.label"); //$NON-NLS-1$
+ addComboBox(composite, label, PREF_PB_UNREACHABLE_CODE,
+ errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_unitialized_local_variable.label"); //$NON-NLS-1$
+ addComboBox(composite, label, PREF_PB_UNINITIALIZED_LOCAL_VARIABLE,
+ errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_overriding_pkg_dflt.label"); //$NON-NLS-1$
+ // addComboBox(composite, label,
+ // PREF_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD, errorWarningIgnore,
+ // errorWarningIgnoreLabels, 0);
+
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_method_naming.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_METHOD_WITH_CONSTRUCTOR_NAME,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_hidden_catchblock.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_HIDDEN_CATCH_BLOCK,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_static_access_receiver.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_STATIC_ACCESS_RECEIVER,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_no_effect_assignment.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_NO_EFFECT_ASSIGNMENT,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_indirect_access_to_static.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_INDIRECT_STATIC_ACCESS,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_accidential_assignement.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label,
+ // PREF_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT, errorWarningIgnore,
+ // errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_finally_block_not_completing.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_FINALLY_BLOCK_NOT_COMPLETING,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_undocumented_empty_block.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_UNDOCUMENTED_EMPTY_BLOCK,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ return composite;
+ }
+
+ private Composite createAdvancedTabContent(TabFolder folder) {
+ String[] errorWarningIgnore = new String[] { ERROR, WARNING, IGNORE };
+
+ String[] errorWarningIgnoreLabels = new String[] {
+ PreferencesMessages
+ .getString("CompilerConfigurationBlock.error"), //$NON-NLS-1$
+ PreferencesMessages
+ .getString("CompilerConfigurationBlock.warning"), //$NON-NLS-1$
+ PreferencesMessages
+ .getString("CompilerConfigurationBlock.ignore") //$NON-NLS-1$
+ };
+
+ String[] enabledDisabled = new String[] { ENABLED, DISABLED };
+
+ int nColumns = 3;
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = nColumns;
+
+ Composite composite = new Composite(folder, SWT.NULL);
+ composite.setLayout(layout);
+
+ Label description = new Label(composite, SWT.WRAP);
+ description.setText(PreferencesMessages
+ .getString("CompilerConfigurationBlock.advanced.description")); //$NON-NLS-1$
+ GridData gd = new GridData();
+ gd.horizontalSpan = nColumns;
+ gd.widthHint = fPixelConverter.convertWidthInCharsToPixels(50);
+ description.setLayoutData(gd);
+
+ // String label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_synth_access_emul.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_SYNTHETIC_ACCESS_EMULATION,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_local_variable_hiding.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_LOCAL_VARIABLE_HIDING,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ // int indent= fPixelConverter.convertWidthInCharsToPixels(2);
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_special_param_hiding.label");
+ // //$NON-NLS-1$
+ // addCheckBox(composite, label, PREF_PB_SPECIAL_PARAMETER_HIDING_FIELD,
+ // enabledDisabled, indent);
+
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_field_hiding.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_FIELD_HIDING,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_non_externalized_strings.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_NON_EXTERNALIZED_STRINGS,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_incompatible_interface_method.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_INCOMPATIBLE_INTERFACE_METHOD,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_char_array_in_concat.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_CHAR_ARRAY_IN_CONCAT,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ // label=
+ // PreferencesMessages.getString("CompilerConfigurationBlock.pb_unqualified_field_access.label");
+ // //$NON-NLS-1$
+ // addComboBox(composite, label, PREF_PB_UNQUALIFIED_FIELD_ACCESS,
+ // errorWarningIgnore, errorWarningIgnoreLabels, 0);
+
+ gd = new GridData();
+ gd.widthHint = fPixelConverter.convertWidthInCharsToPixels(6);
+
+ String label = PreferencesMessages
+ .getString("CompilerConfigurationBlock.pb_max_per_unit.label"); //$NON-NLS-1$
+ Text text = addTextField(composite, label, PREF_PB_MAX_PER_UNIT, 0, 0);
+ text.setTextLimit(6);
+ text.setLayoutData(gd);
+
+ return composite;
+ }
+
+ /*
+ * (non-javadoc) Update fields and validate. @param changedKey Key that
+ * changed, or null, if all changed.
+ */
+ protected void validateSettings(String changedKey, String newValue) {
+
+ if (changedKey != null) {
+ // if (INTR_DEFAULT_COMPLIANCE.equals(changedKey)) {
+ // updateComplianceEnableState();
+ // if (DEFAULT_CONF.equals(newValue)) {
+ // updateComplianceDefaultSettings();
+ // }
+ // fComplianceStatus= validateCompliance();
+ // } else if (PREF_COMPLIANCE.equals(changedKey)) {
+ // if (checkValue(INTR_DEFAULT_COMPLIANCE, DEFAULT_CONF)) {
+ // updateComplianceDefaultSettings();
+ // }
+ // fComplianceStatus= validateCompliance();
+ // } else if (PREF_SOURCE_COMPATIBILITY.equals(changedKey) ||
+ // PREF_CODEGEN_TARGET_PLATFORM.equals(changedKey) ||
+ // PREF_PB_ASSERT_AS_IDENTIFIER.equals(changedKey)) {
+ // fComplianceStatus= validateCompliance();
+ // } else
+ if (PREF_PB_MAX_PER_UNIT.equals(changedKey)) {
+ fMaxNumberProblemsStatus = validateMaxNumberProblems();
+ // } else if (PREF_RESOURCE_FILTER.equals(changedKey)) {
+ // fResourceFilterStatus= validateResourceFilters();
+ // } else if (S.equals(changedKey) ||
+ // PREF_PB_DEPRECATION.equals(changedKey) ) { // ||
+ // // PREF_PB_INVALID_JAVADOC.equals(changedKey) ||
+ // // PREF_PB_MISSING_JAVADOC_TAGS.equals(changedKey) ||
+ // // PREF_PB_MISSING_JAVADOC_COMMENTS.equals(changedKey) ||
+ // // PREF_PB_MISSING_JAVADOC_COMMENTS.equals(changedKey) ||
+ // //
+ // PREF_PB_UNUSED_DECLARED_THROWN_EXCEPTION.equals(changedKey))
+ // {
+ // updateEnableStates();
+ // } else if
+ // (PREF_PB_SIGNAL_PARAMETER_IN_OVERRIDING.equals(changedKey)) {
+ // // merging the two options
+ // fWorkingValues.put(PREF_PB_SIGNAL_PARAMETER_IN_ABSTRACT,
+ // newValue);
+ } else {
+ return;
+ }
+ } else {
+ // updateEnableStates();
+ // updateComplianceEnableState();
+ // fComplianceStatus= validateCompliance();
+ fMaxNumberProblemsStatus = validateMaxNumberProblems();
+ // fResourceFilterStatus= validateResourceFilters();
+ }
+ // IStatus status= StatusUtil.getMostSevere(new IStatus[] {
+ // fComplianceStatus, fMaxNumberProblemsStatus, fResourceFilterStatus
+ // });
+ IStatus status = StatusUtil
+ .getMostSevere(new IStatus[] { fMaxNumberProblemsStatus });
+ fContext.statusChanged(status);
+ }
+
+ // private void updateEnableStates() {
+ // boolean enableUnusedParams= !checkValue(PREF_PB_UNUSED_PARAMETER,
+ // IGNORE);
+ // getCheckBox(PREF_PB_SIGNAL_PARAMETER_IN_OVERRIDING).setEnabled(enableUnusedParams);
+
+ // boolean enableDeprecation= !checkValue(PREF_PB_DEPRECATION, IGNORE);
+ // getCheckBox(PREF_PB_DEPRECATION_IN_DEPRECATED_CODE).setEnabled(enableDeprecation);
+ // getCheckBox(PREF_PB_DEPRECATION_WHEN_OVERRIDING).setEnabled(enableDeprecation);
+ //
+ // boolean enableThrownExceptions=
+ // !checkValue(PREF_PB_UNUSED_DECLARED_THROWN_EXCEPTION, IGNORE);
+ // getCheckBox(PREF_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING).setEnabled(enableThrownExceptions);
+ //
+ // boolean enableHiding= !checkValue(PREF_PB_LOCAL_VARIABLE_HIDING, IGNORE);
+ // getCheckBox(PREF_PB_SPECIAL_PARAMETER_HIDING_FIELD).setEnabled(enableHiding);
+ //
+ // boolean enableInvalidTagsErrors= !checkValue(PREF_PB_INVALID_JAVADOC,
+ // IGNORE);
+ // getCheckBox(PREF_PB_INVALID_JAVADOC_TAGS).setEnabled(enableInvalidTagsErrors);
+ // setComboEnabled(PREF_PB_INVALID_JAVADOC_TAGS_VISIBILITY,
+ // enableInvalidTagsErrors);
+ //
+ // boolean enableMissingTagsErrors=
+ // !checkValue(PREF_PB_MISSING_JAVADOC_TAGS, IGNORE);
+ // getCheckBox(PREF_PB_MISSING_JAVADOC_TAGS_OVERRIDING).setEnabled(enableMissingTagsErrors);
+ // setComboEnabled(PREF_PB_MISSING_JAVADOC_TAGS_VISIBILITY,
+ // enableMissingTagsErrors);
+ //
+ // boolean enableMissingCommentsErrors=
+ // !checkValue(PREF_PB_MISSING_JAVADOC_COMMENTS, IGNORE);
+ // getCheckBox(PREF_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING).setEnabled(enableMissingCommentsErrors);
+ // setComboEnabled(PREF_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY,
+ // enableMissingCommentsErrors);
+ // }
+
+ // private IStatus validateCompliance() {
+ // StatusInfo status= new StatusInfo();
+ // if (checkValue(PREF_COMPLIANCE, VERSION_1_3)) {
+ // if (checkValue(PREF_SOURCE_COMPATIBILITY, VERSION_1_4)) {
+ // status.setError(PreferencesMessages.getString("CompilerConfigurationBlock.cpl13src14.error"));
+ // //$NON-NLS-1$
+ // return status;
+ // } else if (checkValue(PREF_CODEGEN_TARGET_PLATFORM, VERSION_1_4)) {
+ // status.setError(PreferencesMessages.getString("CompilerConfigurationBlock.cpl13trg14.error"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ // }
+ // if (checkValue(PREF_SOURCE_COMPATIBILITY, VERSION_1_4)) {
+ // if (!checkValue(PREF_PB_ASSERT_AS_IDENTIFIER, ERROR)) {
+ // status.setError(PreferencesMessages.getString("CompilerConfigurationBlock.src14asrterr.error"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ // }
+ // if (checkValue(PREF_SOURCE_COMPATIBILITY, VERSION_1_4)) {
+ // if (!checkValue(PREF_CODEGEN_TARGET_PLATFORM, VERSION_1_4)) {
+ // status.setError(PreferencesMessages.getString("CompilerConfigurationBlock.src14tgt14.error"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ // }
+ // return status;
+ // }
+
+ private IStatus validateMaxNumberProblems() {
+ String number = (String) fWorkingValues.get(PREF_PB_MAX_PER_UNIT);
+ StatusInfo status = new StatusInfo();
+ if (number.length() == 0) {
+ status.setError(PreferencesMessages
+ .getString("CompilerConfigurationBlock.empty_input")); //$NON-NLS-1$
+ } else {
+ try {
+ int value = Integer.parseInt(number);
+ if (value <= 0) {
+ status
+ .setError(PreferencesMessages
+ .getFormattedString(
+ "CompilerConfigurationBlock.invalid_input", number)); //$NON-NLS-1$
+ }
+ } catch (NumberFormatException e) {
+ status.setError(PreferencesMessages.getFormattedString(
+ "CompilerConfigurationBlock.invalid_input", number)); //$NON-NLS-1$
+ }
+ }
+ return status;
+ }
+
+ // private IStatus validateResourceFilters() {
+ // String text= (String) fWorkingValues.get(PREF_RESOURCE_FILTER);
+ //
+ // IWorkspace workspace= ResourcesPlugin.getWorkspace();
+ //
+ // String[] filters= getTokens(text, ","); //$NON-NLS-1$
+ // for (int i= 0; i < filters.length; i++) {
+ // String fileName= filters[i].replace('*', 'x');
+ // int resourceType= IResource.FILE;
+ // int lastCharacter= fileName.length() - 1;
+ // if (lastCharacter >= 0 && fileName.charAt(lastCharacter) == '/') {
+ // fileName= fileName.substring(0, lastCharacter);
+ // resourceType= IResource.FOLDER;
+ // }
+ // IStatus status= workspace.validateName(fileName, resourceType);
+ // if (status.matches(IStatus.ERROR)) {
+ // String message=
+ // PreferencesMessages.getFormattedString("CompilerConfigurationBlock.filter.invalidsegment.error",
+ // status.getMessage()); //$NON-NLS-1$
+ // return new StatusInfo(IStatus.ERROR, message);
+ // }
+ // }
+ // return new StatusInfo();
+ // }
+
+ protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
+ String title = PreferencesMessages
+ .getString("CompilerConfigurationBlock.needsbuild.title"); //$NON-NLS-1$
+ String message;
+ if (workspaceSettings) {
+ message = PreferencesMessages
+ .getString("CompilerConfigurationBlock.needsfullbuild.message"); //$NON-NLS-1$
+ } else {
+ message = PreferencesMessages
+ .getString("CompilerConfigurationBlock.needsprojectbuild.message"); //$NON-NLS-1$
+ }
+ return new String[] { title, message };
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerPreferencePage.java
new file mode 100644
index 0000000..5137ae2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerPreferencePage.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+
+/*
+ * The page to configure the compiler options.
+ */
+public class CompilerPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage, IStatusChangeListener {
+
+ private CompilerConfigurationBlock fConfigurationBlock;
+
+ public CompilerPreferencePage() {
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+ setDescription(PreferencesMessages
+ .getString("CompilerPreferencePage.description")); //$NON-NLS-1$
+
+ // only used when page is shown programatically
+ setTitle(PreferencesMessages.getString("CompilerPreferencePage.title")); //$NON-NLS-1$
+
+ fConfigurationBlock = new CompilerConfigurationBlock(this, null);
+ }
+
+ /*
+ * @see IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * @see PreferencePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.COMPILER_PREFERENCE_PAGE);
+ }
+
+ /*
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ Control result = fConfigurationBlock.createContents(parent);
+ Dialog.applyDialogFont(result);
+ return result;
+ }
+
+ /*
+ * @see IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ if (!fConfigurationBlock.performOk(true)) {
+ return false;
+ }
+ return super.performOk();
+ }
+
+ /*
+ * @see PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ fConfigurationBlock.performDefaults();
+ super.performDefaults();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus)
+ */
+ public void statusChanged(IStatus status) {
+ setValid(!status.matches(IStatus.ERROR));
+ StatusUtil.applyToStatusLine(this, status);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerPropertyPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerPropertyPage.java
new file mode 100644
index 0000000..377710b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CompilerPropertyPage.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.ControlEnableState;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.IPreferenceNode;
+import org.eclipse.jface.preference.IPreferencePage;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.preference.PreferenceManager;
+import org.eclipse.jface.preference.PreferenceNode;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+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.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Property page used to configure project specific compiler settings
+ */
+public class CompilerPropertyPage extends PropertyPage {
+
+ private CompilerConfigurationBlock fConfigurationBlock;
+
+ private Control fConfigurationBlockControl;
+
+ private ControlEnableState fBlockEnableState;
+
+ private SelectionButtonDialogField fUseWorkspaceSettings;
+
+ private SelectionButtonDialogField fChangeWorkspaceSettings;
+
+ private SelectionButtonDialogField fUseProjectSettings;
+
+ private IStatus fBlockStatus;
+
+ public CompilerPropertyPage() {
+ fBlockStatus = new StatusInfo();
+ fBlockEnableState = null;
+
+ IDialogFieldListener listener = new IDialogFieldListener() {
+ public void dialogFieldChanged(DialogField field) {
+ doDialogFieldChanged(field);
+ }
+ };
+
+ fUseWorkspaceSettings = new SelectionButtonDialogField(SWT.RADIO);
+ fUseWorkspaceSettings.setDialogFieldListener(listener);
+ fUseWorkspaceSettings.setLabelText(PreferencesMessages
+ .getString("CompilerPropertyPage.useworkspacesettings.label")); //$NON-NLS-1$
+
+ fChangeWorkspaceSettings = new SelectionButtonDialogField(SWT.PUSH);
+ fChangeWorkspaceSettings.setLabelText(PreferencesMessages
+ .getString("CompilerPropertyPage.useworkspacesettings.change")); //$NON-NLS-1$
+ fChangeWorkspaceSettings.setDialogFieldListener(listener);
+
+ fUseWorkspaceSettings.attachDialogField(fChangeWorkspaceSettings);
+
+ fUseProjectSettings = new SelectionButtonDialogField(SWT.RADIO);
+ fUseProjectSettings.setDialogFieldListener(listener);
+ fUseProjectSettings.setLabelText(PreferencesMessages
+ .getString("CompilerPropertyPage.useprojectsettings.label")); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.COMPILER_PROPERTY_PAGE);
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ IStatusChangeListener listener = new IStatusChangeListener() {
+ public void statusChanged(IStatus status) {
+ fBlockStatus = status;
+ doStatusChanged();
+ }
+ };
+ fConfigurationBlock = new CompilerConfigurationBlock(listener,
+ getProject());
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+
+ fUseWorkspaceSettings.doFillIntoGrid(composite, 1);
+ LayoutUtil.setHorizontalGrabbing(fUseWorkspaceSettings
+ .getSelectionButton(null));
+
+ fChangeWorkspaceSettings.doFillIntoGrid(composite, 1);
+
+ fUseProjectSettings.doFillIntoGrid(composite, 2);
+
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.VERTICAL_ALIGN_FILL);
+ data.horizontalSpan = 2;
+
+ fConfigurationBlockControl = fConfigurationBlock
+ .createContents(composite);
+ fConfigurationBlockControl.setLayoutData(data);
+
+ boolean useProjectSettings = fConfigurationBlock
+ .hasProjectSpecificOptions();
+
+ fUseProjectSettings.setSelection(useProjectSettings);
+ fUseWorkspaceSettings.setSelection(!useProjectSettings);
+
+ updateEnableState();
+ Dialog.applyDialogFont(composite);
+ return composite;
+ }
+
+ private boolean useProjectSettings() {
+ return fUseProjectSettings.isSelected();
+ }
+
+ private void doDialogFieldChanged(DialogField field) {
+ if (field == fChangeWorkspaceSettings) {
+ String id = "net.sourceforge.phpdt.ui.preferences.CompilerPreferencePage"; //$NON-NLS-1$
+ CompilerPreferencePage page = new CompilerPreferencePage();
+ showPreferencePage(id, page);
+ } else {
+ updateEnableState();
+ doStatusChanged();
+ }
+ }
+
+ /**
+ * Method statusChanged.
+ */
+ private void doStatusChanged() {
+ updateStatus(useProjectSettings() ? fBlockStatus : new StatusInfo());
+ }
+
+ /**
+ * Method getProject.
+ */
+ private IJavaProject getProject() {
+ return (IJavaProject) getElement().getAdapter(IJavaElement.class);
+ }
+
+ private void updateEnableState() {
+ if (useProjectSettings()) {
+ if (fBlockEnableState != null) {
+ fBlockEnableState.restore();
+ fBlockEnableState = null;
+ }
+ } else {
+ if (fBlockEnableState == null) {
+ fBlockEnableState = ControlEnableState
+ .disable(fConfigurationBlockControl);
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ if (useProjectSettings()) {
+ fUseProjectSettings.setSelection(false);
+ fUseWorkspaceSettings.setSelection(true);
+ fConfigurationBlock.performDefaults();
+ }
+ super.performDefaults();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ return fConfigurationBlock.performOk(useProjectSettings());
+ }
+
+ private void updateStatus(IStatus status) {
+ setValid(!status.matches(IStatus.ERROR));
+ StatusUtil.applyToStatusLine(this, status);
+ }
+
+ private boolean showPreferencePage(String id, IPreferencePage page) {
+ final IPreferenceNode targetNode = new PreferenceNode(id, page);
+
+ PreferenceManager manager = new PreferenceManager();
+ manager.addToRoot(targetNode);
+ final PreferenceDialog dialog = new PreferenceDialog(getControl()
+ .getShell(), manager);
+ final boolean[] result = new boolean[] { false };
+ BusyIndicator.showWhile(getControl().getDisplay(), new Runnable() {
+ public void run() {
+ dialog.create();
+ dialog.setMessage(targetNode.getLabelText());
+ result[0] = (dialog.open() == Window.OK);
+ }
+ });
+ return result[0];
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditTemplateDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditTemplateDialog.java
new file mode 100644
index 0000000..e0b3d24
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditTemplateDialog.java
@@ -0,0 +1,638 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusDialog;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.template.preferences.TemplateVariableProcessor;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+import net.sourceforge.phpdt.ui.IContextMenuConstants;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+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.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.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.custom.VerifyKeyListener;
+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.events.VerifyEvent;
+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.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.IUpdate;
+
+/**
+ * Dialog to edit a template.
+ */
+public 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() {
+
+ 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 final Template fTemplate;
+
+ private Text fNameText;
+
+ private Text fDescriptionText;
+
+ private Combo fContextCombo;
+
+ private SourceViewer fPatternEditor;
+
+ private Button fInsertVariableButton;
+
+ private boolean fIsNameModifiable;
+
+ private StatusInfo fValidationStatus;
+
+ private boolean fSuppressError = true; // #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 registry
+ * the context type registry to use
+ */
+ public EditTemplateDialog(Shell parent, Template template, boolean edit,
+ boolean isNameModifiable, ContextTypeRegistry registry) {
+ super(parent);
+
+ setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE);
+
+ String title = edit ? PreferencesMessages
+ .getString("EditTemplateDialog.title.edit") //$NON-NLS-1$
+ : PreferencesMessages.getString("EditTemplateDialog.title.new"); //$NON-NLS-1$
+ setTitle(title);
+
+ fTemplate = template;
+ fIsNameModifiable = isNameModifiable;
+
+ // XXX workaround for bug 63313 - disabling prefix until fixed.
+ // String delim= new Document().getLegalLineDelimiters()[0];
+
+ List contexts = new ArrayList();
+ for (Iterator it = registry.contextTypes(); it.hasNext();) {
+ TemplateContextType type = (TemplateContextType) it.next();
+ // if (type.getId().equals("javadoc")) //$NON-NLS-1$
+ // contexts.add(new String[] { type.getId(), type.getName(), "/**" +
+ // delim }); //$NON-NLS-1$
+ // else
+ contexts.add(new String[] { type.getId(), type.getName(), "" }); //$NON-NLS-1$
+ }
+ fContextTypes = (String[][]) contexts.toArray(new String[contexts
+ .size()][]);
+
+ fValidationStatus = new StatusInfo();
+
+ fContextTypeRegistry = registry;
+
+ TemplateContextType type = fContextTypeRegistry.getContextType(template
+ .getContextTypeId());
+ fTemplateProcessor.setContextType(type);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.dialogs.StatusDialog#create()
+ */
+ public void create() {
+ super.create();
+ // update initial ok button to be disabled for new templates
+ boolean valid = fNameText == null
+ || fNameText.getText().trim().length() != 0;
+ if (!valid) {
+ StatusInfo status = new StatusInfo();
+ status.setError(PreferencesMessages
+ .getString("EditTemplateDialog.error.noname")); //$NON-NLS-1$
+ updateButtonsEnableState(status);
+ }
+ }
+
+ /*
+ * @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
+ .getString("EditTemplateDialog.name")); //$NON-NLS-1$
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ layout = new GridLayout();
+ layout.numColumns = 3;
+ 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;
+ updateButtons();
+ }
+ }
+ });
+
+ createLabel(composite, PreferencesMessages
+ .getString("EditTemplateDialog.context")); //$NON-NLS-1$
+ fContextCombo = new Combo(composite, SWT.READ_ONLY);
+
+ for (int i = 0; i < fContextTypes.length; i++) {
+ fContextCombo.add(fContextTypes[i][1]);
+ }
+
+ fContextCombo.addModifyListener(listener);
+ }
+
+ createLabel(parent, PreferencesMessages
+ .getString("EditTemplateDialog.description")); //$NON-NLS-1$
+
+ 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
+ .getString("EditTemplateDialog.pattern")); //$NON-NLS-1$
+ 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));
+ fInsertVariableButton.setText(PreferencesMessages
+ .getString("EditTemplateDialog.insert.variable")); //$NON-NLS-1$
+ 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);
+ fContextCombo.select(getIndex(fTemplate.getContextTypeId()));
+ } else {
+ fPatternEditor.getControl().setFocus();
+ }
+ initializeActions();
+
+ applyDialogFont(parent);
+ return composite;
+ }
+
+ protected void doTextWidgetChanged(Widget w) {
+ if (w == fNameText) {
+ fSuppressError = false;
+ String name = fNameText.getText();
+ fTemplate.setName(name);
+ updateButtons();
+ } else if (w == fContextCombo) {
+ String name = fContextCombo.getText();
+ String contextId = getContextId(name);
+ fTemplate.setContextTypeId(contextId);
+ fTemplateProcessor.setContextType(fContextTypeRegistry
+ .getContextType(contextId));
+ } else if (w == fDescriptionText) {
+ String desc = fDescriptionText.getText();
+ fTemplate.setDescription(desc);
+ }
+ }
+
+ private String getContextId(String name) {
+ if (name == null)
+ return name;
+
+ for (int i = 0; i < fContextTypes.length; i++) {
+ if (name.equals(fContextTypes[i][1])) {
+ return fContextTypes[i][0];
+ }
+ }
+ return name;
+ }
+
+ protected void doSourceChanged(IDocument document) {
+ String text = document.get();
+ String prefix = getPrefix();
+ fTemplate.setPattern(text.substring(prefix.length(), text.length()));
+ fValidationStatus.setOK();
+ TemplateContextType contextType = fContextTypeRegistry
+ .getContextType(fTemplate.getContextTypeId());
+ if (contextType != null) {
+ try {
+ contextType.validate(text);
+ } catch (TemplateException e) {
+ fValidationStatus.setError(e.getLocalizedMessage());
+ }
+ }
+
+ updateUndoAction();
+ updateButtons();
+ }
+
+ private static GridData getButtonGridData(Button button) {
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ data.heightHint = SWTUtil.getButtonHeightHint(button);
+
+ 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 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());
+ JavaTextTools tools = WebUI.getDefault().getJavaTextTools();
+ tools.setupJavaDocumentPartitioner(document,
+ IPHPPartitions.PHP_PARTITIONING);
+ IPreferenceStore store = WebUI.getDefault()
+ .getCombinedPreferenceStore();
+ SourceViewer viewer = new JavaSourceViewer(parent, null, null, false,
+ SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store);
+ TemplateEditorSourceViewerConfiguration configuration = new TemplateEditorSourceViewerConfiguration(
+ tools.getColorManager(), store, null, fTemplateProcessor);
+ viewer.configure(configuration);
+ viewer.setEditable(true);
+ // XXX workaround for bug 63313 - disabling prefix until fixed.
+ // viewer.setDocument(document, prefix.length(), document.getLength() -
+ // prefix.length());
+ viewer.setDocument(document);
+
+ Font font = JFaceResources
+ .getFont(PreferenceConstants.EDITOR_TEXT_FONT);
+ viewer.getTextWidget().setFont(font);
+ new JavaSourcePreviewerUpdater(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();
+ }
+ });
+
+ viewer.prependVerifyKeyListener(new VerifyKeyListener() {
+ public void verifyKey(VerifyEvent event) {
+ handleVerifyKeyPressed(event);
+ }
+ });
+
+ return viewer;
+ }
+
+ private String getPrefix() {
+ String prefix;
+ int idx = getIndex(fTemplate.getContextTypeId());
+ if (idx != -1)
+ prefix = fContextTypes[idx][2];
+ else
+ prefix = ""; //$NON-NLS-1$
+
+ return prefix;
+ }
+
+ private void handleVerifyKeyPressed(VerifyEvent event) {
+ if (!event.doit)
+ return;
+
+ if (event.stateMask != SWT.MOD1)
+ return;
+
+ switch (event.character) {
+ case ' ':
+ fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
+ event.doit = false;
+ break;
+
+ // CTRL-Z
+ case 'z' - 'a' + 1:
+ fPatternEditor.doOperation(ITextOperationTarget.UNDO);
+ event.doit = false;
+ break;
+ }
+ }
+
+ private void initializeActions() {
+ TextViewerAction action = new TextViewerAction(fPatternEditor,
+ SourceViewer.UNDO);
+ action
+ .setText(PreferencesMessages
+ .getString("EditTemplateDialog.undo")); //$NON-NLS-1$
+ fGlobalActions.put(ITextEditorActionConstants.UNDO, action);
+
+ action = new TextViewerAction(fPatternEditor, SourceViewer.CUT);
+ action.setText(PreferencesMessages.getString("EditTemplateDialog.cut")); //$NON-NLS-1$
+ fGlobalActions.put(ITextEditorActionConstants.CUT, action);
+
+ action = new TextViewerAction(fPatternEditor, SourceViewer.COPY);
+ action
+ .setText(PreferencesMessages
+ .getString("EditTemplateDialog.copy")); //$NON-NLS-1$
+ fGlobalActions.put(ITextEditorActionConstants.COPY, action);
+
+ action = new TextViewerAction(fPatternEditor, SourceViewer.PASTE);
+ action.setText(PreferencesMessages
+ .getString("EditTemplateDialog.paste")); //$NON-NLS-1$
+ fGlobalActions.put(ITextEditorActionConstants.PASTE, action);
+
+ action = new TextViewerAction(fPatternEditor, SourceViewer.SELECT_ALL);
+ action.setText(PreferencesMessages
+ .getString("EditTemplateDialog.select.all")); //$NON-NLS-1$
+ fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action);
+
+ action = new TextViewerAction(fPatternEditor,
+ SourceViewer.CONTENTASSIST_PROPOSALS);
+ action.setText(PreferencesMessages
+ .getString("EditTemplateDialog.content.assist")); //$NON-NLS-1$
+ fGlobalActions.put("ContentAssistProposal", action); //$NON-NLS-1$
+
+ 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.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 updateUndoAction() {
+ IAction action = (IAction) fGlobalActions
+ .get(ITextEditorActionConstants.UNDO);
+ if (action instanceof IUpdate)
+ ((IUpdate) action).update();
+ }
+
+ 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() {
+ super.okPressed();
+ }
+
+ private void updateButtons() {
+ StatusInfo status;
+
+ boolean valid = fNameText == null
+ || fNameText.getText().trim().length() != 0;
+ if (!valid) {
+ status = new StatusInfo();
+ if (!fSuppressError) {
+ status.setError(PreferencesMessages
+ .getString("EditTemplateDialog.error.noname")); //$NON-NLS-1$
+ }
+ } else {
+ status = fValidationStatus;
+ }
+ updateStatus(status);
+ }
+
+ /*
+ * @see org.eclipse.jface.window.Window#configureShell(Shell)
+ */
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
+ IJavaHelpContextIds.EDIT_TEMPLATE_DIALOG);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditorConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditorConfigurationBlock.java
new file mode 100644
index 0000000..53482fd
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditorConfigurationBlock.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+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.Group;
+
+/**
+ * Options configuration block for editor related settings.
+ *
+ * @since 3.0
+ */
+public class EditorConfigurationBlock extends OptionsConfigurationBlock {
+
+ /** Preference keys for the preferences in this block */
+ private static final String PREF_EDITOR_SAVE_ON_BLUR = PreferenceConstants.EDITOR_SAVE_ON_BLUR;
+
+ private static final String PREF_EDITOR_P_RTRIM_ON_SAVE = PreferenceConstants.EDITOR_P_RTRIM_ON_SAVE;
+
+ /**
+ * Creates a new editor configuration block.
+ *
+ * @param context
+ * The status change listener
+ * @param project
+ * The Java project
+ */
+ public EditorConfigurationBlock(final IStatusChangeListener context,
+ final IJavaProject project) {
+ super(context, project, getAllKeys());
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(final Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+
+ final String[] trueFalse = new String[] { IPreferenceStore.TRUE,
+ IPreferenceStore.FALSE };
+
+ Group user = new Group(composite, SWT.NONE);
+ user.setText(PreferencesMessages
+ .getString("EditorPreferencePage.file.title")); //$NON-NLS-1$
+ user.setLayout(new GridLayout());
+ user.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ String label = PreferencesMessages
+ .getString("EditorPreferencePage.save_on_blur"); //$NON-NLS-1$
+ addCheckBox(user, label, PREF_EDITOR_SAVE_ON_BLUR, trueFalse, 0);
+
+ label = PreferencesMessages
+ .getString("EditorPreferencePage.p_rtrim_on_save"); //$NON-NLS-1$
+ addCheckBox(user, label, PREF_EDITOR_P_RTRIM_ON_SAVE, trueFalse, 0);
+
+ return composite;
+ }
+
+ private static String[] getAllKeys() {
+ return new String[] { PREF_EDITOR_SAVE_ON_BLUR,
+ PREF_EDITOR_P_RTRIM_ON_SAVE };
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getDefaultOptions()
+ */
+ protected Map getDefaultOptions() {
+
+ final String[] keys = fAllKeys;
+ final Map options = new HashMap();
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ options.put(keys[index], store.getDefaultString(keys[index]));
+
+ return options;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
+ */
+ protected final String[] getFullBuildDialogStrings(final boolean workspace) {
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getOptions(boolean)
+ */
+ protected Map getOptions(final boolean inherit) {
+
+ final String[] keys = fAllKeys;
+ final Map options = new HashMap();
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ options.put(keys[index], store.getString(keys[index]));
+
+ return options;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#setOptions(java.util.Map)
+ */
+ protected void setOptions(final Map options) {
+
+ final String[] keys = fAllKeys;
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ store.setValue(keys[index], (String) fWorkingValues
+ .get(keys[index]));
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(java.lang.String,java.lang.String)
+ */
+ protected void validateSettings(final String key, final String value) {
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditorPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditorPreferencePage.java
new file mode 100644
index 0000000..5890cd0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/EditorPreferencePage.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Preference page for spell checking preferences.
+ *
+ * @since 3.0
+ */
+public class EditorPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage, IStatusChangeListener {
+
+ /** The spelling configuration block */
+ private final EditorConfigurationBlock fBlock = new EditorConfigurationBlock(
+ this, null);
+
+ /**
+ * Creates a new spelling preference page.
+ */
+ public EditorPreferencePage() {
+
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+ setDescription(PreferencesMessages
+ .getString("EditorPreferencePage.description")); //$NON-NLS-1$
+ setTitle(PreferencesMessages.getString("EditorPreferencePage.title")); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(final Composite parent) {
+
+ final Control control = fBlock.createContents(parent);
+ Dialog.applyDialogFont(control);
+
+ return control;
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(final Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.JAVA_EDITOR_PREFERENCE_PAGE);
+ }
+
+ /*
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(final IWorkbench workbench) {
+ // Do nothing
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ fBlock.performDefaults();
+
+ super.performDefaults();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+
+ if (!fBlock.performOk(true))
+ return false;
+
+ return super.performOk();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus)
+ */
+ public void statusChanged(final IStatus status) {
+ setValid(!status.matches(IStatus.ERROR));
+
+ StatusUtil.applyToStatusLine(this, status);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/FoldingConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/FoldingConfigurationBlock.java
new file mode 100644
index 0000000..242d87f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/FoldingConfigurationBlock.java
@@ -0,0 +1,398 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.text.folding.JavaFoldingStructureProviderDescriptor;
+import net.sourceforge.phpdt.internal.ui.text.folding.JavaFoldingStructureProviderRegistry;
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingPreferenceBlock;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+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;
+
+/**
+ * Configures Java Editor folding preferences.
+ *
+ * @since 3.0
+ */
+class FoldingConfigurationBlock {
+
+ private static class ErrorPreferences implements
+ IJavaFoldingPreferenceBlock {
+ private String fMessage;
+
+ protected ErrorPreferences(String message) {
+ fMessage = message;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.IJavaFoldingPreferences#createControl(org.eclipse.swt.widgets.Group)
+ */
+ public Control createControl(Composite composite) {
+ Composite inner = new Composite(composite, SWT.NONE);
+ inner.setLayout(new FillLayout(SWT.VERTICAL));
+
+ Label label = new Label(inner, SWT.CENTER);
+ label.setText(fMessage);
+
+ return inner;
+ }
+
+ public void initialize() {
+ }
+
+ public void performOk() {
+ }
+
+ public void performDefaults() {
+ }
+
+ public void dispose() {
+ }
+
+ }
+
+ /** The overlay preference store. */
+ private final OverlayPreferenceStore fStore;
+
+ /* The controls */
+ private Combo fProviderCombo;
+
+ private Button fFoldingCheckbox;
+
+ private ComboViewer fProviderViewer;
+
+ private Map fProviderDescriptors;
+
+ private Composite fGroup;
+
+ private Map fProviderPreferences;
+
+ private Map fProviderControls;
+
+ private StackLayout fStackLayout;
+
+ public FoldingConfigurationBlock(OverlayPreferenceStore store) {
+ Assert.isNotNull(store);
+ fStore = store;
+ fStore.addKeys(createOverlayStoreKeys());
+ fProviderDescriptors = createListModel();
+ fProviderPreferences = new HashMap();
+ fProviderControls = new HashMap();
+ }
+
+ private Map createListModel() {
+ JavaFoldingStructureProviderRegistry reg = WebUI
+ .getDefault().getFoldingStructureProviderRegistry();
+ reg.reloadExtensions();
+ JavaFoldingStructureProviderDescriptor[] descs = reg
+ .getFoldingProviderDescriptors();
+ Map map = new HashMap();
+ for (int i = 0; i < descs.length; i++) {
+ map.put(descs[i].getId(), descs[i]);
+ }
+ return map;
+ }
+
+ private OverlayPreferenceStore.OverlayKey[] createOverlayStoreKeys() {
+
+ ArrayList overlayKeys = new ArrayList();
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_FOLDING_ENABLED));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_FOLDING_PROVIDER));
+
+ OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys
+ .size()];
+ overlayKeys.toArray(keys);
+ return keys;
+ }
+
+ /**
+ * Creates page for folding preferences.
+ *
+ * @param parent
+ * the parent composite
+ * @return the control for the preference page
+ */
+ Control createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NULL);
+ // assume parent page uses griddata
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER
+ | GridData.VERTICAL_ALIGN_FILL);
+ composite.setLayoutData(gd);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ PixelConverter pc = new PixelConverter(composite);
+ layout.verticalSpacing = pc.convertHeightInCharsToPixels(1) / 2;
+ composite.setLayout(layout);
+
+ /* check box for new editors */
+ fFoldingCheckbox = new Button(composite, SWT.CHECK);
+ fFoldingCheckbox.setText(PreferencesMessages
+ .getString("FoldingConfigurationBlock.enable")); //$NON-NLS-1$
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING
+ | GridData.VERTICAL_ALIGN_BEGINNING);
+ fFoldingCheckbox.setLayoutData(gd);
+ fFoldingCheckbox.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean enabled = fFoldingCheckbox.getSelection();
+ fStore.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED,
+ enabled);
+ updateCheckboxDependencies();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ Label label = new Label(composite, SWT.CENTER);
+ gd = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.VERTICAL_ALIGN_BEGINNING);
+ label.setLayoutData(gd);
+
+ /* list */
+ Composite comboComp = new Composite(composite, SWT.NONE);
+ gd = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.VERTICAL_ALIGN_BEGINNING);
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = 0;
+ comboComp.setLayout(gridLayout);
+
+ Label comboLabel = new Label(comboComp, SWT.CENTER);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING
+ | GridData.VERTICAL_ALIGN_CENTER);
+ comboLabel.setLayoutData(gd);
+ comboLabel.setText(PreferencesMessages
+ .getString("FoldingConfigurationBlock.combo_caption")); //$NON-NLS-1$
+
+ label = new Label(composite, SWT.CENTER);
+ gd = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.VERTICAL_ALIGN_BEGINNING);
+ label.setLayoutData(gd);
+
+ fProviderCombo = new Combo(comboComp, SWT.READ_ONLY | SWT.DROP_DOWN);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_END
+ | GridData.VERTICAL_ALIGN_CENTER);
+ fProviderCombo.setLayoutData(gd);
+
+ /* list viewer */
+ fProviderViewer = new ComboViewer(fProviderCombo);
+ fProviderViewer.setContentProvider(new IStructuredContentProvider() {
+
+ /*
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
+ * java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput,
+ Object newInput) {
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ return fProviderDescriptors.values().toArray();
+ }
+ });
+ fProviderViewer.setLabelProvider(new LabelProvider() {
+ /*
+ * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ return ((JavaFoldingStructureProviderDescriptor) element)
+ .getName();
+ }
+ });
+ fProviderViewer
+ .addSelectionChangedListener(new ISelectionChangedListener() {
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection sel = (IStructuredSelection) event
+ .getSelection();
+ if (!sel.isEmpty()) {
+ fStore
+ .setValue(
+ PreferenceConstants.EDITOR_FOLDING_PROVIDER,
+ ((JavaFoldingStructureProviderDescriptor) sel
+ .getFirstElement()).getId());
+ updateListDependencies();
+ }
+ }
+ });
+ fProviderViewer.setInput(fProviderDescriptors);
+ fProviderViewer.refresh();
+
+ Composite groupComp = new Composite(composite, SWT.NONE);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = 2;
+ groupComp.setLayoutData(gd);
+ gridLayout = new GridLayout(1, false);
+ gridLayout.marginWidth = 0;
+ groupComp.setLayout(gridLayout);
+
+ /* contributed provider preferences. */
+ fGroup = new Composite(groupComp, SWT.NONE);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING
+ | GridData.VERTICAL_ALIGN_BEGINNING);
+ fGroup.setLayoutData(gd);
+ fStackLayout = new StackLayout();
+ fGroup.setLayout(fStackLayout);
+
+ return composite;
+ }
+
+ private void updateCheckboxDependencies() {
+ }
+
+ void updateListDependencies() {
+ String id = fStore
+ .getString(PreferenceConstants.EDITOR_FOLDING_PROVIDER);
+ JavaFoldingStructureProviderDescriptor desc = (JavaFoldingStructureProviderDescriptor) fProviderDescriptors
+ .get(id);
+ IJavaFoldingPreferenceBlock prefs;
+
+ if (desc == null) {
+ // safety in case there is no such descriptor
+ String message = PreferencesMessages
+ .getString("FoldingConfigurationBlock.error.not_exist"); //$NON-NLS-1$
+ WebUI.log(new Status(IStatus.WARNING, WebUI
+ .getPluginId(), IStatus.OK, message, null));
+ prefs = new ErrorPreferences(message);
+ } else {
+ prefs = (IJavaFoldingPreferenceBlock) fProviderPreferences.get(id);
+ if (prefs == null) {
+ try {
+ prefs = desc.createPreferences();
+ fProviderPreferences.put(id, prefs);
+ } catch (CoreException e) {
+ WebUI.log(e);
+ prefs = new ErrorPreferences(e.getLocalizedMessage());
+ }
+ }
+ }
+
+ Control control = (Control) fProviderControls.get(id);
+ if (control == null) {
+ control = prefs.createControl(fGroup);
+ if (control == null) {
+ String message = PreferencesMessages
+ .getString("FoldingConfigurationBlock.info.no_preferences"); //$NON-NLS-1$
+ control = new ErrorPreferences(message).createControl(fGroup);
+ } else {
+ fProviderControls.put(id, control);
+ }
+ }
+ fStackLayout.topControl = control;
+ control.pack();
+ fGroup.layout();
+ fGroup.getParent().layout();
+
+ prefs.initialize();
+ }
+
+ void initialize() {
+ restoreFromPreferences();
+ }
+
+ void performOk() {
+ for (Iterator it = fProviderPreferences.values().iterator(); it
+ .hasNext();) {
+ IJavaFoldingPreferenceBlock prefs = (IJavaFoldingPreferenceBlock) it
+ .next();
+ prefs.performOk();
+ }
+ }
+
+ void performDefaults() {
+ restoreFromPreferences();
+ for (Iterator it = fProviderPreferences.values().iterator(); it
+ .hasNext();) {
+ IJavaFoldingPreferenceBlock prefs = (IJavaFoldingPreferenceBlock) it
+ .next();
+ prefs.performDefaults();
+ }
+ }
+
+ void dispose() {
+ for (Iterator it = fProviderPreferences.values().iterator(); it
+ .hasNext();) {
+ IJavaFoldingPreferenceBlock prefs = (IJavaFoldingPreferenceBlock) it
+ .next();
+ prefs.dispose();
+ }
+ }
+
+ private void restoreFromPreferences() {
+ boolean enabled = fStore
+ .getBoolean(PreferenceConstants.EDITOR_FOLDING_ENABLED);
+ fFoldingCheckbox.setSelection(enabled);
+ updateCheckboxDependencies();
+
+ String id = fStore
+ .getString(PreferenceConstants.EDITOR_FOLDING_PROVIDER);
+ Object provider = fProviderDescriptors.get(id);
+ if (provider != null) {
+ fProviderViewer.setSelection(new StructuredSelection(provider),
+ true);
+ updateListDependencies();
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/IPreferenceConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/IPreferenceConfigurationBlock.java
new file mode 100644
index 0000000..10f856d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/IPreferenceConfigurationBlock.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Interface for preference configuration blocks which can either be wrapped by
+ * a
+ * {@link net.sourceforge.phpdt.internal.ui.preferences.AbstractConfigurationBlockPreferencePage}
+ * or be included some preference page.
+ * if filter was not set.
+ */
+ public String getFilter() {
+ if (fFilteredList == null)
+ return fFilter;
+ else
+ return fFilteredList.getFilter();
+ }
+
+ /**
+ * Returns the indices referring the current selection. To be called within
+ * open().
+ *
+ * @return returns the indices of the current selection.
+ */
+ protected int[] getSelectionIndices() {
+ Assert.isNotNull(fFilteredList);
+ return fFilteredList.getSelectionIndices();
+ }
+
+ /**
+ * Returns an index referring the first current selection. To be called
+ * within open().
+ *
+ * @return returns the indices of the current selection.
+ */
+ protected int getSelectionIndex() {
+ Assert.isNotNull(fFilteredList);
+ return fFilteredList.getSelectionIndex();
+ }
+
+ /**
+ * Sets the selection referenced by an array of elements. To be called
+ * within open().
+ *
+ * @param selection
+ * the indices of the selection.
+ */
+ protected void setSelection(Object[] selection) {
+ Assert.isNotNull(fFilteredList);
+ fFilteredList.setSelection(selection);
+ }
+
+ /**
+ * Returns an array of the currently selected elements. To be called within
+ * or after open().
+ *
+ * @return returns an array of the currently selected elements.
+ */
+ protected Object[] getSelectedElements() {
+ Assert.isNotNull(fFilteredList);
+ return fFilteredList.getSelection();
+ }
+
+ /**
+ * Returns all elements which are folded together to one entry in the list.
+ *
+ * @param index
+ * the index selecting the entry in the list.
+ * @return returns an array of elements folded together.
+ */
+ public Object[] getFoldedElements(int index) {
+ Assert.isNotNull(fFilteredList);
+ return fFilteredList.getFoldedElements(index);
+ }
+
+ /**
+ * Creates the message text widget and sets layout data.
+ *
+ * @param composite
+ * the parent composite of the message area.
+ */
+ protected Label createMessageArea(Composite composite) {
+ Label label = super.createMessageArea(composite);
+
+ GridData data = new GridData();
+ data.grabExcessVerticalSpace = false;
+ data.grabExcessHorizontalSpace = true;
+ data.horizontalAlignment = GridData.FILL;
+ data.verticalAlignment = GridData.BEGINNING;
+ label.setLayoutData(data);
+
+ fMessage = label;
+
+ return label;
+ }
+
+ /**
+ * Handles a selection changed event. By default, the current selection is
+ * validated.
+ */
+ protected void handleSelectionChanged() {
+ validateCurrentSelection();
+ }
+
+ /**
+ * Validates the current selection and updates the status line accordingly.
+ */
+ protected boolean validateCurrentSelection() {
+ Assert.isNotNull(fFilteredList);
+
+ IStatus status;
+ Object[] elements = getSelectedElements();
+
+ if (elements.length > 0) {
+ if (fValidator != null) {
+ status = fValidator.validate(elements);
+ } else {
+ status = new StatusInfo();
+ }
+ } else {
+ if (fFilteredList.isEmpty()) {
+ status = new StatusInfo(IStatus.ERROR, fEmptyListMessage);
+ } else {
+ status = new StatusInfo(IStatus.ERROR, fEmptySelectionMessage);
+ }
+ }
+
+ updateStatus(status);
+
+ return status.isOK();
+ }
+
+ /*
+ * @see Dialog#cancelPressed
+ */
+ protected void cancelPressed() {
+ setResult(null);
+ super.cancelPressed();
+ }
+
+ /**
+ * Creates a filtered list.
+ *
+ * @param parent
+ * the parent composite.
+ * @return returns the filtered list widget.
+ */
+ protected FilteredList createFilteredList(Composite parent) {
+ int flags = SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL
+ | (fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE);
+
+ FilteredList list = new FilteredList(parent, flags, fRenderer,
+ fIgnoreCase, fAllowDuplicates, fMatchEmptyString);
+
+ GridData data = new GridData();
+ data.widthHint = convertWidthInCharsToPixels(fWidth);
+ data.heightHint = convertHeightInCharsToPixels(fHeight);
+ data.grabExcessVerticalSpace = true;
+ data.grabExcessHorizontalSpace = true;
+ data.horizontalAlignment = GridData.FILL;
+ data.verticalAlignment = GridData.FILL;
+ list.setLayoutData(data);
+
+ list.setFilter((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
+
+ list.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ handleDefaultSelected();
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ handleWidgetSelected();
+ }
+ });
+
+ fFilteredList = list;
+
+ return list;
+ }
+
+ // 3515
+ private void handleWidgetSelected() {
+ Object[] newSelection = fFilteredList.getSelection();
+
+ if (newSelection.length != fSelection.length) {
+ fSelection = newSelection;
+ handleSelectionChanged();
+ } else {
+ for (int i = 0; i != newSelection.length; i++) {
+ if (!newSelection[i].equals(fSelection[i])) {
+ fSelection = newSelection;
+ handleSelectionChanged();
+ break;
+ }
+ }
+ }
+ }
+
+ protected Text createFilterText(Composite parent) {
+ Text text = new Text(parent, SWT.BORDER);
+
+ GridData data = new GridData();
+ data.grabExcessVerticalSpace = false;
+ data.grabExcessHorizontalSpace = true;
+ data.horizontalAlignment = GridData.FILL;
+ data.verticalAlignment = GridData.BEGINNING;
+ text.setLayoutData(data);
+
+ text.setText((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
+
+ Listener listener = new Listener() {
+ public void handleEvent(Event e) {
+ fFilteredList.setFilter(fFilterText.getText());
+ }
+ };
+ text.addListener(SWT.Modify, listener);
+
+ text.addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == SWT.ARROW_DOWN)
+ fFilteredList.setFocus();
+ }
+
+ public void keyReleased(KeyEvent e) {
+ }
+ });
+
+ fFilterText = text;
+
+ return text;
+ }
+
+ /*
+ * @see Window#open()
+ */
+ public int open() {
+ BusyIndicator.showWhile(null, new Runnable() {
+ public void run() {
+ access$superOpen();
+ }
+ });
+ return getReturnCode();
+ }
+
+ private void access$superOpen() {
+ super.open();
+ }
+
+ /*
+ * @see Window#create(Shell)
+ */
+ public void create() {
+ super.create();
+
+ Assert.isNotNull(fFilteredList);
+
+ if (fFilteredList.isEmpty()) {
+ handleEmptyList();
+ } else {
+ validateCurrentSelection();
+ fFilterText.selectAll();
+ fFilterText.setFocus();
+ }
+ }
+
+ /**
+ * Handles empty list by disabling widgets.
+ */
+ protected void handleEmptyList() {
+ fMessage.setEnabled(false);
+ fFilterText.setEnabled(false);
+ fFilteredList.setEnabled(false);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/CheckedTreeSelectionDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/CheckedTreeSelectionDialog.java
new file mode 100644
index 0000000..deb47fc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/CheckedTreeSelectionDialog.java
@@ -0,0 +1,353 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.viewsupport.ContainerCheckedTreeViewer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * A class to select elements out of a tree structure.
+ */
+public class CheckedTreeSelectionDialog extends SelectionStatusDialog {
+
+ private CheckboxTreeViewer fViewer;
+
+ private ILabelProvider fLabelProvider;
+
+ private ITreeContentProvider fContentProvider;
+
+ private ISelectionValidator fValidator = null;
+
+ private ViewerSorter fSorter;
+
+ private String fEmptyListMessage = "No entries available";
+
+ private IStatus fCurrStatus = new StatusInfo();
+
+ private List fFilters;
+
+ private Object fInput;
+
+ private boolean fIsEmpty;
+
+ private int fWidth = 60;
+
+ private int fHeight = 18;
+
+ private boolean fContainerMode;
+
+ private Object[] fExpandedElements;
+
+ /**
+ * Constructs an instance of
.
+ * Only those elements in the selection are part of the transfer which can be
+ * converted into an ElementTreeSelectionDialog
.
+ *
+ * @param labelProvider
+ * the label provider to render the entries
+ * @param contentProvider
+ * the content provider to evaluate the tree structure
+ */
+ public CheckedTreeSelectionDialog(Shell parent,
+ ILabelProvider labelProvider, ITreeContentProvider contentProvider) {
+ super(parent);
+
+ fLabelProvider = labelProvider;
+ fContentProvider = contentProvider;
+
+ setResult(new ArrayList(0));
+ setStatusLineAboveButtons(true);
+
+ fContainerMode = false;
+ fExpandedElements = null;
+
+ int shellStyle = getShellStyle();
+ setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
+ }
+
+ /**
+ * If set, the checked /gray state of containers (inner nodes) is derived
+ * from the checked state of its leaf nodes.
+ *
+ * @param containerMode
+ * The containerMode to set
+ */
+ public void setContainerMode(boolean containerMode) {
+ fContainerMode = containerMode;
+ }
+
+ /**
+ * Sets the initial selection. Convenience method.
+ *
+ * @param selection
+ * the initial selection.
+ */
+ public void setInitialSelection(Object selection) {
+ setInitialSelections(new Object[] { selection });
+ }
+
+ /**
+ * Sets the message to be displayed if the list is empty.
+ *
+ * @param message
+ * the message to be displayed.
+ */
+ public void setEmptyListMessage(String message) {
+ fEmptyListMessage = message;
+ }
+
+ /**
+ * Sets the sorter used by the tree viewer.
+ */
+ public void setSorter(ViewerSorter sorter) {
+ fSorter = sorter;
+ }
+
+ /**
+ * Adds a filter to the tree viewer.
+ *
+ * @param filter
+ * a filter.
+ */
+ public void addFilter(ViewerFilter filter) {
+ if (fFilters == null)
+ fFilters = new ArrayList(4);
+
+ fFilters.add(filter);
+ }
+
+ /**
+ * Sets an optional validator to check if the selection is valid. The
+ * validator is invoked whenever the selection changes.
+ *
+ * @param validator
+ * the validator to validate the selection.
+ */
+ public void setValidator(ISelectionValidator validator) {
+ fValidator = validator;
+ }
+
+ /**
+ * Sets the tree input.
+ *
+ * @param input
+ * the tree input.
+ */
+ public void setInput(Object input) {
+ fInput = input;
+ }
+
+ /**
+ * Expands the tree
+ */
+ public void setExpandedElements(Object[] elements) {
+ fExpandedElements = elements;
+ }
+
+ /**
+ * Sets the size of the tree in unit of characters.
+ *
+ * @param width
+ * the width of the tree.
+ * @param height
+ * the height of the tree.
+ */
+ public void setSize(int width, int height) {
+ fWidth = width;
+ fHeight = height;
+ }
+
+ protected void updateOKStatus() {
+ if (!fIsEmpty) {
+ if (fValidator != null) {
+ fCurrStatus = fValidator.validate(fViewer.getCheckedElements());
+ updateStatus(fCurrStatus);
+ } else if (!fCurrStatus.isOK()) {
+ fCurrStatus = new StatusInfo();
+ }
+ } else {
+ fCurrStatus = new StatusInfo(IStatus.ERROR, fEmptyListMessage);
+ }
+ updateStatus(fCurrStatus);
+ }
+
+ /*
+ * @see Window#open()
+ */
+ public int open() {
+ fIsEmpty = evaluateIfTreeEmpty(fInput);
+ BusyIndicator.showWhile(null, new Runnable() {
+ public void run() {
+ access$superOpen();
+ }
+ });
+
+ return getReturnCode();
+ }
+
+ private void access$superOpen() {
+ super.open();
+ }
+
+ /**
+ * Handles cancel button pressed event.
+ */
+ protected void cancelPressed() {
+ setResult(null);
+ super.cancelPressed();
+ }
+
+ /*
+ * @see SelectionStatusDialog#computeResult()
+ */
+ protected void computeResult() {
+ setResult(Arrays.asList(fViewer.getCheckedElements()));
+ }
+
+ /*
+ * @see Window#create()
+ */
+ public void create() {
+ super.create();
+
+ List initialSelections = getInitialElementSelections();
+ if (initialSelections != null) {
+ fViewer.setCheckedElements(initialSelections.toArray());
+ }
+
+ if (fExpandedElements != null) {
+ fViewer.setExpandedElements(fExpandedElements);
+ }
+
+ updateOKStatus();
+ }
+
+ /*
+ * @see Dialog#createDialogArea(Composite)
+ */
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ Label messageLabel = createMessageArea(composite);
+ Control treeWidget = createTreeViewer(composite);
+ Control buttonComposite = createSelectionButtons(composite);
+
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.widthHint = convertWidthInCharsToPixels(fWidth);
+ data.heightHint = convertHeightInCharsToPixels(fHeight);
+ treeWidget.setLayoutData(data);
+
+ if (fIsEmpty) {
+ messageLabel.setEnabled(false);
+ treeWidget.setEnabled(false);
+ buttonComposite.setEnabled(false);
+ }
+
+ return composite;
+ }
+
+ private Tree createTreeViewer(Composite parent) {
+ if (fContainerMode) {
+ fViewer = new ContainerCheckedTreeViewer(parent, SWT.BORDER);
+ } else {
+ fViewer = new CheckboxTreeViewer(parent, SWT.BORDER);
+ }
+
+ fViewer.setContentProvider(fContentProvider);
+ fViewer.setLabelProvider(fLabelProvider);
+ fViewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ updateOKStatus();
+ }
+ });
+
+ fViewer.setSorter(fSorter);
+ if (fFilters != null) {
+ for (int i = 0; i != fFilters.size(); i++)
+ fViewer.addFilter((ViewerFilter) fFilters.get(i));
+ }
+
+ fViewer.setInput(fInput);
+
+ return fViewer.getTree();
+ }
+
+ /**
+ * Add the selection and deselection buttons to the dialog.
+ *
+ * @param composite
+ * org.eclipse.swt.widgets.Composite
+ */
+ private Composite createSelectionButtons(Composite composite) {
+
+ Composite buttonComposite = new Composite(composite, SWT.RIGHT);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ buttonComposite.setLayout(layout);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
+ | GridData.GRAB_HORIZONTAL);
+ data.grabExcessHorizontalSpace = true;
+ composite.setData(data);
+
+ Button selectButton = createButton(buttonComposite,
+ IDialogConstants.SELECT_ALL_ID, "Select &All", false);
+
+ SelectionListener listener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ fViewer
+ .setCheckedElements(fContentProvider
+ .getElements(fInput));
+ updateOKStatus();
+ }
+ };
+ selectButton.addSelectionListener(listener);
+
+ Button deselectButton = createButton(buttonComposite,
+ IDialogConstants.DESELECT_ALL_ID, "&Deselect All", false);
+
+ listener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ fViewer.setCheckedElements(new Object[0]);
+ updateOKStatus();
+ }
+ };
+ deselectButton.addSelectionListener(listener);
+ return buttonComposite;
+ }
+
+ private boolean evaluateIfTreeEmpty(Object input) {
+ Object[] elements = fContentProvider.getElements(input);
+ if (elements.length > 0) {
+ if (fFilters != null) {
+ for (int i = 0; i < fFilters.size(); i++) {
+ ViewerFilter curr = (ViewerFilter) fFilters.get(i);
+ elements = curr.filter(fViewer, input, elements);
+ }
+ }
+ }
+ return elements.length == 0;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/ElementListSelectionDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/ElementListSelectionDialog.java
new file mode 100644
index 0000000..e8588c5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/ElementListSelectionDialog.java
@@ -0,0 +1,67 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A class to select elements out of a list of elements.
+ */
+public class ElementListSelectionDialog extends
+ AbstractElementListSelectionDialog {
+
+ private Object[] fElements;
+
+ /**
+ * Creates a list selection dialog.
+ *
+ * @param parent
+ * the parent widget.
+ * @param renderer
+ * the label renderer.
+ */
+ public ElementListSelectionDialog(Shell parent, ILabelProvider renderer) {
+ super(parent, renderer);
+ }
+
+ /**
+ * Sets the elements of the list.
+ *
+ * @param elements
+ * the elements of the list.
+ */
+ public void setElements(Object[] elements) {
+ fElements = elements;
+ }
+
+ /*
+ * @see SelectionStatusDialog#computeResult()
+ */
+ protected void computeResult() {
+ setResult(Arrays.asList(getSelectedElements()));
+ }
+
+ /*
+ * @see Dialog#createDialogArea(Composite)
+ */
+ protected Control createDialogArea(Composite parent) {
+ Composite contents = (Composite) super.createDialogArea(parent);
+
+ createMessageArea(contents);
+ createFilterText(contents);
+ createFilteredList(contents);
+
+ setListElements(fElements);
+
+ List initialSelections = getInitialElementSelections();
+ if (initialSelections != null)
+ setSelection(initialSelections.toArray());
+
+ return contents;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/ISelectionValidator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/ISelectionValidator.java
new file mode 100644
index 0000000..dacdc87
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/ISelectionValidator.java
@@ -0,0 +1,9 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import org.eclipse.core.runtime.IStatus;
+
+public interface ISelectionValidator {
+
+ IStatus validate(Object[] selection);
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/MessageLine.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/MessageLine.java
new file mode 100644
index 0000000..dc9ac8d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/MessageLine.java
@@ -0,0 +1,87 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A message line displaying a status.
+ */
+public class MessageLine extends CLabel {
+
+ private static final RGB ERROR_BACKGROUND_RGB = new RGB(230, 226, 221);
+
+ private Color fNormalMsgAreaBackground;
+
+ private Color fErrorMsgAreaBackground;
+
+ /**
+ * Creates a new message line as a child of the given parent.
+ */
+ public MessageLine(Composite parent) {
+ this(parent, SWT.LEFT);
+ }
+
+ /**
+ * Creates a new message line as a child of the parent and with the given
+ * SWT stylebits.
+ */
+ public MessageLine(Composite parent, int style) {
+ super(parent, style);
+ fNormalMsgAreaBackground = getBackground();
+ fErrorMsgAreaBackground = null;
+ }
+
+ private Image findImage(IStatus status) {
+ if (status.isOK()) {
+ return null;
+ } else if (status.matches(IStatus.ERROR)) {
+ return PHPUiImages.get(PHPUiImages.IMG_OBJS_ERROR);
+ } else if (status.matches(IStatus.WARNING)) {
+ return PHPUiImages.get(PHPUiImages.IMG_OBJS_WARNING);
+ } else if (status.matches(IStatus.INFO)) {
+ return PHPUiImages.get(PHPUiImages.IMG_OBJS_INFO);
+ }
+ return null;
+ }
+
+ /**
+ * Sets the message and image to the given status. null
is a
+ * valid argument and will set the empty text and no image
+ */
+ public void setErrorStatus(IStatus status) {
+ if (status != null) {
+ String message = status.getMessage();
+ if (message != null && message.length() > 0) {
+ setText(message);
+ setImage(findImage(status));
+ if (fErrorMsgAreaBackground == null) {
+ fErrorMsgAreaBackground = new Color(getDisplay(),
+ ERROR_BACKGROUND_RGB);
+ }
+ setBackground(fErrorMsgAreaBackground);
+ return;
+ }
+ }
+ setText("");
+ setImage(null);
+ setBackground(fNormalMsgAreaBackground);
+ }
+
+ /*
+ * @see Widget#dispose()
+ */
+ public void dispose() {
+ if (fErrorMsgAreaBackground != null) {
+ fErrorMsgAreaBackground.dispose();
+ fErrorMsgAreaBackground = null;
+ }
+ super.dispose();
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/SelectionStatusDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/SelectionStatusDialog.java
new file mode 100644
index 0000000..eb6514f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/SelectionStatusDialog.java
@@ -0,0 +1,154 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import java.util.Arrays;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+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.SelectionDialog;
+
+/**
+ * An abstract base class for dialogs with a status bar and ok/cancel buttons.
+ * The status message must be passed over as StatusInfo object and can be an
+ * error, warning or ok. The OK button is enabled or disabled depending on the
+ * status.
+ */
+public abstract class SelectionStatusDialog extends SelectionDialog {
+
+ private MessageLine fStatusLine;
+
+ private IStatus fLastStatus;
+
+ private Image fImage;
+
+ private boolean fStatusLineAboveButtons = false;
+
+ /**
+ * Creates an instance of a SelectionStatusDialog
.
+ */
+ public SelectionStatusDialog(Shell parent) {
+ super(parent);
+ }
+
+ /**
+ * Controls whether status line appears to the left of the buttons (default)
+ * or above them.
+ *
+ * @param aboveButtons
+ * if true
status line is placed above buttons; if
+ * false
to the right
+ */
+ public void setStatusLineAboveButtons(boolean aboveButtons) {
+ fStatusLineAboveButtons = aboveButtons;
+ }
+
+ /**
+ * Sets the image for this dialog.
+ *
+ * @param image
+ * the image.
+ */
+ public void setImage(Image image) {
+ fImage = image;
+ }
+
+ /**
+ * Returns the first element from the list of results. Returns
+ * null
if no element has been selected.
+ *
+ * @return the first result element if one exists. Otherwise
+ * null
is returned.
+ */
+ public Object getFirstResult() {
+ Object[] result = getResult();
+ if (result == null || result.length == 0)
+ return null;
+ return result[0];
+ }
+
+ /**
+ * Sets a result element at the given position.
+ */
+ protected void setResult(int position, Object element) {
+ Object[] result = getResult();
+ result[position] = element;
+ setResult(Arrays.asList(result));
+ }
+
+ /**
+ * Compute the result and return it.
+ */
+ protected abstract void computeResult();
+
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ if (fImage != null)
+ shell.setImage(fImage);
+ }
+
+ /**
+ * Update the dialog's status line to reflect the given status. It is safe
+ * to call this method before the dialog has been opened.
+ */
+ protected void updateStatus(IStatus status) {
+ fLastStatus = status;
+ if (fStatusLine != null && !fStatusLine.isDisposed()) {
+ updateButtonsEnableState(status);
+ fStatusLine.setErrorStatus(status);
+ }
+ }
+
+ /**
+ * Update the status of the ok button to reflect the given status.
+ * Subclasses may override this method to update additional buttons.
+ */
+ protected void updateButtonsEnableState(IStatus status) {
+ Button okButton = getOkButton();
+ if (okButton != null && !okButton.isDisposed())
+ okButton.setEnabled(!status.matches(IStatus.ERROR));
+ }
+
+ protected void okPressed() {
+ computeResult();
+ super.okPressed();
+ }
+
+ public void create() {
+ super.create();
+ if (fLastStatus != null)
+ updateStatus(fLastStatus);
+ }
+
+ protected Control createButtonBar(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ if (fStatusLineAboveButtons) {
+ layout.marginWidth = 5;
+ } else {
+ layout.numColumns = 2;
+ }
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ fStatusLine = new MessageLine(composite);
+ fStatusLine.setAlignment(SWT.LEFT);
+ fStatusLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ fStatusLine.setErrorStatus(null);
+
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalIndent = convertWidthInCharsToPixels(1);
+ fStatusLine.setLayoutData(gd);
+
+ super.createButtonBar(composite);
+ return composite;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusDialog.java
new file mode 100644
index 0000000..b58b7fb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusDialog.java
@@ -0,0 +1,168 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * An abstract base class for dialogs with a status bar and ok/cancel buttons.
+ * The status message must be passed over as StatusInfo object and can be an
+ * error, warning or ok. The OK button is enabled or disabled depending on the
+ * status.
+ */
+public abstract class StatusDialog extends Dialog {
+
+ private Button fOkButton;
+
+ private MessageLine fStatusLine;
+
+ private IStatus fLastStatus;
+
+ private String fTitle;
+
+ private Image fImage;
+
+ private boolean fStatusLineAboveButtons;
+
+ /**
+ * Creates an instane of a status dialog.
+ */
+ public StatusDialog(Shell parent) {
+ super(parent);
+ fStatusLineAboveButtons = false;
+ }
+
+ /**
+ * Specifies whether status line appears to the left of the buttons
+ * (default) or above them.
+ *
+ * @param aboveButtons
+ * if true
status line is placed above buttons; if
+ * false
to the right
+ */
+ public void setStatusLineAboveButtons(boolean aboveButtons) {
+ fStatusLineAboveButtons = aboveButtons;
+ }
+
+ /**
+ * Update the dialog's status line to reflect the given status. It is save
+ * to call this method before the dialog has been opened.
+ */
+ protected void updateStatus(IStatus status) {
+ fLastStatus = status;
+ if (fStatusLine != null && !fStatusLine.isDisposed()) {
+ updateButtonsEnableState(status);
+ fStatusLine.setErrorStatus(status);
+ }
+ }
+
+ /**
+ * Returns the last status.
+ */
+ public IStatus getStatus() {
+ return fLastStatus;
+ }
+
+ /**
+ * Updates the status of the ok button to reflect the given status.
+ * Subclasses may override this method to update additional buttons.
+ *
+ * @param status
+ * the status.
+ */
+ protected void updateButtonsEnableState(IStatus status) {
+ if (fOkButton != null && !fOkButton.isDisposed())
+ fOkButton.setEnabled(!status.matches(IStatus.ERROR));
+ }
+
+ /*
+ * @see Window#create(Shell)
+ */
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ if (fTitle != null)
+ shell.setText(fTitle);
+ }
+
+ /*
+ * @see Window#create()
+ */
+ public void create() {
+ super.create();
+ if (fLastStatus != null) {
+ // policy: dialogs are not allowed to come up with an error message
+ if (fLastStatus.matches(IStatus.ERROR)) {
+ StatusInfo status = new StatusInfo();
+ status.setError(""); //$NON-NLS-1$
+ fLastStatus = status;
+ }
+ updateStatus(fLastStatus);
+ }
+ }
+
+ /*
+ * @see Dialog#createButtonsForButtonBar(Composite)
+ */
+ protected void createButtonsForButtonBar(Composite parent) {
+ fOkButton = createButton(parent, IDialogConstants.OK_ID,
+ IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID,
+ IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ /*
+ * @see Dialog#createButtonBar(Composite)
+ */
+ protected Control createButtonBar(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ layout.marginHeight = 0;
+ layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ fStatusLine = new MessageLine(composite);
+ fStatusLine.setAlignment(SWT.LEFT);
+ fStatusLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ fStatusLine.setErrorStatus(null); //$NON-NLS-1$
+
+ super.createButtonBar(composite);
+ return composite;
+ }
+
+ /**
+ * Sets the title for this dialog.
+ *
+ * @param title
+ * the title.
+ */
+ public void setTitle(String title) {
+ fTitle = title != null ? title : ""; //$NON-NLS-1$
+ Shell shell = getShell();
+ if ((shell != null) && !shell.isDisposed())
+ shell.setText(fTitle);
+ }
+
+ /**
+ * Sets the image for this dialog.
+ *
+ * @param image
+ * the image.
+ */
+ public void setImage(Image image) {
+ fImage = image;
+ Shell shell = getShell();
+ if ((shell != null) && !shell.isDisposed())
+ shell.setImage(fImage);
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusInfo.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusInfo.java
new file mode 100644
index 0000000..0c5ee8f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusInfo.java
@@ -0,0 +1,176 @@
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.util.Assert;
+
+/**
+ * A settable IStatus. Can be an error, warning, info or ok. For error, info and
+ * warning states, a message describes the problem.
+ */
+public class StatusInfo implements IStatus {
+
+ private String fStatusMessage;
+
+ private int fSeverity;
+
+ /**
+ * Creates a status set to OK (no message)
+ */
+ public StatusInfo() {
+ this(OK, null);
+ }
+
+ /**
+ * Creates a status .
+ *
+ * @param severity
+ * The status severity: ERROR, WARNING, INFO and OK.
+ * @param message
+ * The message of the status. Applies only for ERROR, WARNING and
+ * INFO.
+ */
+ public StatusInfo(int severity, String message) {
+ fStatusMessage = message;
+ fSeverity = severity;
+ }
+
+ /**
+ * Returns if the status' severity is OK.
+ */
+ public boolean isOK() {
+ return fSeverity == IStatus.OK;
+ }
+
+ /**
+ * Returns if the status' severity is WARNING.
+ */
+ public boolean isWarning() {
+ return fSeverity == IStatus.WARNING;
+ }
+
+ /**
+ * Returns if the status' severity is INFO.
+ */
+ public boolean isInfo() {
+ return fSeverity == IStatus.INFO;
+ }
+
+ /**
+ * Returns if the status' severity is ERROR.
+ */
+ public boolean isError() {
+ return fSeverity == IStatus.ERROR;
+ }
+
+ /**
+ * @see IStatus#getMessage
+ */
+ public String getMessage() {
+ return fStatusMessage;
+ }
+
+ /**
+ * Sets the status to ERROR.
+ *
+ * @param The
+ * error message (can be empty, but not null)
+ */
+ public void setError(String errorMessage) {
+ Assert.isNotNull(errorMessage);
+ fStatusMessage = errorMessage;
+ fSeverity = IStatus.ERROR;
+ }
+
+ /**
+ * Sets the status to WARNING.
+ *
+ * @param The
+ * warning message (can be empty, but not null)
+ */
+ public void setWarning(String warningMessage) {
+ Assert.isNotNull(warningMessage);
+ fStatusMessage = warningMessage;
+ fSeverity = IStatus.WARNING;
+ }
+
+ /**
+ * Sets the status to INFO.
+ *
+ * @param The
+ * info message (can be empty, but not null)
+ */
+ public void setInfo(String infoMessage) {
+ Assert.isNotNull(infoMessage);
+ fStatusMessage = infoMessage;
+ fSeverity = IStatus.INFO;
+ }
+
+ /**
+ * Sets the status to OK.
+ */
+ public void setOK() {
+ fStatusMessage = null;
+ fSeverity = IStatus.OK;
+ }
+
+ /*
+ * @see IStatus#matches(int)
+ */
+ public boolean matches(int severityMask) {
+ return (fSeverity & severityMask) != 0;
+ }
+
+ /**
+ * Returns always false
.
+ *
+ * @see IStatus#isMultiStatus()
+ */
+ public boolean isMultiStatus() {
+ return false;
+ }
+
+ /*
+ * @see IStatus#getSeverity()
+ */
+ public int getSeverity() {
+ return fSeverity;
+ }
+
+ /*
+ * @see IStatus#getPlugin()
+ */
+ public String getPlugin() {
+ return WebUI.PLUGIN_ID;
+ }
+
+ /**
+ * Returns always null
.
+ *
+ * @see IStatus#getException()
+ */
+ public Throwable getException() {
+ return null;
+ }
+
+ /**
+ * Returns always the error severity.
+ *
+ * @see IStatus#getCode()
+ */
+ public int getCode() {
+ return fSeverity;
+ }
+
+ /**
+ * Returns always null
.
+ *
+ * @see IStatus#getChildren()
+ */
+ public IStatus[] getChildren() {
+ return new IStatus[0];
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusUtil.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusUtil.java
new file mode 100644
index 0000000..f87adf0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dialogs/StatusUtil.java
@@ -0,0 +1,74 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.dialogs;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.DialogPage;
+
+/**
+ * A utility class to work with IStatus.
+ */
+public class StatusUtil {
+
+ /**
+ * Compares two instances of IStatus
. The more severe is
+ * returned: An error is more severe than a warning, and a warning is more
+ * severe than ok. If the two stati have the same severity, the second is
+ * returned.
+ */
+ public static IStatus getMoreSevere(IStatus s1, IStatus s2) {
+ if (s1.getSeverity() > s2.getSeverity()) {
+ return s1;
+ } else {
+ return s2;
+ }
+ }
+
+ /**
+ * Finds the most severe status from a array of stati. An error is more
+ * severe than a warning, and a warning is more severe than ok.
+ */
+ public static IStatus getMostSevere(IStatus[] status) {
+ IStatus max = null;
+ for (int i = 0; i < status.length; i++) {
+ IStatus curr = status[i];
+ if (curr.matches(IStatus.ERROR)) {
+ return curr;
+ }
+ if (max == null || curr.getSeverity() > max.getSeverity()) {
+ max = curr;
+ }
+ }
+ return max;
+ }
+
+ /**
+ * Applies the status to the status line of a dialog page.
+ */
+ public static void applyToStatusLine(DialogPage page, IStatus status) {
+ String message = status.getMessage();
+ switch (status.getSeverity()) {
+ case IStatus.OK:
+ page.setMessage(message, DialogPage.NONE);
+ page.setErrorMessage(null);
+ break;
+ case IStatus.WARNING:
+ page.setMessage(message, DialogPage.WARNING);
+ page.setErrorMessage(null);
+ break;
+ case IStatus.INFO:
+ page.setMessage(message, DialogPage.INFORMATION);
+ page.setErrorMessage(null);
+ break;
+ default:
+ if (message.length() == 0) {
+ message = null;
+ }
+ page.setMessage(null);
+ page.setErrorMessage(message);
+ break;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/BasicSelectionTransferDragAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/BasicSelectionTransferDragAdapter.java
new file mode 100644
index 0000000..866f69a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/BasicSelectionTransferDragAdapter.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.Transfer;
+
+public class BasicSelectionTransferDragAdapter extends DragSourceAdapter
+ implements TransferDragSourceListener {
+
+ private ISelectionProvider fProvider;
+
+ public BasicSelectionTransferDragAdapter(ISelectionProvider provider) {
+ Assert.isNotNull(provider);
+ fProvider = provider;
+ }
+
+ /**
+ * @see TransferDragSourceListener#getTransfer
+ */
+ public Transfer getTransfer() {
+ return LocalSelectionTransfer.getInstance();
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see org.eclipse.swt.dnd.DragSourceListener#dragStart
+ */
+ public void dragStart(DragSourceEvent event) {
+ ISelection selection = fProvider.getSelection();
+ LocalSelectionTransfer.getInstance().setSelection(selection);
+ LocalSelectionTransfer.getInstance().setSelectionSetTime(event.time);
+ event.doit = isDragable(selection);
+ }
+
+ /**
+ * Checks if the elements contained in the given selection can be dragged.
+ * TransferDragSourceListener
s On dragStart
the
+ * adapter determines the listener to be used for any further drag*
+ * callback.
+ */
+public class DelegatingDragAdapter implements DragSourceListener {
+
+ private TransferDragSourceListener[] fPossibleListeners;
+
+ private List fActiveListeners;
+
+ private TransferDragSourceListener fFinishListener;
+
+ public DelegatingDragAdapter(TransferDragSourceListener[] listeners) {
+ setPossibleListeners(listeners);
+ }
+
+ protected void setPossibleListeners(TransferDragSourceListener[] listeners) {
+ Assert.isNotNull(listeners);
+ Assert
+ .isTrue(fActiveListeners == null,
+ "Can only set possible listeners before drag operation has started"); //$NON-NLS-1$
+ fPossibleListeners = listeners;
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DragSourceListener
+ */
+ public void dragStart(DragSourceEvent event) {
+ fFinishListener = null;
+ boolean saveDoit = event.doit;
+ Object saveData = event.data;
+ boolean doIt = false;
+ List transfers = new ArrayList(fPossibleListeners.length);
+ fActiveListeners = new ArrayList(fPossibleListeners.length);
+
+ for (int i = 0; i < fPossibleListeners.length; i++) {
+ TransferDragSourceListener listener = fPossibleListeners[i];
+ event.doit = saveDoit;
+ listener.dragStart(event);
+ if (event.doit) {
+ transfers.add(listener.getTransfer());
+ fActiveListeners.add(listener);
+ }
+ doIt = doIt || event.doit;
+ }
+ if (doIt) {
+ ((DragSource) event.widget).setTransfer((Transfer[]) transfers
+ .toArray(new Transfer[transfers.size()]));
+ }
+ event.data = saveData;
+ event.doit = doIt;
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DragSourceListener
+ */
+ public void dragSetData(DragSourceEvent event) {
+ fFinishListener = getListener(event.dataType);
+ if (fFinishListener != null)
+ fFinishListener.dragSetData(event);
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DragSourceListener
+ */
+ public void dragFinished(DragSourceEvent event) {
+ try {
+ if (fFinishListener != null) {
+ fFinishListener.dragFinished(event);
+ } else {
+ // If the user presses Escape then we get a dragFinished without
+ // getting a dragSetData before.
+ fFinishListener = getListener(event.dataType);
+ if (fFinishListener != null)
+ fFinishListener.dragFinished(event);
+ }
+ } finally {
+ fFinishListener = null;
+ fActiveListeners = null;
+ }
+ }
+
+ private TransferDragSourceListener getListener(TransferData type) {
+ if (type == null)
+ return null;
+
+ for (Iterator iter = fActiveListeners.iterator(); iter.hasNext();) {
+ TransferDragSourceListener listener = (TransferDragSourceListener) iter
+ .next();
+ if (listener.getTransfer().isSupportedType(type)) {
+ return listener;
+ }
+ }
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/DelegatingDropAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/DelegatingDropAdapter.java
new file mode 100644
index 0000000..4424f34
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/DelegatingDropAdapter.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.TransferData;
+
+/**
+ * A delegating drop adapter negotiates between a set of
+ * TransferDropTargetListener
s On dragEnter
the
+ * adapter determines the listener to be used for any further drag*
+ * callback.
+ */
+public class DelegatingDropAdapter implements DropTargetListener {
+
+ private TransferDropTargetListener[] fListeners;
+
+ private TransferDropTargetListener fChosenListener;
+
+ /**
+ * Creates a new delegating drop adapter.
+ *
+ * @param listeners
+ * an array of potential listeners
+ */
+ public DelegatingDropAdapter(TransferDropTargetListener[] listeners) {
+ fListeners = listeners;
+ Assert.isNotNull(listeners);
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DropTargetListener
+ */
+ public void dragEnter(DropTargetEvent event) {
+ fChosenListener = null;
+ event.currentDataType = selectPreferredListener(event.dataTypes);
+ if (fChosenListener != null)
+ fChosenListener.dragEnter(event);
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DropTargetListener
+ */
+ public void dragLeave(DropTargetEvent event) {
+ if (fChosenListener != null)
+ fChosenListener.dragLeave(event);
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DropTargetListener
+ */
+ public void dragOperationChanged(DropTargetEvent event) {
+ if (fChosenListener != null)
+ fChosenListener.dragOperationChanged(event);
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DropTargetListener
+ */
+ public void dragOver(DropTargetEvent event) {
+ if (fChosenListener != null)
+ fChosenListener.dragOver(event);
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DropTargetListener
+ */
+ public void drop(DropTargetEvent event) {
+ if (fChosenListener != null)
+ fChosenListener.drop(event);
+ fChosenListener = null;
+ }
+
+ /*
+ * non Java-doc
+ *
+ * @see DropTargetListener
+ */
+ public void dropAccept(DropTargetEvent event) {
+ if (fChosenListener != null)
+ fChosenListener.dropAccept(event);
+ }
+
+ private TransferData selectPreferredListener(TransferData[] dataTypes) {
+ for (int i = 0; i < fListeners.length; i++) {
+ TransferData data = computeTransferData(dataTypes, fListeners[i]);
+ if (data != null)
+ return data;
+ }
+ return null;
+ }
+
+ private TransferData computeTransferData(TransferData[] dataTypes,
+ TransferDropTargetListener listener) {
+ for (int i = 0; i < dataTypes.length; i++) {
+ if (listener.getTransfer().isSupportedType(dataTypes[i])) {
+ fChosenListener = listener;
+ return dataTypes[i];
+ }
+ }
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/JdtViewerDragAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/JdtViewerDragAdapter.java
new file mode 100644
index 0000000..63351c2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/JdtViewerDragAdapter.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+public class JdtViewerDragAdapter extends DelegatingDragAdapter {
+
+ private StructuredViewer fViewer;
+
+ public JdtViewerDragAdapter(StructuredViewer viewer,
+ TransferDragSourceListener[] listeners) {
+ super(listeners);
+ Assert.isNotNull(viewer);
+ fViewer = viewer;
+ }
+
+ public void dragStart(DragSourceEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) fViewer
+ .getSelection();
+ if (selection.isEmpty()) {
+ event.doit = false;
+ return;
+ }
+ super.dragStart(event);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/JdtViewerDropAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/JdtViewerDropAdapter.java
new file mode 100644
index 0000000..7e2143b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/JdtViewerDropAdapter.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.TreeItem;
+
+/**
+ * A drag and drop adapter to be used together with structured viewers. The
+ * adapater delegates the dragEnter
, dragOperationChanged
+ *
,
+ * dragOver
and dropAccept
method to the
+ * validateDrop
method. Furthermore it adds location feedback.
+ */
+public class JdtViewerDropAdapter implements DropTargetListener {
+
+ /**
+ * Constant describing the position of the mouse cursor relative to the
+ * target object. This means the mouse is positioned slightly before the
+ * target.
+ */
+ protected static final int LOCATION_BEFORE = 1;
+
+ /**
+ * Constant describing the position of the mouse cursor relative to the
+ * target object. This means the mouse is positioned slightly after the
+ * target.
+ */
+ protected static final int LOCATION_AFTER = 2;
+
+ /**
+ * Constant describing the position of the mouse cursor relative to the
+ * target object. This means the mouse is positioned directly on the target.
+ */
+ protected static final int LOCATION_ON = 3;
+
+ /**
+ * Constant describing the position of the mouse cursor relative to the
+ * target object. This means the mouse is not positioned over or near any
+ * valid target.
+ */
+ protected static final int LOCATION_NONE = 4;
+
+ /**
+ * The threshold used to determine if the mouse is before or after an item.
+ */
+ private static final int LOCATION_EPSILON = 5;
+
+ /**
+ * Style to enable location feedback.
+ */
+ public static final int INSERTION_FEEDBACK = 1 << 1;
+
+ private StructuredViewer fViewer;
+
+ private int fFeedback;
+
+ private boolean fShowInsertionFeedback;
+
+ private int fRequestedOperation;
+
+ private int fLastOperation;
+
+ protected int fLocation;
+
+ protected Object fTarget;
+
+ public JdtViewerDropAdapter(StructuredViewer viewer, int feedback) {
+ fViewer = viewer;
+ Assert.isNotNull(fViewer);
+ fFeedback = feedback;
+ fLastOperation = -1;
+ }
+
+ /**
+ * Controls whether the drop adapter shows insertion feedback or not.
+ *
+ * @param showInsertionFeedback
+ * true
if the drop adapter is supposed to show
+ * insertion feedback. Otherwise false
+ */
+ public void showInsertionFeedback(boolean showInsertionFeedback) {
+ fShowInsertionFeedback = showInsertionFeedback;
+ }
+
+ /**
+ * Returns the viewer this adapter is working on.
+ */
+ protected StructuredViewer getViewer() {
+ return fViewer;
+ }
+
+ // ---- Hooks to override
+ // -----------------------------------------------------
+
+ /**
+ * The actual drop has occurred. Calls
+ * drop(Object target, DropTargetEvent event)
+ *
.
+ *
+ * @see DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent)
+ */
+ public void drop(DropTargetEvent event) {
+ drop(fTarget, event);
+ }
+
+ /**
+ * The actual drop has occurred.
+ *
+ * @param target
+ * the drop target in form of a domain element.
+ * @param event
+ * the drop traget event
+ */
+ public void drop(Object target, DropTargetEvent event) {
+ }
+
+ /**
+ * Checks if the drop is valid. The method calls validateDrop
+ * (Object target, DropTargetEvent event). Implementors can alter the
+ *
DROP_NODEcurrentDataType
field and the detail
field
+ * to give feedback about drop acceptence.
+ */
+ public void validateDrop(DropTargetEvent event) {
+ validateDrop(fTarget, event, fRequestedOperation);
+ }
+
+ /**
+ * Checks if the drop on the current target is valid. The method can alter
+ * the currentDataType
field and the
+ * detail
+ * field to give feedback about drop acceptence.
+ *
+ * @param target
+ * the drop target in form of a domain element.
+ * @param event
+ * the drop traget event
+ * @param operation
+ * the operation requested by the user.
+ */
+ public void validateDrop(Object target, DropTargetEvent event, int operation) {
+ }
+
+ public void dragEnter(DropTargetEvent event) {
+ dragOperationChanged(event);
+ }
+
+ public void dragLeave(DropTargetEvent event) {
+ fTarget = null;
+ fLocation = LOCATION_NONE;
+ }
+
+ public void dragOperationChanged(DropTargetEvent event) {
+ fRequestedOperation = event.detail;
+ fTarget = computeTarget(event);
+ fLocation = computeLocation(event);
+ validateDrop(event);
+ fLastOperation = event.detail;
+ computeFeedback(event);
+ }
+
+ public void dragOver(DropTargetEvent event) {
+ Object oldTarget = fTarget;
+ fTarget = computeTarget(event);
+
+ // set the location feedback
+ int oldLocation = fLocation;
+ fLocation = computeLocation(event);
+ if (oldLocation != fLocation || oldTarget != fTarget
+ || fLastOperation != event.detail) {
+ validateDrop(event);
+ fLastOperation = event.detail;
+ } else {
+ event.detail = fLastOperation;
+ }
+ computeFeedback(event);
+ }
+
+ public void dropAccept(DropTargetEvent event) {
+ fTarget = computeTarget(event);
+ validateDrop(event);
+ fLastOperation = event.detail;
+ }
+
+ /**
+ * Returns the data held by event.item
. Inside a viewer this
+ * corresponds to the items data model element.
+ */
+ protected Object computeTarget(DropTargetEvent event) {
+ return event.item == null ? null : event.item.getData();
+ }
+
+ /**
+ * Returns the position of the given coordinates relative to the given
+ * target. The position is determined to be before, after, or on the item,
+ * based on some threshold value. The return value is one of the LOCATION_*
+ * constants defined in this class.
+ */
+ final protected int computeLocation(DropTargetEvent event) {
+ if (!(event.item instanceof Item))
+ return LOCATION_NONE;
+
+ Item item = (Item) event.item;
+ Point coordinates = fViewer.getControl().toControl(
+ new Point(event.x, event.y));
+ Rectangle bounds = getBounds(item);
+ if (bounds == null) {
+ return LOCATION_NONE;
+ }
+ if ((coordinates.y - bounds.y) < LOCATION_EPSILON) {
+ return LOCATION_BEFORE;
+ }
+ if ((bounds.y + bounds.height - coordinates.y) < LOCATION_EPSILON) {
+ return LOCATION_AFTER;
+ }
+ return LOCATION_ON;
+ }
+
+ /**
+ * Returns the bounds of the given item, or null
if it is not
+ * a valid type of item.
+ */
+ private Rectangle getBounds(Item item) {
+ if (item instanceof TreeItem)
+ return ((TreeItem) item).getBounds();
+
+ if (item instanceof TableItem)
+ return ((TableItem) item).getBounds(0);
+
+ return null;
+ }
+
+ /**
+ * Sets the drag under feedback corresponding to the value of
+ * fLocation
and the INSERTION_FEEDBACK
style
+ * bit.
+ */
+ protected void computeFeedback(DropTargetEvent event) {
+ if (!fShowInsertionFeedback && fLocation != LOCATION_NONE) {
+ event.feedback = DND.FEEDBACK_SELECT;
+ } else {
+ if (fLocation == LOCATION_BEFORE) {
+ event.feedback = DND.FEEDBACK_INSERT_BEFORE;
+ } else if (fLocation == LOCATION_AFTER) {
+ event.feedback = DND.FEEDBACK_INSERT_AFTER;
+ }
+ }
+ event.feedback |= fFeedback;
+ }
+
+ /**
+ * Sets the drop operation to .
+ */
+ protected void clearDropOperation(DropTargetEvent event) {
+ event.detail = DND.DROP_NONE;
+ }
+
+ /**
+ * Returns the requested drop operation.
+ */
+ protected int getRequestedOperation() {
+ return fRequestedOperation;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/LocalSelectionTransfer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/LocalSelectionTransfer.java
new file mode 100644
index 0000000..49ea330
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/LocalSelectionTransfer.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+
+public class LocalSelectionTransfer extends ByteArrayTransfer {
+
+ // First attempt to create a UUID for the type name to make sure that
+ // different Eclipse applications use different "types" of
+ //
IResourceLocalSelectionTransfer
+ private static final String TYPE_NAME = "local-selection-transfer-format" + (new Long(System.currentTimeMillis())).toString(); //$NON-NLS-1$;
+
+ private static final int TYPEID = registerType(TYPE_NAME);
+
+ private static final LocalSelectionTransfer INSTANCE = new LocalSelectionTransfer();
+
+ private ISelection fSelection;
+
+ private int fSelectionSetTime;
+
+ private LocalSelectionTransfer() {
+ }
+
+ /**
+ * Returns the singleton.
+ */
+ public static LocalSelectionTransfer getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Sets the transfer data for local use.
+ */
+ public void setSelection(ISelection s) {
+ fSelection = s;
+ }
+
+ /**
+ * Returns the local transfer data.
+ */
+ public ISelection getSelection() {
+ return fSelection;
+ }
+
+ public void javaToNative(Object object, TransferData transferData) {
+ // No encoding needed since this is a hardcoded string read and written
+ // in the same process.
+ // See nativeToJava below
+ byte[] check = TYPE_NAME.getBytes();
+ super.javaToNative(check, transferData);
+ }
+
+ public Object nativeToJava(TransferData transferData) {
+ Object result = super.nativeToJava(transferData);
+ if (isInvalidNativeType(result)) {
+ WebUI.log(IStatus.ERROR, PHPUIMessages
+ .getString("LocalSelectionTransfer.errorMessage")); //$NON-NLS-1$
+ }
+ return fSelection;
+ }
+
+ private boolean isInvalidNativeType(Object result) {
+ // No encoding needed since this is a hardcoded string read and written
+ // in the same process.
+ // See javaToNative above
+ return !(result instanceof byte[])
+ || !TYPE_NAME.equals(new String((byte[]) result));
+ }
+
+ /**
+ * The type id used to identify this transfer.
+ */
+ protected int[] getTypeIds() {
+ return new int[] { TYPEID };
+ }
+
+ protected String[] getTypeNames() {
+ return new String[] { TYPE_NAME };
+ }
+
+ public int getSelectionSetTime() {
+ return fSelectionSetTime;
+ }
+
+ public void setSelectionSetTime(int time) {
+ fSelectionSetTime = time;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/ResourceTransferDragAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/ResourceTransferDragAdapter.java
new file mode 100644
index 0000000..8157ce9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/ResourceTransferDragAdapter.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.IJavaStatusConstants;
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.part.ResourceTransfer;
+
+/**
+ * A drag adapter that transfers the current selection as IResource
.
+ */
+public class ResourceTransferDragAdapter extends DragSourceAdapter implements
+ TransferDragSourceListener {
+
+ private ISelectionProvider fProvider;
+
+ private static final List EMPTY_LIST = new ArrayList(0);
+
+ /**
+ * Creates a new ResourceTransferDragAdapter for the given selection
+ * provider.
+ *
+ * @param provider
+ * the selection provider to access the viewer's selection
+ */
+ public ResourceTransferDragAdapter(ISelectionProvider provider) {
+ fProvider = provider;
+ Assert.isNotNull(fProvider);
+ }
+
+ public Transfer getTransfer() {
+ return ResourceTransfer.getInstance();
+ }
+
+ public void dragStart(DragSourceEvent event) {
+ event.doit = convertSelection().size() > 0;
+ }
+
+ public void dragSetData(DragSourceEvent event) {
+ List resources = convertSelection();
+ event.data = (IResource[]) resources.toArray(new IResource[resources
+ .size()]);
+ }
+
+ public void dragFinished(DragSourceEvent event) {
+ if (!event.doit)
+ return;
+
+ if (event.detail == DND.DROP_MOVE) {
+ handleFinishedDropMove(event);
+ }
+ }
+
+ private List convertSelection() {
+ ISelection s = fProvider.getSelection();
+ if (!(s instanceof IStructuredSelection))
+ return EMPTY_LIST;
+ IStructuredSelection selection = (IStructuredSelection) s;
+ List result = new ArrayList(selection.size());
+ for (Iterator iter = selection.iterator(); iter.hasNext();) {
+ Object element = iter.next();
+ if (element instanceof IAdaptable) {
+ IAdaptable adaptable = (IAdaptable) element;
+ IResource resource = (IResource) adaptable
+ .getAdapter(IResource.class);
+ if (resource != null)
+ result.add(resource);
+ }
+ }
+ return result;
+ }
+
+ private void handleFinishedDropMove(DragSourceEvent event) {
+ MultiStatus status = new MultiStatus(
+ WebUI.getPluginId(),
+ IJavaStatusConstants.INTERNAL_ERROR,
+ PHPUIMessages
+ .getString("ResourceTransferDragAdapter.cannot_delete_resource"), //$NON-NLS-1$
+ null);
+ List resources = convertSelection();
+ for (Iterator iter = resources.iterator(); iter.hasNext();) {
+ IResource resource = (IResource) iter.next();
+ try {
+ resource.delete(true, null);
+ } catch (CoreException e) {
+ status.add(e.getStatus());
+ }
+ }
+ if (status.getChildren().length > 0) {
+ Shell parent = SWTUtil.getShell(event.widget);
+ ErrorDialog error = new ErrorDialog(
+ parent,
+ PHPUIMessages
+ .getString("ResourceTransferDragAdapter.moving_resource"), //$NON-NLS-1$
+ PHPUIMessages
+ .getString("ResourceTransferDragAdapter.cannot_delete_files"), //$NON-NLS-1$
+ status, IStatus.ERROR);
+ error.open();
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/TransferDragSourceListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/TransferDragSourceListener.java
new file mode 100644
index 0000000..dbe83c8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/TransferDragSourceListener.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.Transfer;
+
+/**
+ * A special drag source listener which is typed with a
+ * TransferData
.
+ */
+public interface TransferDragSourceListener extends DragSourceListener {
+
+ /**
+ * Returns the transfer used by this drag source.
+ */
+ public Transfer getTransfer();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/TransferDropTargetListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/TransferDropTargetListener.java
new file mode 100644
index 0000000..abea4ab
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/dnd/TransferDropTargetListener.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.dnd;
+
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.Transfer;
+
+/**
+ * A special drop target listener which is typed with a
+ * TransferData
.
+ */
+public interface TransferDropTargetListener extends DropTargetListener {
+
+ /**
+ * Returns the transfer used by this drop target.
+ */
+ public Transfer getTransfer();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ClassFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ClassFilter.java
new file mode 100644
index 0000000..850db3b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ClassFilter.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Filters classes
+ */
+public class ClassFilter extends ViewerFilter {
+
+ /*
+ * @see ViewerFilter
+ */
+ public boolean select(Viewer viewer, Object parent, Object element) {
+ if (element instanceof IType) {
+ try {
+ return ((IType) element).isInterface();
+ } catch (JavaModelException ex) {
+ return true;
+ }
+ }
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ClosedProjectFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ClosedProjectFilter.java
new file mode 100644
index 0000000..2ac29b1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ClosedProjectFilter.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Filters closed projects
+ */
+public class ClosedProjectFilter extends ViewerFilter {
+
+ /*
+ * @see ViewerFilter
+ */
+ public boolean select(Viewer viewer, Object parent, Object element) {
+ if (element instanceof IJavaElement)
+ return ((IJavaElement) element).getJavaProject().getProject()
+ .isOpen();
+ if (element instanceof IResource)
+ return ((IResource) element).getProject().isOpen();
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/CustomFiltersDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/CustomFiltersDialog.java
new file mode 100644
index 0000000..8060d76
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/CustomFiltersDialog.java
@@ -0,0 +1,442 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+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 java.util.Stack;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+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.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.SelectionDialog;
+
+public class CustomFiltersDialog extends SelectionDialog {
+
+ private static final String SEPARATOR = ","; //$NON-NLS-1$
+
+ private String fViewId;
+
+ private boolean fEnablePatterns;
+
+ private String[] fPatterns;
+
+ private String[] fEnabledFilterIds;
+
+ private FilterDescriptor[] fBuiltInFilters;
+
+ private CheckboxTableViewer fCheckBoxList;
+
+ private Button fEnableUserDefinedPatterns;
+
+ private Text fUserDefinedPatterns;
+
+ private Stack fFilterDescriptorChangeHistory;
+
+ /**
+ * Creates a dialog to customize Java element filters.
+ *
+ * @param shell
+ * the parent shell
+ * @param viewId
+ * the id of the view
+ * @param enablePatterns
+ * true
if pattern filters are enabled
+ * @param patterns
+ * the filter patterns
+ * @param enabledFilterIds
+ * the Ids of the enabled filters
+ */
+ public CustomFiltersDialog(Shell shell, String viewId,
+ boolean enablePatterns, String[] patterns, String[] enabledFilterIds) {
+
+ super(shell);
+ Assert.isNotNull(viewId);
+ Assert.isNotNull(patterns);
+ Assert.isNotNull(enabledFilterIds);
+
+ fViewId = viewId;
+ fPatterns = patterns;
+ fEnablePatterns = enablePatterns;
+ fEnabledFilterIds = enabledFilterIds;
+
+ fBuiltInFilters = FilterDescriptor.getFilterDescriptors(fViewId);
+ fFilterDescriptorChangeHistory = new Stack();
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ }
+
+ protected void configureShell(Shell shell) {
+ setTitle(FilterMessages.getString("CustomFiltersDialog.title")); //$NON-NLS-1$
+ setMessage(FilterMessages
+ .getString("CustomFiltersDialog.filterList.label")); //$NON-NLS-1$
+ super.configureShell(shell);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
+ IJavaHelpContextIds.CUSTOM_FILTERS_DIALOG);
+ }
+
+ /**
+ * Overrides method in Dialog
+ *
+ * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite)
+ */
+ protected Control createDialogArea(Composite parent) {
+ initializeDialogUnits(parent);
+ // create a composite with standard margins and spacing
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+ layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ composite.setFont(parent.getFont());
+ Composite group = composite;
+
+ // Checkbox
+ fEnableUserDefinedPatterns = new Button(group, SWT.CHECK);
+ fEnableUserDefinedPatterns.setFocus();
+ fEnableUserDefinedPatterns.setText(FilterMessages
+ .getString("CustomFiltersDialog.enableUserDefinedPattern")); //$NON-NLS-1$
+
+ // Pattern field
+ fUserDefinedPatterns = new Text(group, SWT.SINGLE | SWT.BORDER);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.GRAB_HORIZONTAL);
+ data.widthHint = convertWidthInCharsToPixels(59);
+ fUserDefinedPatterns.setLayoutData(data);
+ String patterns = convertToString(fPatterns, SEPARATOR);
+ fUserDefinedPatterns.setText(patterns);
+
+ // Info text
+ final Label info = new Label(group, SWT.LEFT);
+ info.setText(FilterMessages
+ .getString("CustomFiltersDialog.patternInfo")); //$NON-NLS-1$
+
+ // Enabling / disabling of pattern group
+ fEnableUserDefinedPatterns.setSelection(fEnablePatterns);
+ fUserDefinedPatterns.setEnabled(fEnablePatterns);
+ info.setEnabled(fEnablePatterns);
+ fEnableUserDefinedPatterns.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean state = fEnableUserDefinedPatterns.getSelection();
+ fUserDefinedPatterns.setEnabled(state);
+ info.setEnabled(fEnableUserDefinedPatterns.getSelection());
+ if (state)
+ fUserDefinedPatterns.setFocus();
+ }
+ });
+
+ // Filters provided by extension point
+ if (fBuiltInFilters.length > 0)
+ createCheckBoxList(group);
+
+ applyDialogFont(parent);
+ return parent;
+ }
+
+ private void createCheckBoxList(Composite parent) {
+ // Filler
+ new Label(parent, SWT.NONE);
+
+ Label info = new Label(parent, SWT.LEFT);
+ info.setText(FilterMessages
+ .getString("CustomFiltersDialog.filterList.label")); //$NON-NLS-1$
+
+ fCheckBoxList = CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.heightHint = fCheckBoxList.getTable().getItemHeight() * 10;
+ fCheckBoxList.getTable().setLayoutData(data);
+
+ fCheckBoxList.setLabelProvider(createLabelPrivder());
+ fCheckBoxList.setContentProvider(new ArrayContentProvider());
+
+ fCheckBoxList.setInput(fBuiltInFilters);
+ setInitialSelections(getEnabledFilterDescriptors());
+
+ List initialSelection = getInitialElementSelections();
+ if (initialSelection != null && !initialSelection.isEmpty())
+ checkInitialSelections();
+
+ // Description
+ info = new Label(parent, SWT.LEFT);
+ info.setText(FilterMessages
+ .getString("CustomFiltersDialog.description.label")); //$NON-NLS-1$
+ final Text description = new Text(parent, SWT.LEFT | SWT.WRAP
+ | SWT.MULTI | SWT.READ_ONLY | SWT.BORDER | SWT.V_SCROLL);
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.heightHint = convertHeightInCharsToPixels(3);
+ description.setLayoutData(data);
+ fCheckBoxList
+ .addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ Object selectedElement = ((IStructuredSelection) selection)
+ .getFirstElement();
+ if (selectedElement instanceof FilterDescriptor)
+ description
+ .setText(((FilterDescriptor) selectedElement)
+ .getDescription());
+ }
+ }
+ });
+ fCheckBoxList.addCheckStateListener(new ICheckStateListener() {
+ /*
+ * @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
+ */
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ Object element = event.getElement();
+ if (element instanceof FilterDescriptor) {
+ // renew if already touched
+ if (fFilterDescriptorChangeHistory.contains(element))
+ fFilterDescriptorChangeHistory.remove(element);
+ fFilterDescriptorChangeHistory.push(element);
+ }
+ }
+ });
+
+ addSelectionButtons(parent);
+ }
+
+ private void addSelectionButtons(Composite composite) {
+ Composite buttonComposite = new Composite(composite, SWT.RIGHT);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ buttonComposite.setLayout(layout);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
+ | GridData.GRAB_HORIZONTAL);
+ data.grabExcessHorizontalSpace = true;
+ composite.setData(data);
+
+ // Select All button
+ String label = FilterMessages
+ .getString("CustomFiltersDialog.SelectAllButton.label"); //$NON-NLS-1$
+ Button selectButton = createButton(buttonComposite,
+ IDialogConstants.SELECT_ALL_ID, label, false);
+ SWTUtil.setButtonDimensionHint(selectButton);
+ SelectionListener listener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ fCheckBoxList.setAllChecked(true);
+ fFilterDescriptorChangeHistory.clear();
+ for (int i = 0; i < fBuiltInFilters.length; i++)
+ fFilterDescriptorChangeHistory.push(fBuiltInFilters[i]);
+ }
+ };
+ selectButton.addSelectionListener(listener);
+
+ // De-select All button
+ label = FilterMessages
+ .getString("CustomFiltersDialog.DeselectAllButton.label"); //$NON-NLS-1$
+ Button deselectButton = createButton(buttonComposite,
+ IDialogConstants.DESELECT_ALL_ID, label, false);
+ SWTUtil.setButtonDimensionHint(deselectButton);
+ listener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ fCheckBoxList.setAllChecked(false);
+ fFilterDescriptorChangeHistory.clear();
+ for (int i = 0; i < fBuiltInFilters.length; i++)
+ fFilterDescriptorChangeHistory.push(fBuiltInFilters[i]);
+ }
+ };
+ deselectButton.addSelectionListener(listener);
+ }
+
+ private void checkInitialSelections() {
+ Iterator itemsToCheck = getInitialElementSelections().iterator();
+ while (itemsToCheck.hasNext())
+ fCheckBoxList.setChecked(itemsToCheck.next(), true);
+ }
+
+ protected void okPressed() {
+ if (fBuiltInFilters != null) {
+ ArrayList result = new ArrayList();
+ for (int i = 0; i < fBuiltInFilters.length; ++i) {
+ if (fCheckBoxList.getChecked(fBuiltInFilters[i]))
+ result.add(fBuiltInFilters[i]);
+ }
+ setResult(result);
+ }
+ super.okPressed();
+ }
+
+ private ILabelProvider createLabelPrivder() {
+ return new LabelProvider() {
+ public Image getImage(Object element) {
+ return null;
+ }
+
+ public String getText(Object element) {
+ if (element instanceof FilterDescriptor)
+ return ((FilterDescriptor) element).getName();
+ else
+ return null;
+ }
+ };
+ }
+
+ // ---------- result handling ----------
+
+ protected void setResult(List newResult) {
+ super.setResult(newResult);
+ if (fUserDefinedPatterns.getText().length() > 0) {
+ fEnablePatterns = fEnableUserDefinedPatterns.getSelection();
+ fPatterns = convertFromString(fUserDefinedPatterns.getText(),
+ SEPARATOR);
+ } else {
+ fEnablePatterns = false;
+ fPatterns = new String[0];
+ }
+ }
+
+ /**
+ * @return the patterns which have been entered by the user
+ */
+ public String[] getUserDefinedPatterns() {
+ return fPatterns;
+ }
+
+ /**
+ * @return the Ids of the enabled built-in filters
+ */
+ public String[] getEnabledFilterIds() {
+ Object[] result = getResult();
+ Set enabledIds = new HashSet(result.length);
+ for (int i = 0; i < result.length; i++)
+ enabledIds.add(((FilterDescriptor) result[i]).getId());
+ return (String[]) enabledIds.toArray(new String[enabledIds.size()]);
+ }
+
+ /**
+ * @return true
if the user-defined patterns are disabled
+ */
+ public boolean areUserDefinedPatternsEnabled() {
+ return fEnablePatterns;
+ }
+
+ /**
+ * @return a stack with the filter descriptor check history
+ * @since 3.0
+ */
+ public Stack getFilterDescriptorChangeHistory() {
+ return fFilterDescriptorChangeHistory;
+ }
+
+ private FilterDescriptor[] getEnabledFilterDescriptors() {
+ FilterDescriptor[] filterDescs = fBuiltInFilters;
+ List result = new ArrayList(filterDescs.length);
+ List enabledFilterIds = Arrays.asList(fEnabledFilterIds);
+ for (int i = 0; i < filterDescs.length; i++) {
+ String id = filterDescs[i].getId();
+ if (enabledFilterIds.contains(id))
+ result.add(filterDescs[i]);
+ }
+ return (FilterDescriptor[]) result.toArray(new FilterDescriptor[result
+ .size()]);
+ }
+
+ public static String[] convertFromString(String patterns, String separator) {
+ StringTokenizer tokenizer = new StringTokenizer(patterns, separator,
+ true);
+ int tokenCount = tokenizer.countTokens();
+ List result = new ArrayList(tokenCount);
+ boolean escape = false;
+ boolean append = false;
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken().trim();
+ if (separator.equals(token)) {
+ if (!escape)
+ escape = true;
+ else {
+ addPattern(result, separator);
+ append = true;
+ }
+ } else {
+ if (!append)
+ result.add(token);
+ else
+ addPattern(result, token);
+ append = false;
+ escape = false;
+ }
+ }
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ private static void addPattern(List list, String pattern) {
+ if (list.isEmpty())
+ list.add(pattern);
+ else {
+ int index = list.size() - 1;
+ list.set(index, ((String) list.get(index)) + pattern);
+ }
+ }
+
+ public static String convertToString(String[] patterns, String separator) {
+ int length = patterns.length;
+ StringBuffer strBuf = new StringBuffer();
+ if (length > 0)
+ strBuf.append(escapeSeparator(patterns[0], separator));
+ else
+ return ""; //$NON-NLS-1$
+ int i = 1;
+ while (i < length) {
+ strBuf.append(separator);
+ strBuf.append(" "); //$NON-NLS-1$
+ strBuf.append(escapeSeparator(patterns[i++], separator));
+ }
+ return strBuf.toString();
+ }
+
+ private static String escapeSeparator(String pattern, String separator) {
+ int length = pattern.length();
+ StringBuffer buf = new StringBuffer(length);
+ for (int i = 0; i < length; i++) {
+ char ch = pattern.charAt(i); //$NON-NLS-1$
+ if (separator.equals(String.valueOf(ch)))
+ buf.append(ch);
+ buf.append(ch);
+ }
+ return buf.toString();
+
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FieldsFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FieldsFilter.java
new file mode 100644
index 0000000..ad3fd39
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FieldsFilter.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.internal.ui.viewsupport.MemberFilter;
+
+/**
+ * Fields filter.
+ *
+ * @since 3.0
+ */
+public class FieldsFilter extends MemberFilter {
+ public FieldsFilter() {
+ addFilter(MemberFilter.FILTER_FIELDS);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterDescriptor.java
new file mode 100644
index 0000000..9c722b6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterDescriptor.java
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.ui.IPluginContribution;
+import org.eclipse.ui.activities.WorkbenchActivityHelper;
+
+/**
+ * Represents a custom filter which is provided by the
+ * "net.sourceforge.phpdt.ui.javaElementFilters" extension point.
+ *
+ * since 2.0
+ */
+public class FilterDescriptor implements Comparable, IPluginContribution {
+
+ private static String PATTERN_FILTER_ID_PREFIX = "_patternFilterId_"; //$NON-NLS-1$
+
+ private static final String EXTENSION_POINT_NAME = "phpElementFilters"; //$NON-NLS-1$
+
+ private static final String FILTER_TAG = "filter"; //$NON-NLS-1$
+
+ private static final String PATTERN_ATTRIBUTE = "pattern"; //$NON-NLS-1$
+
+ private static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$
+
+ /**
+ * @deprecated as of 3.0 use {@link FilterDescriptor#TARGET_ID_ATTRIBUTE}
+ */
+ private static final String VIEW_ID_ATTRIBUTE = "viewId"; //$NON-NLS-1$
+
+ private static final String TARGET_ID_ATTRIBUTE = "targetId"; //$NON-NLS-1$
+
+ private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+
+ private static final String NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
+
+ private static final String ENABLED_ATTRIBUTE = "enabled"; //$NON-NLS-1$
+
+ private static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
+
+ /**
+ * @deprecated use "enabled" instead
+ */
+ private static final String SELECTED_ATTRIBUTE = "selected"; //$NON-NLS-1$
+
+ private static FilterDescriptor[] fgFilterDescriptors;
+
+ private IConfigurationElement fElement;
+
+ /**
+ * Returns all contributed Java element filters.
+ */
+ public static FilterDescriptor[] getFilterDescriptors() {
+ if (fgFilterDescriptors == null) {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IConfigurationElement[] elements = registry
+ .getConfigurationElementsFor(WebUI.PLUGIN_ID,
+ EXTENSION_POINT_NAME);
+ fgFilterDescriptors = createFilterDescriptors(elements);
+ }
+ return fgFilterDescriptors;
+ }
+
+ /**
+ * Returns all Java element filters which are contributed to the given view.
+ */
+ public static FilterDescriptor[] getFilterDescriptors(String targetId) {
+ FilterDescriptor[] filterDescs = FilterDescriptor
+ .getFilterDescriptors();
+ List result = new ArrayList(filterDescs.length);
+ for (int i = 0; i < filterDescs.length; i++) {
+ String tid = filterDescs[i].getTargetId();
+ if (WorkbenchActivityHelper.filterItem(filterDescs[i]))
+ continue;
+ if (tid == null || tid.equals(targetId))
+ result.add(filterDescs[i]);
+ }
+ return (FilterDescriptor[]) result.toArray(new FilterDescriptor[result
+ .size()]);
+ }
+
+ /**
+ * Creates a new filter descriptor for the given configuration element.
+ */
+ private FilterDescriptor(IConfigurationElement element) {
+ fElement = element;
+ // it is either a pattern filter or a custom filter
+ Assert
+ .isTrue(
+ isPatternFilter() ^ isCustomFilter(),
+ "An extension for extension-point net.sourceforge.phpdt.ui.javaElementFilters does not specify a correct filter"); //$NON-NLS-1$
+ Assert
+ .isNotNull(
+ getId(),
+ "An extension for extension-point net.sourceforge.phpdt.ui.javaElementFilters does not provide a valid ID"); //$NON-NLS-1$
+ Assert
+ .isNotNull(
+ getName(),
+ "An extension for extension-point net.sourceforge.phpdt.ui.javaElementFilters does not provide a valid name"); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates a new ViewerFilter
. This method is only valid for
+ * viewer filters.
+ */
+ public ViewerFilter createViewerFilter() {
+ if (!isCustomFilter())
+ return null;
+
+ final ViewerFilter[] result = new ViewerFilter[1];
+ String message = FilterMessages.getFormattedString(
+ "FilterDescriptor.filterCreationError.message", getId()); //$NON-NLS-1$
+ ISafeRunnable code = new SafeRunnable(message) {
+ /*
+ * @see org.eclipse.core.runtime.ISafeRunnable#run()
+ */
+ public void run() throws Exception {
+ result[0] = (ViewerFilter) fElement
+ .createExecutableExtension(CLASS_ATTRIBUTE);
+ }
+
+ };
+ Platform.run(code);
+ return result[0];
+ }
+
+ // ---- XML Attribute accessors
+ // ---------------------------------------------
+
+ /**
+ * Returns the filter's id.
+ * null
if it's not a pattern
+ * filter
+ */
+ public String getPattern() {
+ return fElement.getAttribute(PATTERN_ATTRIBUTE);
+ }
+
+ /**
+ * Returns the filter's viewId.
+ *
+ * @return the view ID or null
if the filter is for all views
+ * @since 3.0
+ */
+ public String getTargetId() {
+ String tid = fElement.getAttribute(TARGET_ID_ATTRIBUTE);
+
+ if (tid != null)
+ return tid;
+
+ // Backwards compatibility code
+ return fElement.getAttribute(VIEW_ID_ATTRIBUTE);
+
+ }
+
+ /**
+ * Returns the filter's description.
+ *
+ * @return the description or null
if no description is
+ * provided
+ */
+ public String getDescription() {
+ String description = fElement.getAttribute(DESCRIPTION_ATTRIBUTE);
+ if (description == null)
+ description = ""; //$NON-NLS-1$
+ return description;
+ }
+
+ /**
+ * @return true
if this filter is a custom filter.
+ */
+ public boolean isPatternFilter() {
+ return getPattern() != null;
+ }
+
+ /**
+ * @return true
if this filter is a pattern filter.
+ */
+ public boolean isCustomFilter() {
+ return fElement.getAttribute(CLASS_ATTRIBUTE) != null;
+ }
+
+ /**
+ * Returns true
if the filter is initially enabled.
+ *
+ * This attribute is optional and defaults to true
.
+ */
+ public boolean isEnabled() {
+ String strVal = fElement.getAttribute(ENABLED_ATTRIBUTE);
+ if (strVal == null)
+ // backward compatibility
+ strVal = fElement.getAttribute(SELECTED_ATTRIBUTE);
+ return strVal == null || Boolean.valueOf(strVal).booleanValue();
+ }
+
+ /*
+ * Implements a method from IComparable
+ */
+ public int compareTo(Object o) {
+ if (o instanceof FilterDescriptor)
+ return Collator.getInstance().compare(getName(),
+ ((FilterDescriptor) o).getName());
+ else
+ return Integer.MIN_VALUE;
+ }
+
+ // ---- initialization ---------------------------------------------------
+
+ /**
+ * Creates the filter descriptors.
+ */
+ private static FilterDescriptor[] createFilterDescriptors(
+ IConfigurationElement[] elements) {
+ List result = new ArrayList(5);
+ Set descIds = new HashSet(5);
+ for (int i = 0; i < elements.length; i++) {
+ final IConfigurationElement element = elements[i];
+ if (FILTER_TAG.equals(element.getName())) {
+
+ final FilterDescriptor[] desc = new FilterDescriptor[1];
+ Platform
+ .run(new SafeRunnable(
+ FilterMessages
+ .getString("FilterDescriptor.filterDescriptionCreationError.message")) { //$NON-NLS-1$
+ public void run() throws Exception {
+ desc[0] = new FilterDescriptor(element);
+ }
+ });
+
+ if (desc[0] != null && !descIds.contains(desc[0].getId())) {
+ result.add(desc[0]);
+ descIds.add(desc[0].getId());
+ }
+ }
+ }
+ Collections.sort(result);
+ return (FilterDescriptor[]) result.toArray(new FilterDescriptor[result
+ .size()]);
+ }
+
+ public String getLocalId() {
+ return fElement.getAttribute(ID_ATTRIBUTE);
+ }
+
+ public String getPluginId() {
+ return fElement.getDeclaringExtension().getNamespace();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterMessages.java
new file mode 100644
index 0000000..7ed3444
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterMessages.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class FilterMessages {
+
+ private static final String RESOURCE_BUNDLE = FilterMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private FilterMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * 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[] args) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ return MessageFormat.format(format, args);
+ }
+
+ /**
+ * 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) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ if (arg == null)
+ arg = ""; //$NON-NLS-1$
+ return MessageFormat.format(format, new Object[] { arg });
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterMessages.properties
new file mode 100644
index 0000000..5904766
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/FilterMessages.properties
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2000, 2004 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+CustomFiltersDialog.title= Java Element Filters
+CustomFiltersDialog.patternInfo= The patterns are separated by comma, where\n* = any string, ? = any character, ,, = ,
+CustomFiltersDialog.enableUserDefinedPattern= &Name filter patterns (matching names will be hidden):
+CustomFiltersDialog.filterList.label= S&elect the elements to exclude from the view:
+CustomFiltersDialog.description.label= Filter description:
+CustomFiltersDialog.SelectAllButton.label= &Select All
+CustomFiltersDialog.DeselectAllButton.label= &Deselect All
+
+OpenCustomFiltersDialogAction.text= &Filters...
+
+FilterDescriptor.filterDescriptionCreationError.message= One of the extensions for extension-point net.sourceforge.phpdt.ui.javaElementFilters is incorrect.
+FilterDescriptor.filterCreationError.title= Filter Creation Error
+FilterDescriptor.filterCreationError.message= The net.sourceforge.phpdt.ui.javaElementFilters plug-in extension "{0}" specifies a viewer filter class which does not exist.
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ImportDeclarationFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ImportDeclarationFilter.java
new file mode 100644
index 0000000..c317b54
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/ImportDeclarationFilter.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.core.IImportContainer;
+import net.sourceforge.phpdt.core.IImportDeclaration;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Filters import declarations
+ */
+public class ImportDeclarationFilter extends ViewerFilter {
+
+ /*
+ * @see ViewerFilter
+ */
+ public boolean select(Viewer viewer, Object parent, Object element) {
+ return !((element instanceof IImportContainer) || (element instanceof IImportDeclaration));
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/InterfaceFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/InterfaceFilter.java
new file mode 100644
index 0000000..cfe35e1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/InterfaceFilter.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Filters interfaces
+ */
+public class InterfaceFilter extends ViewerFilter {
+
+ /*
+ * @see ViewerFilter
+ */
+ public boolean select(Viewer viewer, Object parent, Object element) {
+ if (element instanceof IType) {
+ try {
+ return !((IType) element).isInterface();
+ } catch (JavaModelException ex) {
+ return true;
+ }
+ }
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/JavaFileFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/JavaFileFilter.java
new file mode 100644
index 0000000..d406dc8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/JavaFileFilter.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Filters out all compilation units and class files elements.
+ */
+public class JavaFileFilter extends ViewerFilter {
+
+ /**
+ * Returns the result of this filter, when applied to the given inputs.
+ *
+ * @param inputs
+ * the set of elements to
+ * @return Returns true if element should be included in filtered set
+ */
+ public boolean select(Viewer viewer, Object parent, Object element) {
+ if (element instanceof ICompilationUnit)
+ return false;
+ // if (element instanceof IClassFile)
+ // return false;
+
+ // if (element instanceof IPackageFragment)
+ // try {
+ // return ((IPackageFragment)element).getNonJavaResources().length > 0;
+ // } catch (JavaModelException ex) {
+ // return true;
+ // }
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/NamePatternFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/NamePatternFilter.java
new file mode 100644
index 0000000..f1dc30a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/NamePatternFilter.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.ui.util.StringMatcher;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * The NamePatternFilter selects the elements which match the given string
+ * patterns.
+ * true
if element should be included
+ * @since 3.0
+ */
+ public boolean select(Viewer viewer, Object parent, Object element) {
+ if (element instanceof IFolder) {
+ IFolder folder = (IFolder) element;
+ IProject proj = folder.getProject();
+ try {
+ if (!proj.hasNature(WebUI.PHP_NATURE_ID))
+ return true;
+
+ IJavaProject jProject = JavaCore.create(folder.getProject());
+ if (jProject == null || !jProject.exists())
+ return true;
+
+ // Check default output location
+ IPath defaultOutputLocation = jProject.getOutputLocation();
+ IPath folderPath = folder.getFullPath();
+ if (defaultOutputLocation != null
+ && defaultOutputLocation.equals(folderPath))
+ return false;
+
+ // Check output location for each class path entry
+ IClasspathEntry[] cpEntries = jProject.getRawClasspath();
+ for (int i = 0, length = cpEntries.length; i < length; i++) {
+ IPath outputLocation = cpEntries[i].getOutputLocation();
+ if (outputLocation != null
+ && outputLocation.equals(folderPath))
+ return false;
+ }
+ } catch (CoreException ex) {
+ return true;
+ }
+ }
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/StaticsFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/StaticsFilter.java
new file mode 100644
index 0000000..6179f48
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/filters/StaticsFilter.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.filters;
+
+import net.sourceforge.phpdt.internal.ui.viewsupport.MemberFilter;
+
+/**
+ * Statics filter.
+ *
+ * @since 3.0
+ */
+public class StaticsFilter extends MemberFilter {
+ public StaticsFilter() {
+ addFilter(MemberFilter.FILTER_STATIC);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/phpdocexport/JavadocExportMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/phpdocexport/JavadocExportMessages.java
new file mode 100644
index 0000000..b6a785b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/phpdocexport/JavadocExportMessages.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.phpdocexport;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class JavadocExportMessages {
+
+ private static final String RESOURCE_BUNDLE = JavadocExportMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private JavadocExportMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/phpdocexport/JavadocExportMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/phpdocexport/JavadocExportMessages.properties
new file mode 100644
index 0000000..58866ea
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/phpdocexport/JavadocExportMessages.properties
@@ -0,0 +1,104 @@
+###############################################################################
+# Copyright (c) 2000, 2003 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+
+JavadocSpecificsWizardPage.description=Configure Javadoc arguments.
+
+
+JavadocSpecificsWizardPage.stylesheetbrowsedialog.title=Style sheet Selection
+JavadocSpecificsWizardPage.overviewbutton.label=&Overview:
+JavadocSpecificsWizardPage.overviewbrowse.label=Bro&wse...
+JavadocSpecificsWizardPage.extraoptionsfield.label=E&xtra Javadoc options (path names with white spaces must be enclosed in quotes):
+JavadocSpecificsWizardPage.overviewbrowsedialog.title=Select overview page
+JavadocSpecificsWizardPage.antscriptbutton.label=&Save the settings of this Javadoc export as an Ant script:
+JavadocSpecificsWizardPage.antscripttext.label=&Ant Script:
+JavadocSpecificsWizardPage.antscriptbrowse.label=Brows&e...
+JavadocSpecificsWizardPage.openbrowserbutton.label=O&pen generated index file in browser
+JavadocSpecificsWizardPage.antscriptbrowsedialog.title=Destination Selection
+JavadocSpecificsWizardPage.antscriptbrowsedialog.label=&Select destination folder for ant script:
+
+JavadocSpecificsWizardPage.jdk14mode.label=JRE 1.4 source compatibility
+
+JavadocSpecificsWizardPage.overviewnotfound.error=Overview path not found.
+JavadocSpecificsWizardPage.overviewincorrect.error=Overview must be an html document.
+JavadocSpecificsWizardPage.antfileincorrect.error=Not a valid Ant file name.
+JavadocSpecificsWizardPage.antfileoverwrite.warning=The generated ant file will overwrite the existing ant file.
+JavadocTreeWizardPage.javadoctreewizardpage.description=Select types for Javadoc generation.
+JavadocTreeWizardPage.checkboxtreeandlistgroup.label=Select &types for which Javadoc will be generated:
+JavadocTreeWizardPage.visibilitygroup.label=Create Javadoc for members with visibility:
+JavadocTreeWizardPage.privatebutton.label=Pr&ivate
+JavadocTreeWizardPage.packagebutton.label=P&ackage
+JavadocTreeWizardPage.protectedbutton.label=Pr&otected
+JavadocTreeWizardPage.publicbutton.label=P&ublic
+JavadocTreeWizardPage.standarddocletbutton.label=Use &Standard Doclet
+JavadocTreeWizardPage.destinationfield.label=&Destination:
+JavadocTreeWizardPage.destinationbrowse.label=Bro&wse...
+JavadocTreeWizardPage.customdocletbutton.label=Use &Custom Doclet
+JavadocTreeWizardPage.docletnamefield.label=Doc&let name:
+JavadocTreeWizardPage.docletpathfield.label=Doclet class &path:
+JavadocTreeWizardPage.destinationbrowsedialog.title=Destination Selection
+JavadocTreeWizardPage.destinationbrowsedialog.label=&Select the Javadoc destination folder:
+JavadocTreeWizardPage.javadoccommand.error=Javadoc command location not specified on the Javadoc preference page.
+JavadocTreeWizardPage.nodocletname.error=Enter a doclet name.
+JavadocTreeWizardPage.invaliddocletname.error=Invalid doclet name.
+JavadocTreeWizardPage.invaliddocletpath.error=Not a valid doclet class path.
+JavadocTreeWizardPage.nodestination.error=Enter the destination folder.
+JavadocTreeWizardPage.invaliddestination.error=Not a valid folder.
+JavadocTreeWizardPage.invalidtreeselection.error=Select elements from tree.
+
+JavadocWizardPage.javadocwizardpage.description=Javadoc Generation
+JavadocWizard.javadocwizard.title=Generate Javadoc
+JavadocWizard.updatejavadoclocation.message=Do you want to update the Javadoc location for ''{0}'' with the chosen destination folder ''{1}''?
+JavadocWizard.updatejavadocdialog.label=Update Javadoc Location
+JavadocWizard.javadocprocess.label=Javadoc Generation
+JavadocWizard.saveresourcedialogCE.title=Save Resources
+JavadocWizard.saveresourcedialogCE.message=Saving resources failed.
+JavadocWizard.saveresourcedialogITE.title=Save Resources
+JavadocWizard.saveresourcedialogITE.message=Saving resources failed.
+JavadocWizard.savetask.name=Saving...
+JavadocWizard.launchconfig.name=Javadoc
+
+JavadocOptionsManager.antfileincorrectCE.warning=Unable to run wizard from Ant file, loading previous settings.
+JavadocOptionsManager.antfileincorrectIOE.warning=Error reading Ant file, loading previous settings.
+JavadocOptionsManager.antfileincorrectSAXE.warning=Error reading Ant file, loading previous settings.
+
+JavadcoStandardWizardPage.description=Configure Javadoc arguments for standard doclet.
+JavadcoStandardWizardPage.titlebutton.label=Document &title:
+JavadcoStandardWizardPage.basicgroup.label=Basic Options
+JavadcoStandardWizardPage.usebutton.label=Generate &use page
+JavadcoStandardWizardPage.hierarchybutton.label=Generate &hierarchy tree
+JavadcoStandardWizardPage.navigartorbutton.label=Generate navi&gator bar
+JavadcoStandardWizardPage.indexbutton.label=Generate &index
+JavadcoStandardWizardPage.seperateindexbutton.label=Separate index &per letter
+JavadcoStandardWizardPage.tagsgroup.label=Document these tags
+JavadcoStandardWizardPage.authorbutton.label=@&author
+JavadcoStandardWizardPage.versionbutton.label=@&version
+JavadcoStandardWizardPage.deprecatedbutton.label=@&deprecated
+JavadcoStandardWizardPage.deprecatedlistbutton.label=deprecated &list
+JavadcoStandardWizardPage.stylesheettext.label=St&yle sheet:
+JavadcoStandardWizardPage.selectallbutton.label=&Select All
+JavadcoStandardWizardPage.clearallbutton.label=&Clear All
+JavadcoStandardWizardPage.referencedclasses.label=Select &referenced classes to which Javadoc should create links:
+JavadcoStandardWizardPage.stylesheetnopath.error=Style sheet path not found.
+JavadcoStandardWizardPage.stylesheetnotcss.error=Style sheet must be a css document.
+JavadocStandardWizardPage.stylesheetbrowsebutton.label=Bro&wse...
+JavadocStandardWizardPage.configurebutton.label=Con&figure...
+JavadocStandardWizardPage.javadocpropertydialog.title=Configure Javadoc Location
+
+JavadocLinkDialogLabelProvider.configuredentry={0} - {1}
+JavadocLinkDialogLabelProvider.notconfiguredentry={0} - Not Configured
+JavadocTreeWizardPage.privatevisibilitydescription.label=Private: Generate Javadoc for all classes and members.
+JavadocTreeWizardPage.warning.mayoverwritefiles=Javadoc generation may overwrite existing files
+JavadocTreeWizardPage.packagevisibledescription.label=Package: Generate Javadoc for only package, protected, and public classes and members.
+JavadocTreeWizardPage.protectedvisibilitydescription.label=Protected: Generate Javadoc for only protected and public classes and members.
+JavadocTreeWizardPage.publicvisibilitydescription.label=Public: Generate Javadoc for only public classes and members.
+JavadocWizard.antInformationDialog.title=Javadoc Generation with Ant Scripts
+JavadocWizard.antInformationDialog.message=Ant file will be created.\nNote that to run the generated ant script, the operating system PATH must contain the Javadoc command.
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/AbstractConfigurationBlockPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/AbstractConfigurationBlockPreferencePage.java
new file mode 100644
index 0000000..9f5bb6b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/AbstractConfigurationBlockPreferencePage.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Abstract preference page which is used to wrap a
+ * {@link net.sourceforge.phpdt.internal.ui.preferences.IPreferenceConfigurationBlock}.
+ *
+ * @since 3.0
+ */
+public abstract class AbstractConfigurationBlockPreferencePage extends
+ PreferencePage implements IWorkbenchPreferencePage {
+
+ private IPreferenceConfigurationBlock fConfigurationBlock;
+
+ private OverlayPreferenceStore fOverlayStore;
+
+ /**
+ * Creates a new preference page.
+ */
+ public AbstractConfigurationBlockPreferencePage() {
+ setDescription();
+ setPreferenceStore();
+ fOverlayStore = new OverlayPreferenceStore(getPreferenceStore(),
+ new OverlayPreferenceStore.OverlayKey[] {});
+ fConfigurationBlock = createConfigurationBlock(fOverlayStore);
+ }
+
+ protected abstract IPreferenceConfigurationBlock createConfigurationBlock(
+ OverlayPreferenceStore overlayPreferenceStore);
+
+ protected abstract String getHelpId();
+
+ protected abstract void setDescription();
+
+ protected abstract void setPreferenceStore();
+
+ /*
+ * @see IWorkbenchPreferencePage#init()
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * @see PreferencePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ getHelpId());
+ }
+
+ /*
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+
+ fOverlayStore.load();
+ fOverlayStore.start();
+
+ fConfigurationBlock.createControl(parent);
+
+ initialize();
+
+ Dialog.applyDialogFont(parent);
+ return parent;
+ }
+
+ private void initialize() {
+ fConfigurationBlock.initialize();
+ }
+
+ /*
+ * @see PreferencePage#performOk()
+ */
+ public boolean performOk() {
+
+ fConfigurationBlock.performOk();
+
+ fOverlayStore.propagate();
+
+ WebUI.getDefault().savePluginPreferences();
+
+ return true;
+ }
+
+ /*
+ * @see PreferencePage#performDefaults()
+ */
+ public void performDefaults() {
+
+ fOverlayStore.loadDefaults();
+ fConfigurationBlock.performDefaults();
+
+ super.performDefaults();
+ }
+
+ /*
+ * @see DialogPage#dispose()
+ */
+ public void dispose() {
+
+ fConfigurationBlock.dispose();
+
+ if (fOverlayStore != null) {
+ fOverlayStore.stop();
+ fOverlayStore = null;
+ }
+
+ super.dispose();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CodeAssistConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CodeAssistConfigurationBlock.java
new file mode 100644
index 0000000..1a116f6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CodeAssistConfigurationBlock.java
@@ -0,0 +1,645 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Configures the code assist preferences.
+ *
+ * @since 3.0
+ */
+class CodeAssistConfigurationBlock implements IPreferenceConfigurationBlock {
+
+ private OverlayPreferenceStore fStore;
+
+ private PreferencePage fMainPreferencePage;
+
+ private List fContentAssistColorList;
+
+ private ColorEditor fContentAssistColorEditor;
+
+ private Control fAutoInsertDelayText;
+
+ private Control fAutoInsertJavaTriggerText;
+
+ private Control fAutoInsertJavaDocTriggerText;
+
+ private Control fAutoInsertHTMLTriggerText;
+
+ private Label fAutoInsertDelayLabel;
+
+ private Label fAutoInsertJavaTriggerLabel;
+
+ private Label fAutoInsertJavaDocTriggerLabel;
+
+ private Label fAutoInsertHTMLTriggerLabel;
+
+ // private Button fCompletionInsertsRadioButton;
+ // private Button fCompletionOverwritesRadioButton;
+ /**
+ * List of master/slave listeners when there's a dependency.
+ *
+ * @see #createDependency(Button, String, Control)
+ * @since 3.0
+ */
+ private ArrayList fMasterSlaveListeners = new ArrayList();
+
+ private final String[][] fContentAssistColorListModel = new String[][] {
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.backgroundForCompletionProposals"), PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND }, //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.foregroundForCompletionProposals"), PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND }, //$NON-NLS-1$
+ // {PreferencesMessages.getString("JavaEditorPreferencePage.backgroundForMethodParameters"),
+ // PreferenceConstants.CODEASSIST_PARAMETERS_BACKGROUND },
+ // //$NON-NLS-1$
+ // {PreferencesMessages.getString("JavaEditorPreferencePage.foregroundForMethodParameters"),
+ // PreferenceConstants.CODEASSIST_PARAMETERS_FOREGROUND },
+ // //$NON-NLS-1$
+ // {PreferencesMessages.getString("JavaEditorPreferencePage.backgroundForCompletionReplacement"),
+ // PreferenceConstants.CODEASSIST_REPLACEMENT_BACKGROUND },
+ // //$NON-NLS-1$
+ // {PreferencesMessages.getString("JavaEditorPreferencePage.foregroundForCompletionReplacement"),
+ // PreferenceConstants.CODEASSIST_REPLACEMENT_FOREGROUND }
+ // //$NON-NLS-1$
+ };
+
+ private Map fCheckBoxes = new HashMap();
+
+ private SelectionListener fCheckBoxListener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ Button button = (Button) e.widget;
+ fStore.setValue((String) fCheckBoxes.get(button), button
+ .getSelection());
+ }
+ };
+
+ private Map fTextFields = new HashMap();
+
+ private ModifyListener fTextFieldListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ Text text = (Text) e.widget;
+ fStore.setValue((String) fTextFields.get(text), text.getText());
+ }
+ };
+
+ private ArrayList fNumberFields = new ArrayList();
+
+ private ModifyListener fNumberFieldListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ numberFieldChanged((Text) e.widget);
+ }
+ };
+
+ public CodeAssistConfigurationBlock(PreferencePage mainPreferencePage,
+ OverlayPreferenceStore store) {
+ Assert.isNotNull(mainPreferencePage);
+ Assert.isNotNull(store);
+ fStore = store;
+ fStore.addKeys(createOverlayStoreKeys());
+ fMainPreferencePage = mainPreferencePage;
+ }
+
+ private OverlayPreferenceStore.OverlayKey[] createOverlayStoreKeys() {
+
+ ArrayList overlayKeys = new ArrayList();
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.INT,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_AUTOINSERT));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PARAMETERS_BACKGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PARAMETERS_FOREGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_REPLACEMENT_BACKGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_REPLACEMENT_FOREGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_HTML));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_ORDER_PROPOSALS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_CASE_SENSITIVITY));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_ADDIMPORT));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_INSERT_COMPLETION));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_PREFIX_COMPLETION));
+
+ OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys
+ .size()];
+ overlayKeys.toArray(keys);
+ return keys;
+ }
+
+ /**
+ * Creates page for hover preferences.
+ *
+ * @param parent
+ * the parent composite
+ * @return the control for the preference page
+ */
+ public Control createControl(Composite parent) {
+
+ PixelConverter pixelConverter = new PixelConverter(parent);
+
+ Composite contentAssistComposite = new Composite(parent, SWT.NONE);
+ contentAssistComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ contentAssistComposite.setLayout(layout);
+
+ // addCompletionRadioButtons(contentAssistComposite);
+
+ String label;
+ // label=
+ // PreferencesMessages.getString("JavaEditorPreferencePage.insertSingleProposalsAutomatically");
+ // //$NON-NLS-1$
+ // addCheckBox(contentAssistComposite, label,
+ // PreferenceConstants.CODEASSIST_AUTOINSERT, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("JavaEditorPreferencePage.completePrefixes");
+ // //$NON-NLS-1$
+ // addCheckBox(contentAssistComposite, label,
+ // PreferenceConstants.CODEASSIST_PREFIX_COMPLETION, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("JavaEditorPreferencePage.showOnlyProposalsVisibleInTheInvocationContext");
+ // //$NON-NLS-1$
+ // addCheckBox(contentAssistComposite, label,
+ // PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("JavaEditorPreferencePage.presentProposalsInAlphabeticalOrder");
+ // //$NON-NLS-1$
+ // addCheckBox(contentAssistComposite, label,
+ // PreferenceConstants.CODEASSIST_ORDER_PROPOSALS, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("JavaEditorPreferencePage.automaticallyAddImportInsteadOfQualifiedName");
+ // //$NON-NLS-1$
+ // addCheckBox(contentAssistComposite, label,
+ // PreferenceConstants.CODEASSIST_ADDIMPORT, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("JavaEditorPreferencePage.fillArgumentNamesOnMethodCompletion");
+ // //$NON-NLS-1$
+ // Button master= addCheckBox(contentAssistComposite, label,
+ // PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES, 0);
+ //
+ // label=
+ // PreferencesMessages.getString("JavaEditorPreferencePage.guessArgumentNamesOnMethodCompletion");
+ // //$NON-NLS-1$
+ // Button slave= addCheckBox(contentAssistComposite, label,
+ // PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS, 0);
+ // createDependency(master,
+ // PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES, slave);
+ //
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.enableAutoActivation"); //$NON-NLS-1$
+ final Button autoactivation = addCheckBox(contentAssistComposite,
+ label, PreferenceConstants.CODEASSIST_AUTOACTIVATION, 0);
+ autoactivation.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ updateAutoactivationControls();
+ }
+ });
+
+ Control[] labelledTextField;
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.autoActivationDelay"); //$NON-NLS-1$
+ labelledTextField = addLabelledTextField(contentAssistComposite, label,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY, 4, 0, true);
+ fAutoInsertDelayLabel = getLabelControl(labelledTextField);
+ fAutoInsertDelayText = getTextControl(labelledTextField);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.autoActivationTriggersForJava"); //$NON-NLS-1$
+ labelledTextField = addLabelledTextField(contentAssistComposite, label,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA, 4,
+ 0, false);
+ fAutoInsertJavaTriggerLabel = getLabelControl(labelledTextField);
+ fAutoInsertJavaTriggerText = getTextControl(labelledTextField);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.autoActivationTriggersForJavaDoc"); //$NON-NLS-1$
+ labelledTextField = addLabelledTextField(contentAssistComposite, label,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC,
+ 4, 0, false);
+ fAutoInsertJavaDocTriggerLabel = getLabelControl(labelledTextField);
+ fAutoInsertJavaDocTriggerText = getTextControl(labelledTextField);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.autoActivationTriggersForHTML"); //$NON-NLS-1$
+ labelledTextField = addLabelledTextField(contentAssistComposite, label,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_HTML, 4,
+ 0, false);
+ fAutoInsertHTMLTriggerLabel = getLabelControl(labelledTextField);
+ fAutoInsertHTMLTriggerText = getTextControl(labelledTextField);
+
+ Label l = new Label(contentAssistComposite, SWT.LEFT);
+ l.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.codeAssist.colorOptions")); //$NON-NLS-1$
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ l.setLayoutData(gd);
+
+ Composite editorComposite = new Composite(contentAssistComposite,
+ SWT.NONE);
+ layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.FILL_VERTICAL);
+ gd.horizontalSpan = 2;
+ editorComposite.setLayoutData(gd);
+
+ fContentAssistColorList = new List(editorComposite, SWT.SINGLE
+ | SWT.V_SCROLL | SWT.BORDER);
+ gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
+ | GridData.FILL_HORIZONTAL);
+ gd.heightHint = pixelConverter.convertHeightInCharsToPixels(8);
+ fContentAssistColorList.setLayoutData(gd);
+
+ Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ l = new Label(stylesComposite, SWT.LEFT);
+ l.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.codeAssist.color")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.BEGINNING;
+ l.setLayoutData(gd);
+
+ fContentAssistColorEditor = new ColorEditor(stylesComposite);
+ Button colorButton = fContentAssistColorEditor.getButton();
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ colorButton.setLayoutData(gd);
+
+ fContentAssistColorList.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ handleContentAssistColorListSelection();
+ }
+ });
+ colorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ int i = fContentAssistColorList.getSelectionIndex();
+ String key = fContentAssistColorListModel[i][1];
+
+ PreferenceConverter.setValue(fStore, key,
+ fContentAssistColorEditor.getColorValue());
+ }
+ });
+
+ return contentAssistComposite;
+ }
+
+ private void createDependency(final Button master, String masterKey,
+ final Control slave) {
+ indent(slave);
+ boolean masterState = fStore.getBoolean(masterKey);
+ slave.setEnabled(masterState);
+ SelectionListener listener = new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ slave.setEnabled(master.getSelection());
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ };
+ master.addSelectionListener(listener);
+ fMasterSlaveListeners.add(listener);
+ }
+
+ private static void indent(Control control) {
+ GridData gridData = new GridData();
+ gridData.horizontalIndent = 20;
+ control.setLayoutData(gridData);
+ }
+
+ private static Text getTextControl(Control[] labelledTextField) {
+ return (Text) labelledTextField[1];
+ }
+
+ private static Label getLabelControl(Control[] labelledTextField) {
+ return (Label) labelledTextField[0];
+ }
+
+ /**
+ * Returns an array of size 2: - first element is of type Label
-
+ * second element is of type Text
Use
+ * getLabelControl
and getTextControl
to get
+ * the 2 controls.
+ *
+ * @param composite
+ * the parent composite
+ * @param label
+ * the text field's label
+ * @param key
+ * the preference key
+ * @param textLimit
+ * the text limit
+ * @param indentation
+ * the field's indentation
+ * @param isNumber
+ * true
iff this text field is used to e4dit a
+ * number
+ * @return
+ */
+ private Control[] addLabelledTextField(Composite composite, String label,
+ String key, int textLimit, int indentation, boolean isNumber) {
+
+ PixelConverter pixelConverter = new PixelConverter(composite);
+
+ Label labelControl = new Label(composite, SWT.NONE);
+ labelControl.setText(label);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ labelControl.setLayoutData(gd);
+
+ Text textControl = new Text(composite, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.widthHint = pixelConverter
+ .convertWidthInCharsToPixels(textLimit + 1);
+ textControl.setLayoutData(gd);
+ textControl.setTextLimit(textLimit);
+ fTextFields.put(textControl, key);
+ if (isNumber) {
+ fNumberFields.add(textControl);
+ textControl.addModifyListener(fNumberFieldListener);
+ } else {
+ textControl.addModifyListener(fTextFieldListener);
+ }
+
+ return new Control[] { labelControl, textControl };
+ }
+
+ private void addCompletionRadioButtons(Composite contentAssistComposite) {
+ Composite completionComposite = new Composite(contentAssistComposite,
+ SWT.NONE);
+ GridData ccgd = new GridData();
+ ccgd.horizontalSpan = 2;
+ completionComposite.setLayoutData(ccgd);
+ GridLayout ccgl = new GridLayout();
+ ccgl.marginWidth = 0;
+ ccgl.numColumns = 2;
+ completionComposite.setLayout(ccgl);
+
+ // SelectionListener completionSelectionListener= new SelectionAdapter()
+ // {
+ // public void widgetSelected(SelectionEvent e) {
+ // boolean insert= fCompletionInsertsRadioButton.getSelection();
+ // fStore.setValue(PreferenceConstants.CODEASSIST_INSERT_COMPLETION,
+ // insert);
+ // }
+ // };
+ //
+ // fCompletionInsertsRadioButton= new Button(completionComposite,
+ // SWT.RADIO | SWT.LEFT);
+ // fCompletionInsertsRadioButton.setText(PreferencesMessages.getString("JavaEditorPreferencePage.completionInserts"));
+ // //$NON-NLS-1$
+ // fCompletionInsertsRadioButton.setLayoutData(new GridData());
+ // fCompletionInsertsRadioButton.addSelectionListener(completionSelectionListener);
+ //
+ // fCompletionOverwritesRadioButton= new Button(completionComposite,
+ // SWT.RADIO | SWT.LEFT);
+ // fCompletionOverwritesRadioButton.setText(PreferencesMessages.getString("JavaEditorPreferencePage.completionOverwrites"));
+ // //$NON-NLS-1$
+ // fCompletionOverwritesRadioButton.setLayoutData(new GridData());
+ // fCompletionOverwritesRadioButton.addSelectionListener(completionSelectionListener);
+ }
+
+ public void initialize() {
+ initializeFields();
+
+ for (int i = 0; i < fContentAssistColorListModel.length; i++)
+ fContentAssistColorList.add(fContentAssistColorListModel[i][0]);
+ fContentAssistColorList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (fContentAssistColorList != null
+ && !fContentAssistColorList.isDisposed()) {
+ fContentAssistColorList.select(0);
+ handleContentAssistColorListSelection();
+ }
+ }
+ });
+
+ }
+
+ void initializeFields() {
+ Iterator e = fCheckBoxes.keySet().iterator();
+ while (e.hasNext()) {
+ Button b = (Button) e.next();
+ String key = (String) fCheckBoxes.get(b);
+ b.setSelection(fStore.getBoolean(key));
+ }
+
+ e = fTextFields.keySet().iterator();
+ while (e.hasNext()) {
+ Text t = (Text) e.next();
+ String key = (String) fTextFields.get(t);
+ t.setText(fStore.getString(key));
+ }
+
+ // boolean completionInserts=
+ // fStore.getBoolean(PreferenceConstants.CODEASSIST_INSERT_COMPLETION);
+ // fCompletionInsertsRadioButton.setSelection(completionInserts);
+ // fCompletionOverwritesRadioButton.setSelection(! completionInserts);
+
+ updateAutoactivationControls();
+
+ updateStatus(validatePositiveNumber("0")); //$NON-NLS-1$
+
+ // Update slaves
+ Iterator iter = fMasterSlaveListeners.iterator();
+ while (iter.hasNext()) {
+ SelectionListener listener = (SelectionListener) iter.next();
+ listener.widgetSelected(null);
+ }
+ }
+
+ private void updateAutoactivationControls() {
+ boolean autoactivation = fStore
+ .getBoolean(PreferenceConstants.CODEASSIST_AUTOACTIVATION);
+ fAutoInsertDelayText.setEnabled(autoactivation);
+ fAutoInsertDelayLabel.setEnabled(autoactivation);
+
+ fAutoInsertJavaTriggerText.setEnabled(autoactivation);
+ fAutoInsertJavaTriggerLabel.setEnabled(autoactivation);
+
+ fAutoInsertJavaDocTriggerText.setEnabled(autoactivation);
+ fAutoInsertJavaDocTriggerLabel.setEnabled(autoactivation);
+
+ fAutoInsertHTMLTriggerText.setEnabled(autoactivation);
+ fAutoInsertHTMLTriggerLabel.setEnabled(autoactivation);
+ }
+
+ public void performOk() {
+ }
+
+ public void performDefaults() {
+ handleContentAssistColorListSelection();
+ initializeFields();
+ }
+
+ private void handleContentAssistColorListSelection() {
+ int i = fContentAssistColorList.getSelectionIndex();
+ String key = fContentAssistColorListModel[i][1];
+ RGB rgb = PreferenceConverter.getColor(fStore, key);
+ fContentAssistColorEditor.setColorValue(rgb);
+ }
+
+ private void numberFieldChanged(Text textControl) {
+ String number = textControl.getText();
+ IStatus status = validatePositiveNumber(number);
+ if (!status.matches(IStatus.ERROR))
+ fStore.setValue((String) fTextFields.get(textControl), number);
+ updateStatus(status);
+ }
+
+ private IStatus validatePositiveNumber(String number) {
+ StatusInfo status = new StatusInfo();
+ if (number.length() == 0) {
+ status.setError(PreferencesMessages
+ .getString("JavaEditorPreferencePage.empty_input")); //$NON-NLS-1$
+ } else {
+ try {
+ int value = Integer.parseInt(number);
+ if (value < 0)
+ status.setError(PreferencesMessages.getFormattedString(
+ "JavaEditorPreferencePage.invalid_input", number)); //$NON-NLS-1$
+ } catch (NumberFormatException e) {
+ status.setError(PreferencesMessages.getFormattedString(
+ "JavaEditorPreferencePage.invalid_input", number)); //$NON-NLS-1$
+ }
+ }
+ return status;
+ }
+
+ private void updateStatus(IStatus status) {
+ fMainPreferencePage.setValid(status.isOK());
+ StatusUtil.applyToStatusLine(fMainPreferencePage, status);
+ }
+
+ private Button addCheckBox(Composite parent, String label, String key,
+ int indentation) {
+ Button checkBox = new Button(parent, SWT.CHECK);
+ checkBox.setText(label);
+
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ gd.horizontalSpan = 2;
+ checkBox.setLayoutData(gd);
+ checkBox.addSelectionListener(fCheckBoxListener);
+
+ fCheckBoxes.put(checkBox, key);
+
+ return checkBox;
+ }
+
+ /*
+ * @see DialogPage#dispose()
+ */
+ public void dispose() {
+ // nothing to dispose
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CodeAssistPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CodeAssistPreferencePage.java
new file mode 100644
index 0000000..dca1e1f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/CodeAssistPreferencePage.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+/**
+ * Code Assist preference page.
+ * parent
+ */
+ Control createControl(Composite parent);
+
+ /**
+ * Called after creating the control. Implementations should load the
+ * preferences values and update the controls accordingly.
+ */
+ void initialize();
+
+ /**
+ * Called when the OK
button is pressed on the preference
+ * page. Implementations should commit the configured preference settings
+ * into their form of preference storage.
+ */
+ void performOk();
+
+ /**
+ * Called when the Defaults
button is pressed on the
+ * preference page. Implementation should reset any preference settings to
+ * their default values and adjust the controls accordingly.
+ */
+ void performDefaults();
+
+ /**
+ * Called when the preference page is being disposed. Implementations should
+ * free any resources they are holding on to.
+ */
+ void dispose();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaEditorHoverConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaEditorHoverConfigurationBlock.java
new file mode 100644
index 0000000..cbaaae7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaEditorHoverConfigurationBlock.java
@@ -0,0 +1,480 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaEditorTextHoverDescriptor;
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+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.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Configures Java Editor hover preferences.
+ *
+ * @since 2.1
+ */
+class JavaEditorHoverConfigurationBlock {
+
+ private static final String DELIMITER = PreferencesMessages
+ .getString("JavaEditorHoverConfigurationBlock.delimiter"); //$NON-NLS-1$
+
+ // Data structure to hold the values which are edited by the user
+ private static class HoverConfig {
+
+ private String fModifierString;
+
+ private boolean fIsEnabled;
+
+ private int fStateMask;
+
+ private HoverConfig(String modifier, int stateMask, boolean enabled) {
+ fModifierString = modifier;
+ fIsEnabled = enabled;
+ fStateMask = stateMask;
+ }
+ }
+
+ private IPreferenceStore fStore;
+
+ private HoverConfig[] fHoverConfigs;
+
+ private Text fModifierEditor;
+
+ private Button fEnableField;
+
+ private List fHoverList;
+
+ private Text fDescription;
+
+ private Button fShowHoverAffordanceCheckbox;
+
+ private JavaEditorPreferencePage fMainPreferencePage;
+
+ private StatusInfo fStatus;
+
+ public JavaEditorHoverConfigurationBlock(
+ JavaEditorPreferencePage mainPreferencePage, IPreferenceStore store) {
+ Assert.isNotNull(mainPreferencePage);
+ Assert.isNotNull(store);
+ fMainPreferencePage = mainPreferencePage;
+ fStore = store;
+ }
+
+ /**
+ * Creates page for hover preferences.
+ */
+ public Control createControl(Composite parent) {
+
+ PixelConverter pixelConverter = new PixelConverter(parent);
+
+ Composite hoverComposite = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ hoverComposite.setLayout(layout);
+ GridData gd = new GridData(GridData.GRAB_HORIZONTAL
+ | GridData.VERTICAL_ALIGN_FILL);
+ hoverComposite.setLayoutData(gd);
+
+ Label label = new Label(hoverComposite, SWT.NONE);
+ label
+ .setText(PreferencesMessages
+ .getString("JavaEditorHoverConfigurationBlock.hoverPreferences")); //$NON-NLS-1$
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ gd.horizontalSpan = 2;
+ label.setLayoutData(gd);
+ gd = new GridData(GridData.GRAB_HORIZONTAL
+ | GridData.VERTICAL_ALIGN_FILL);
+
+ // Hover list
+ fHoverList = new List(hoverComposite, SWT.SINGLE | SWT.V_SCROLL
+ | SWT.BORDER);
+ gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
+ | GridData.FILL_HORIZONTAL);
+ int listHeight = 10 * fHoverList.getItemHeight();
+ gd.heightHint = listHeight;
+ fHoverList.setLayoutData(gd);
+ fHoverList.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ handleHoverListSelection();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ Composite stylesComposite = new Composite(hoverComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.heightHint = listHeight + (2 * fHoverList.getBorderWidth());
+ stylesComposite.setLayoutData(gd);
+
+ // Enabled checkbox
+ fEnableField = new Button(stylesComposite, SWT.CHECK);
+ fEnableField.setText(PreferencesMessages
+ .getString("JavaEditorHoverConfigurationBlock.enabled")); //$NON-NLS-1$
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ gd.horizontalSpan = 2;
+ fEnableField.setLayoutData(gd);
+ fEnableField.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ int i = fHoverList.getSelectionIndex();
+ boolean state = fEnableField.getSelection();
+ fModifierEditor.setEnabled(state);
+ fHoverConfigs[i].fIsEnabled = state;
+ handleModifierModified();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ // Text field for modifier string
+ label = new Label(stylesComposite, SWT.LEFT);
+ label.setText(PreferencesMessages
+ .getString("JavaEditorHoverConfigurationBlock.keyModifier")); //$NON-NLS-1$
+ fModifierEditor = new Text(stylesComposite, SWT.BORDER);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ fModifierEditor.setLayoutData(gd);
+
+ fModifierEditor.addKeyListener(new KeyListener() {
+ private boolean isModifierCandidate;
+
+ public void keyPressed(KeyEvent e) {
+ isModifierCandidate = e.keyCode > 0 && e.character == 0
+ && e.stateMask == 0;
+ }
+
+ public void keyReleased(KeyEvent e) {
+ if (isModifierCandidate && e.stateMask > 0
+ && e.stateMask == e.stateMask && e.character == 0) {// &&
+ // e.time
+ // -time
+ // <
+ // 1000)
+ // {
+ String text = fModifierEditor.getText();
+ Point selection = fModifierEditor.getSelection();
+ int i = selection.x - 1;
+ while (i > -1 && Character.isWhitespace(text.charAt(i))) {
+ i--;
+ }
+ boolean needsPrefixDelimiter = i > -1
+ && !String.valueOf(text.charAt(i))
+ .equals(DELIMITER);
+
+ i = selection.y;
+ while (i < text.length()
+ && Character.isWhitespace(text.charAt(i))) {
+ i++;
+ }
+ boolean needsPostfixDelimiter = i < text.length()
+ && !String.valueOf(text.charAt(i))
+ .equals(DELIMITER);
+
+ String insertString;
+
+ if (needsPrefixDelimiter && needsPostfixDelimiter)
+ insertString = PreferencesMessages
+ .getFormattedString(
+ "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
+ else if (needsPrefixDelimiter)
+ insertString = PreferencesMessages
+ .getFormattedString(
+ "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifier", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
+ else if (needsPostfixDelimiter)
+ insertString = PreferencesMessages
+ .getFormattedString(
+ "JavaEditorHoverConfigurationBlock.insertModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
+ else
+ insertString = Action.findModifierString(e.stateMask);
+
+ if (insertString != null)
+ fModifierEditor.insert(insertString);
+ }
+ }
+ });
+
+ fModifierEditor.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ handleModifierModified();
+ }
+ });
+
+ // Description
+ Label descriptionLabel = new Label(stylesComposite, SWT.LEFT);
+ descriptionLabel.setText(PreferencesMessages
+ .getString("JavaEditorHoverConfigurationBlock.description")); //$NON-NLS-1$
+ gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+ gd.horizontalSpan = 2;
+ descriptionLabel.setLayoutData(gd);
+ fDescription = new Text(stylesComposite, SWT.LEFT | SWT.WRAP
+ | SWT.MULTI | SWT.READ_ONLY | SWT.BORDER);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = 2;
+ fDescription.setLayoutData(gd);
+
+ // Vertical filler
+ Label filler = new Label(hoverComposite, SWT.LEFT);
+ gd = new GridData(GridData.BEGINNING | GridData.VERTICAL_ALIGN_FILL);
+ gd.heightHint = pixelConverter.convertHeightInCharsToPixels(1) / 3;
+ filler.setLayoutData(gd);
+
+ // Affordance checkbox
+ fShowHoverAffordanceCheckbox = new Button(hoverComposite, SWT.CHECK);
+ fShowHoverAffordanceCheckbox.setText(PreferencesMessages
+ .getString("JavaEditorHoverConfigurationBlock.showAffordance")); //$NON-NLS-1$
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = 0;
+ gd.horizontalSpan = 2;
+ fShowHoverAffordanceCheckbox.setLayoutData(gd);
+
+ initialize();
+
+ Dialog.applyDialogFont(hoverComposite);
+ return hoverComposite;
+ }
+
+ private JavaEditorTextHoverDescriptor[] getContributedHovers() {
+ return WebUI.getDefault()
+ .getJavaEditorTextHoverDescriptors();
+ }
+
+ void initialize() {
+ JavaEditorTextHoverDescriptor[] hoverDescs = getContributedHovers();
+ fHoverConfigs = new HoverConfig[hoverDescs.length];
+ for (int i = 0; i < hoverDescs.length; i++) {
+ fHoverConfigs[i] = new HoverConfig(hoverDescs[i]
+ .getModifierString(), hoverDescs[i].getStateMask(),
+ hoverDescs[i].isEnabled());
+ fHoverList.add(hoverDescs[i].getLabel());
+ }
+ initializeFields();
+ }
+
+ void initializeFields() {
+ fHoverList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (fHoverList != null && !fHoverList.isDisposed()) {
+ fHoverList.select(0);
+ handleHoverListSelection();
+ }
+ }
+ });
+ fShowHoverAffordanceCheckbox
+ .setSelection(fStore
+ .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
+ }
+
+ void performOk() {
+ StringBuffer buf = new StringBuffer();
+ StringBuffer maskBuf = new StringBuffer();
+ for (int i = 0; i < fHoverConfigs.length; i++) {
+ buf.append(getContributedHovers()[i].getId());
+ buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
+ if (!fHoverConfigs[i].fIsEnabled)
+ buf.append(JavaEditorTextHoverDescriptor.DISABLED_TAG);
+ String modifier = fHoverConfigs[i].fModifierString;
+ if (modifier == null || modifier.length() == 0)
+ modifier = JavaEditorTextHoverDescriptor.NO_MODIFIER;
+ buf.append(modifier);
+ buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
+
+ maskBuf.append(getContributedHovers()[i].getId());
+ maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
+ maskBuf.append(fHoverConfigs[i].fStateMask);
+ maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
+ }
+ fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS, buf
+ .toString());
+ fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS,
+ maskBuf.toString());
+
+ fStore.setValue(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE,
+ fShowHoverAffordanceCheckbox.getSelection());
+
+ WebUI.getDefault().resetJavaEditorTextHoverDescriptors();
+ }
+
+ void performDefaults() {
+ restoreFromPreferences();
+ initializeFields();
+ }
+
+ private void restoreFromPreferences() {
+
+ fShowHoverAffordanceCheckbox
+ .setSelection(fStore
+ .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
+
+ String compiledTextHoverModifiers = fStore
+ .getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
+
+ StringTokenizer tokenizer = new StringTokenizer(
+ compiledTextHoverModifiers,
+ JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
+ HashMap idToModifier = new HashMap(tokenizer.countTokens() / 2);
+
+ while (tokenizer.hasMoreTokens()) {
+ String id = tokenizer.nextToken();
+ if (tokenizer.hasMoreTokens())
+ idToModifier.put(id, tokenizer.nextToken());
+ }
+
+ String compiledTextHoverModifierMasks = WebUI.getDefault()
+ .getPreferenceStore().getString(
+ PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
+
+ tokenizer = new StringTokenizer(compiledTextHoverModifierMasks,
+ JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
+ HashMap idToModifierMask = new HashMap(tokenizer.countTokens() / 2);
+
+ while (tokenizer.hasMoreTokens()) {
+ String id = tokenizer.nextToken();
+ if (tokenizer.hasMoreTokens())
+ idToModifierMask.put(id, tokenizer.nextToken());
+ }
+
+ for (int i = 0; i < fHoverConfigs.length; i++) {
+ String modifierString = (String) idToModifier
+ .get(getContributedHovers()[i].getId());
+ boolean enabled = true;
+ if (modifierString == null)
+ modifierString = JavaEditorTextHoverDescriptor.DISABLED_TAG;
+
+ if (modifierString
+ .startsWith(JavaEditorTextHoverDescriptor.DISABLED_TAG)) {
+ enabled = false;
+ modifierString = modifierString.substring(1);
+ }
+
+ if (modifierString
+ .equals(JavaEditorTextHoverDescriptor.NO_MODIFIER))
+ modifierString = ""; //$NON-NLS-1$
+
+ fHoverConfigs[i].fModifierString = modifierString;
+ fHoverConfigs[i].fIsEnabled = enabled;
+ fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
+ .computeStateMask(modifierString);
+
+ if (fHoverConfigs[i].fStateMask == -1) {
+ try {
+ fHoverConfigs[i].fStateMask = Integer
+ .parseInt((String) idToModifierMask
+ .get(getContributedHovers()[i].getId()));
+ } catch (NumberFormatException ex) {
+ fHoverConfigs[i].fStateMask = -1;
+ }
+ }
+ }
+ }
+
+ private void handleModifierModified() {
+ int i = fHoverList.getSelectionIndex();
+ String modifiers = fModifierEditor.getText();
+ fHoverConfigs[i].fModifierString = modifiers;
+ fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
+ .computeStateMask(modifiers);
+ if (fHoverConfigs[i].fIsEnabled && fHoverConfigs[i].fStateMask == -1)
+ fStatus = new StatusInfo(
+ IStatus.ERROR,
+ PreferencesMessages
+ .getFormattedString(
+ "JavaEditorHoverConfigurationBlock.modifierIsNotValid", fHoverConfigs[i].fModifierString)); //$NON-NLS-1$
+ else
+ fStatus = new StatusInfo();
+ updateStatus();
+ }
+
+ private void handleHoverListSelection() {
+ int i = fHoverList.getSelectionIndex();
+ boolean enabled = fHoverConfigs[i].fIsEnabled;
+ fEnableField.setSelection(enabled);
+ fModifierEditor.setEnabled(enabled);
+ fModifierEditor.setText(fHoverConfigs[i].fModifierString);
+ String description = getContributedHovers()[i].getDescription();
+ if (description == null)
+ description = ""; //$NON-NLS-1$
+ fDescription.setText(description);
+ }
+
+ IStatus getStatus() {
+ if (fStatus == null)
+ fStatus = new StatusInfo();
+ return fStatus;
+ }
+
+ private void updateStatus() {
+ int i = 0;
+ HashMap stateMasks = new HashMap(fHoverConfigs.length);
+ while (fStatus.isOK() && i < fHoverConfigs.length) {
+ if (fHoverConfigs[i].fIsEnabled) {
+ String label = getContributedHovers()[i].getLabel();
+ Integer stateMask = new Integer(fHoverConfigs[i].fStateMask);
+ if (fHoverConfigs[i].fStateMask == -1)
+ fStatus = new StatusInfo(
+ IStatus.ERROR,
+ PreferencesMessages
+ .getFormattedString(
+ "JavaEditorHoverConfigurationBlock.modifierIsNotValidForHover", new String[] { fHoverConfigs[i].fModifierString, label })); //$NON-NLS-1$
+ else if (stateMasks.containsKey(stateMask))
+ fStatus = new StatusInfo(
+ IStatus.ERROR,
+ PreferencesMessages
+ .getFormattedString(
+ "JavaEditorHoverConfigurationBlock.duplicateModifier", new String[] { label, (String) stateMasks.get(stateMask) })); //$NON-NLS-1$
+ else
+ stateMasks.put(stateMask, label);
+ }
+ i++;
+ }
+
+ if (fStatus.isOK())
+ fMainPreferencePage.updateStatus(fStatus);
+ else {
+ fMainPreferencePage.setValid(false);
+ StatusUtil.applyToStatusLine(fMainPreferencePage, fStatus);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaEditorPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaEditorPreferencePage.java
new file mode 100644
index 0000000..baa56e2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaEditorPreferencePage.java
@@ -0,0 +1,2050 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter;
+import net.sourceforge.phpdt.internal.ui.util.TabFolderLayout;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.EditorUtility;
+import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
+import net.sourceforge.phpeclipse.preferences.ColorEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.preference.PreferencePage;
+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.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+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.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+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.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
+
+
+/**
+ * The page for setting the editor options.
+ */
+public class JavaEditorPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage {
+ private static final String BOLD = PreferenceConstants.EDITOR_BOLD_SUFFIX;
+
+ private static final String COMPILER_TASK_TAGS = JavaCore.COMPILER_TASK_TAGS;
+
+ private static final String DELIMITER = PreferencesMessages
+ .getString("JavaEditorPreferencePage.navigation.delimiter"); //$NON-NLS-1$
+
+ /** The keys of the overlay store. */
+ public final OverlayPreferenceStore.OverlayKey[] fKeys;
+
+ private final String[][] fSyntaxColorListModel = new String[][] {
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.multiLineComment"),
+ PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.singleLineComment"),
+ PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_COLOR },
+ //$NON-NLS-1$
+ { PreferencesMessages.getString("JavaEditorPreferencePage.tags"),
+ PreferenceConstants.EDITOR_PHP_TAG_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.keywords"),
+ PreferenceConstants.EDITOR_JAVA_KEYWORD_COLOR },
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.functionNames"),
+ PreferenceConstants.EDITOR_PHP_FUNCTIONNAME_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.variables"),
+ PreferenceConstants.EDITOR_PHP_VARIABLE_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.variables_dollar"),
+ PreferenceConstants.EDITOR_PHP_VARIABLE_DOLLAR_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.constants"),
+ PreferenceConstants.EDITOR_PHP_CONSTANT_COLOR },
+ //$NON-NLS-1$
+ { PreferencesMessages.getString("JavaEditorPreferencePage.types"),
+ PreferenceConstants.EDITOR_PHP_TYPE_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.strings_dq"),
+ PreferenceConstants.EDITOR_STRING_COLOR_DQ },
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.strings_sq"),
+ PreferenceConstants.EDITOR_STRING_COLOR_SQ },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.others"), PreferenceConstants.EDITOR_JAVA_DEFAULT_COLOR }, //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.operators"),
+ PreferenceConstants.EDITOR_PHP_OPERATOR_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.returnKeyword"),
+ PreferenceConstants.EDITOR_PHP_KEYWORD_RETURN_COLOR },
+ { PreferencesMessages.getString("JavaEditorPreferencePage.braces"),
+ PreferenceConstants.EDITOR_PHP_BRACE_OPERATOR_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.phpDocKeywords"),
+ PreferenceConstants.EDITOR_JAVADOC_KEYWORD_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.phpDocHtmlTags"),
+ PreferenceConstants.EDITOR_JAVADOC_TAG_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.phpDocLinks"),
+ PreferenceConstants.EDITOR_JAVADOC_LINKS_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.phpDocOthers"), PreferenceConstants.EDITOR_JAVADOC_DEFAULT_COLOR } //$NON-NLS-1$
+ };
+
+ private final String[][] fAppearanceColorListModel = new String[][] {
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.matchingBracketsHighlightColor2"),
+ PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.currentLineHighlighColor"),
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.printMarginColor2"),
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.findScopeColor2"),
+ PreferenceConstants.EDITOR_FIND_SCOPE_COLOR },
+ //$NON-NLS-1$
+ {
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.linkColor2"), PreferenceConstants.EDITOR_LINK_COLOR }, //$NON-NLS-1$
+ };
+
+ // private final String[][] fAnnotationColorListModel;
+
+ // private final String[][] fAnnotationDecorationListModel = new String[][]{
+ // {
+ // PreferencesMessages
+ // .getString("JavaEditorPreferencePage.AnnotationDecoration.NONE"),
+ // AnnotationPreference.STYLE_NONE},
+ // //$NON-NLS-1$
+ // {
+ // PreferencesMessages
+ // .getString("JavaEditorPreferencePage.AnnotationDecoration.SQUIGGLIES"),
+ // AnnotationPreference.STYLE_SQUIGGLIES},
+ // //$NON-NLS-1$
+ // {
+ // PreferencesMessages
+ // .getString("JavaEditorPreferencePage.AnnotationDecoration.UNDERLINE"),
+ // AnnotationPreference.STYLE_UNDERLINE},
+ // //$NON-NLS-1$
+ // {
+ // PreferencesMessages
+ // .getString("JavaEditorPreferencePage.AnnotationDecoration.BOX"),
+ // AnnotationPreference.STYLE_BOX},
+ // //$NON-NLS-1$
+ // {
+ // PreferencesMessages
+ // .getString("JavaEditorPreferencePage.AnnotationDecoration.IBEAM"),
+ // AnnotationPreference.STYLE_IBEAM} //$NON-NLS-1$
+ // };
+ private OverlayPreferenceStore fOverlayStore;
+
+ private JavaTextTools fJavaTextTools;
+
+ private JavaEditorHoverConfigurationBlock fJavaEditorHoverConfigurationBlock;
+
+ private FoldingConfigurationBlock fFoldingConfigurationBlock;
+
+ private Map fColorButtons = new HashMap();
+
+ private Map fCheckBoxes = new HashMap();
+
+ private SelectionListener fCheckBoxListener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ Button button = (Button) e.widget;
+ fOverlayStore.setValue((String) fCheckBoxes.get(button), button
+ .getSelection());
+ }
+ };
+
+ private Map fTextFields = new HashMap();
+
+ private ModifyListener fTextFieldListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ Text text = (Text) e.widget;
+ fOverlayStore.setValue((String) fTextFields.get(text), text
+ .getText());
+ }
+ };
+
+ private ArrayList fNumberFields = new ArrayList();
+
+ private ModifyListener fNumberFieldListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ numberFieldChanged((Text) e.widget);
+ }
+ };
+
+ private List fSyntaxColorList;
+
+ private List fAppearanceColorList;
+
+ // private List fContentAssistColorList;
+ private List fAnnotationList;
+
+ private ColorEditor fSyntaxForegroundColorEditor;
+
+ private ColorEditor fAppearanceColorEditor;
+
+ private ColorEditor fAnnotationForegroundColorEditor;
+
+ private ColorEditor fContentAssistColorEditor;
+
+ private ColorEditor fBackgroundColorEditor;
+
+ private Button fBackgroundDefaultRadioButton;
+
+ private Button fBackgroundCustomRadioButton;
+
+ private Button fBackgroundColorButton;
+
+ private Button fBoldCheckBox;
+
+ // private Button fAddJavaDocTagsButton;
+
+ private Button fEscapeStringsButtonDQ;
+
+ private Button fEscapeStringsButtonSQ;
+
+ // private Button fGuessMethodArgumentsButton;
+ private SourceViewer fPreviewViewer;
+
+ private Color fBackgroundColor;
+
+ private Control fAutoInsertDelayText;
+
+ private Control fAutoInsertJavaTriggerText;
+
+ private Control fAutoInsertJavaDocTriggerText;
+
+ private Label fAutoInsertDelayLabel;
+
+ private Label fAutoInsertJavaTriggerLabel;
+
+ private Label fAutoInsertJavaDocTriggerLabel;
+
+ private Button fShowInTextCheckBox;
+
+ private Combo fDecorationStyleCombo;
+
+ private Button fHighlightInTextCheckBox;
+
+ private Button fShowInOverviewRulerCheckBox;
+
+ private Button fShowInVerticalRulerCheckBox;
+
+ private Text fBrowserLikeLinksKeyModifierText;
+
+ private Button fBrowserLikeLinksCheckBox;
+
+ private StatusInfo fBrowserLikeLinksKeyModifierStatus;
+
+ // private Button fCompletionInsertsRadioButton;
+ // private Button fCompletionOverwritesRadioButton;
+ // private Button fStickyOccurrencesButton;
+ /**
+ * Creates a new preference page.
+ */
+ public JavaEditorPreferencePage() {
+ setDescription(PreferencesMessages
+ .getString("JavaEditorPreferencePage.description")); //$NON-NLS-1$
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+ MarkerAnnotationPreferences markerAnnotationPreferences = new MarkerAnnotationPreferences();
+ fKeys = createOverlayStoreKeys(markerAnnotationPreferences);
+ fOverlayStore = new OverlayPreferenceStore(getPreferenceStore(), fKeys);
+ // fAnnotationColorListModel =
+ // createAnnotationTypeListModel(markerAnnotationPreferences);
+ }
+
+ private OverlayPreferenceStore.OverlayKey[] createOverlayStoreKeys(
+ MarkerAnnotationPreferences preferences) {
+ ArrayList overlayKeys = new ArrayList();
+ Iterator e = preferences.getAnnotationPreferences().iterator();
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_FOREGROUND_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_FOREGROUND_DEFAULT_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_BACKGROUND_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_BACKGROUND_DEFAULT_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.INT,
+ PreferenceConstants.EDITOR_TAB_WIDTH));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_JAVA_KEYWORD_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_JAVA_KEYWORD_BOLD));
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_TAG_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_TAG_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_FUNCTIONNAME_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_FUNCTIONNAME_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_VARIABLE_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_VARIABLE_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_VARIABLE_DOLLAR_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_VARIABLE_DOLLAR_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_CONSTANT_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_CONSTANT_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_TYPE_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_TYPE_BOLD));
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_STRING_COLOR_DQ));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_STRING_BOLD_DQ));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_STRING_COLOR_SQ));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_STRING_BOLD_SQ));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_JAVA_DEFAULT_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_JAVA_DEFAULT_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_TASK_TAG_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_TASK_TAG_BOLD));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING_DQ,
+ // PreferenceConstants.EDITOR_JAVA_METHOD_NAME_COLOR));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_JAVA_METHOD_NAME_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_OPERATOR_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_OPERATOR_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_KEYWORD_RETURN_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_KEYWORD_RETURN_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_PHP_BRACE_OPERATOR_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_PHP_BRACE_OPERATOR_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_JAVADOC_KEYWORD_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_JAVADOC_KEYWORD_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_JAVADOC_TAG_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_JAVADOC_TAG_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_JAVADOC_LINKS_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_JAVADOC_LINKS_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_JAVADOC_DEFAULT_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_JAVADOC_DEFAULT_BOLD));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_MATCHING_BRACKETS));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.INT,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_STICKY_OCCURRENCES));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_FIND_SCOPE_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_LINK_COLOR));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_CORRECTION_INDICATION));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_EVALUTE_TEMPORARY_PROBLEMS));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_OVERVIEW_RULER));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_SPACES_FOR_TABS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.INT,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_AUTOINSERT));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PARAMETERS_BACKGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_PARAMETERS_FOREGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_REPLACEMENT_BACKGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_REPLACEMENT_FOREGROUND));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_ORDER_PROPOSALS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_CASE_SENSITIVITY));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_ADDIMPORT));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_INSERT_COMPLETION));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_SMART_PASTE));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_CLOSE_STRINGS_DQ_PHP));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_CLOSE_STRINGS_SQ_PHP));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP));
+ // overlayKeys
+ // .add(new OverlayPreferenceStore.OverlayKey(
+ // OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_CLOSE_BRACES));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_CLOSE_JAVADOCS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_WRAP_WORDS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_WRAP_STRINGS_DQ));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_ESCAPE_STRINGS_DQ));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_WRAP_STRINGS_SQ));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_ESCAPE_STRINGS_SQ));
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_FORMAT_JAVADOCS));
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_SMART_HOME_END));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING,
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK));
+ while (e.hasNext()) {
+ AnnotationPreference info = (AnnotationPreference) e.next();
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING, info
+ .getColorPreferenceKey()));
+ overlayKeys
+ .add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN, info
+ .getTextPreferenceKey()));
+ if (info.getHighlightPreferenceKey() != null)
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN, info
+ .getHighlightPreferenceKey()));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN, info
+ .getOverviewRulerPreferenceKey()));
+ if (info.getVerticalRulerPreferenceKey() != null)
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN, info
+ .getVerticalRulerPreferenceKey()));
+ if (info.getTextStylePreferenceKey() != null)
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.STRING, info
+ .getTextStylePreferenceKey()));
+ }
+ OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys
+ .size()];
+ overlayKeys.toArray(keys);
+ return keys;
+ } /*
+ * @see IWorkbenchPreferencePage#init()
+ */
+
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * @see PreferencePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.JAVA_EDITOR_PREFERENCE_PAGE);
+ }
+
+ private void handleSyntaxColorListSelection() {
+ int i = fSyntaxColorList.getSelectionIndex();
+ String key = fSyntaxColorListModel[i][1];
+ RGB rgb = PreferenceConverter.getColor(fOverlayStore, key);
+ fSyntaxForegroundColorEditor.setColorValue(rgb);
+ fBoldCheckBox.setSelection(fOverlayStore.getBoolean(key + BOLD));
+ }
+
+ private void handleAppearanceColorListSelection() {
+ int i = fAppearanceColorList.getSelectionIndex();
+ String key = fAppearanceColorListModel[i][1];
+ RGB rgb = PreferenceConverter.getColor(fOverlayStore, key);
+ fAppearanceColorEditor.setColorValue(rgb);
+ }
+
+ // private void handleAnnotationListSelection() {
+ // int i = fAnnotationList.getSelectionIndex();
+ // String key = fAnnotationColorListModel[i][1];
+ // RGB rgb = PreferenceConverter.getColor(fOverlayStore, key);
+ // fAnnotationForegroundColorEditor.setColorValue(rgb);
+ // key = fAnnotationColorListModel[i][2];
+ // boolean showInText = fOverlayStore.getBoolean(key);
+ // fShowInTextCheckBox.setSelection(showInText);
+ // key = fAnnotationColorListModel[i][6];
+ // if (key != null) {
+ // fDecorationStyleCombo.setEnabled(showInText);
+ // for (int j = 0; j < fAnnotationDecorationListModel.length; j++) {
+ // String value = fOverlayStore.getString(key);
+ // if (fAnnotationDecorationListModel[j][1].equals(value)) {
+ // fDecorationStyleCombo.setText(fAnnotationDecorationListModel[j][0]);
+ // break;
+ // }
+ // }
+ // } else {
+ // fDecorationStyleCombo.setEnabled(false);
+ // fDecorationStyleCombo.setText(fAnnotationDecorationListModel[1][0]); //
+ // set
+ // // selection
+ // // to
+ // // squigglies
+ // // if
+ // // the
+ // // key
+ // // is
+ // // not
+ // // there
+ // // (legacy
+ // // support)
+ // }
+ // key = fAnnotationColorListModel[i][3];
+ // fShowInOverviewRulerCheckBox.setSelection(fOverlayStore.getBoolean(key));
+ // key = fAnnotationColorListModel[i][4];
+ // if (key != null) {
+ // fHighlightInTextCheckBox.setSelection(fOverlayStore.getBoolean(key));
+ // fHighlightInTextCheckBox.setEnabled(true);
+ // } else
+ // fHighlightInTextCheckBox.setEnabled(false);
+ // key = fAnnotationColorListModel[i][5];
+ // if (key != null) {
+ // fShowInVerticalRulerCheckBox.setSelection(fOverlayStore.getBoolean(key));
+ // fShowInVerticalRulerCheckBox.setEnabled(true);
+ // } else {
+ // fShowInVerticalRulerCheckBox.setSelection(true);
+ // fShowInVerticalRulerCheckBox.setEnabled(false);
+ // }
+ // }
+ private Control createSyntaxPage(Composite parent) {
+ Composite colorComposite = new Composite(parent, SWT.NULL);
+ colorComposite.setLayout(new GridLayout());
+ Group backgroundComposite = new Group(colorComposite,
+ SWT.SHADOW_ETCHED_IN);
+ backgroundComposite.setLayout(new RowLayout());
+ backgroundComposite.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.backgroundColor"));//$NON-NLS-1$
+ SelectionListener backgroundSelectionListener = new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean custom = fBackgroundCustomRadioButton.getSelection();
+ fBackgroundColorButton.setEnabled(custom);
+ fOverlayStore.setValue(
+ PreferenceConstants.EDITOR_BACKGROUND_DEFAULT_COLOR,
+ !custom);
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ };
+ fBackgroundDefaultRadioButton = new Button(backgroundComposite,
+ SWT.RADIO | SWT.LEFT);
+ fBackgroundDefaultRadioButton.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.systemDefault")); //$NON-NLS-1$
+ fBackgroundDefaultRadioButton
+ .addSelectionListener(backgroundSelectionListener);
+ fBackgroundCustomRadioButton = new Button(backgroundComposite,
+ SWT.RADIO | SWT.LEFT);
+ fBackgroundCustomRadioButton.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.custom")); //$NON-NLS-1$
+ fBackgroundCustomRadioButton
+ .addSelectionListener(backgroundSelectionListener);
+ fBackgroundColorEditor = new ColorEditor(backgroundComposite);
+ fBackgroundColorButton = fBackgroundColorEditor.getButton();
+ Label label = new Label(colorComposite, SWT.LEFT);
+ label.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.foreground")); //$NON-NLS-1$
+ label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ Composite editorComposite = new Composite(colorComposite, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ editorComposite.setLayoutData(gd);
+ fSyntaxColorList = new List(editorComposite, SWT.SINGLE | SWT.V_SCROLL
+ | SWT.BORDER);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = convertHeightInCharsToPixels(5);
+ fSyntaxColorList.setLayoutData(gd);
+ Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ label = new Label(stylesComposite, SWT.LEFT);
+ label.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.color")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gd);
+ fSyntaxForegroundColorEditor = new ColorEditor(stylesComposite);
+ Button foregroundColorButton = fSyntaxForegroundColorEditor.getButton();
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ foregroundColorButton.setLayoutData(gd);
+ fBoldCheckBox = new Button(stylesComposite, SWT.CHECK);
+ fBoldCheckBox.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.bold")); //$NON-NLS-1$
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ gd.horizontalSpan = 2;
+ fBoldCheckBox.setLayoutData(gd);
+ label = new Label(colorComposite, SWT.LEFT);
+ label.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.preview")); //$NON-NLS-1$
+ label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ Control previewer = createPreviewer(colorComposite);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = convertWidthInCharsToPixels(20);
+ gd.heightHint = convertHeightInCharsToPixels(5);
+ previewer.setLayoutData(gd);
+ fSyntaxColorList.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ handleSyntaxColorListSelection();
+ }
+ });
+ foregroundColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ int i = fSyntaxColorList.getSelectionIndex();
+ String key = fSyntaxColorListModel[i][1];
+ PreferenceConverter.setValue(fOverlayStore, key,
+ fSyntaxForegroundColorEditor.getColorValue());
+ }
+ });
+ fBackgroundColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ PreferenceConverter.setValue(fOverlayStore,
+ PreferenceConstants.EDITOR_BACKGROUND_COLOR,
+ fBackgroundColorEditor.getColorValue());
+ }
+ });
+ fBoldCheckBox.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ int i = fSyntaxColorList.getSelectionIndex();
+ String key = fSyntaxColorListModel[i][1];
+ fOverlayStore
+ .setValue(key + BOLD, fBoldCheckBox.getSelection());
+ }
+ });
+ return colorComposite;
+ }
+
+ private Control createPreviewer(Composite parent) {
+ Preferences coreStore = createTemporaryCorePreferenceStore();
+ fJavaTextTools = new JavaTextTools(fOverlayStore, coreStore, false);
+ IPreferenceStore generalTextStore = EditorsUI.getPreferenceStore();
+ IPreferenceStore store = new ChainedPreferenceStore(
+ new IPreferenceStore[] {
+ fOverlayStore,
+ new PreferencesAdapter(
+ createTemporaryCorePreferenceStore()),
+ generalTextStore });
+
+ fPreviewViewer = new JavaSourceViewer(parent, null, null, false,
+ SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER, store);
+ JavaTextTools tools = WebUI.getDefault().getJavaTextTools();
+ PHPSourceViewerConfiguration configuration = new PHPSourceViewerConfiguration(
+ tools.getColorManager(), store, null,
+ IPHPPartitions.PHP_PARTITIONING);
+ // PHPSourceViewerConfiguration configuration =new
+ // PHPSourceViewerConfiguration(fJavaTextTools, null,
+ // IPHPPartitions.PHP_PARTITIONING);
+ fPreviewViewer.configure(configuration);
+
+ Font font = JFaceResources
+ .getFont(PreferenceConstants.EDITOR_TEXT_FONT);
+ fPreviewViewer.getTextWidget().setFont(font);
+ new JavaSourcePreviewerUpdater(fPreviewViewer, configuration, store);
+ fPreviewViewer.setEditable(false);
+ String content = loadPreviewContentFromFile("ColorSettingPreviewCode.txt"); //$NON-NLS-1$
+ IDocument document = new Document(content);
+ fJavaTextTools.setupJavaDocumentPartitioner(document,
+ IPHPPartitions.PHP_PARTITIONING);
+ fPreviewViewer.setDocument(document);
+ return fPreviewViewer.getControl();
+ }
+
+ private Preferences createTemporaryCorePreferenceStore() {
+ Preferences result = new Preferences();
+ result.setValue(COMPILER_TASK_TAGS, "TASK"); //$NON-NLS-1$
+ return result;
+ }
+
+ private Control createAppearancePage(Composite parent) {
+ Composite appearanceComposite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ appearanceComposite.setLayout(layout);
+
+ // Inserts a hyper-link to the General Editor preferences page
+ // TODO Can probably be removed post 1.5.0?
+ String label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.appearanceTabLink");
+ Link link = new Link(appearanceComposite, SWT.NONE);
+ GridData gridPosition = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gridPosition.horizontalSpan = 2;
+ link.setLayoutData(gridPosition);
+
+ link.setText(label);
+ link.addListener(SWT.Selection, new Listener () {
+ public void handleEvent(Event event) {
+ String u = event.text;
+ PreferencesUtil.createPreferenceDialogOn(getShell(), u, null, null);
+ }
+ });
+ String tooltip = PreferencesMessages
+ .getString("JavaEditorPreferencePage.appearanceTabTooltip");
+ link.setToolTipText(tooltip);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.displayedTabWidth"); //$NON-NLS-1$
+ addTextField(appearanceComposite, label,
+ PreferenceConstants.EDITOR_TAB_WIDTH, 3, 0, true);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.printMarginColumn"); //$NON-NLS-1$
+ addTextField(
+ appearanceComposite,
+ label,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN,
+ 3, 0, true);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.showOverviewRuler"); //$NON-NLS-1$
+ addCheckBox(
+ appearanceComposite,
+ label,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_OVERVIEW_RULER,
+ 0);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.highlightMatchingBrackets"); //$NON-NLS-1$
+ addCheckBox(appearanceComposite, label,
+ PreferenceConstants.EDITOR_MATCHING_BRACKETS, 0);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.highlightCurrentLine"); //$NON-NLS-1$
+ addCheckBox(
+ appearanceComposite,
+ label,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE,
+ 0);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.showPrintMargin"); //$NON-NLS-1$
+ addCheckBox(
+ appearanceComposite,
+ label,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN,
+ 0);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.markOccurrences"); //$NON-NLS-1$
+ // Button master= addCheckBox(appearanceComposite, label,
+ // PreferenceConstants.EDITOR_MARK_OCCURRENCES, 0); //$NON-NLS-1$
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.stickyOccurrences"); //$NON-NLS-1$
+ // fStickyOccurrencesButton= addCheckBox(appearanceComposite, label,
+ // PreferenceConstants.EDITOR_STICKY_OCCURRENCES, 0); //$NON-NLS-1$
+ // createDependency(master, fStickyOccurrencesButton);
+ Label l = new Label(appearanceComposite, SWT.LEFT);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ gd.heightHint = convertHeightInCharsToPixels(1) / 2;
+ l.setLayoutData(gd);
+ l = new Label(appearanceComposite, SWT.LEFT);
+ l.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.appearanceOptions")); //$NON-NLS-1$
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ l.setLayoutData(gd);
+ Composite editorComposite = new Composite(appearanceComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.FILL_VERTICAL);
+ gd.horizontalSpan = 2;
+ editorComposite.setLayoutData(gd);
+ fAppearanceColorList = new List(editorComposite, SWT.SINGLE
+ | SWT.V_SCROLL | SWT.BORDER);
+ gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
+ | GridData.FILL_HORIZONTAL);
+ gd.heightHint = convertHeightInCharsToPixels(8);
+ fAppearanceColorList.setLayoutData(gd);
+ Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ l = new Label(stylesComposite, SWT.LEFT);
+ l.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.color")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.BEGINNING;
+ l.setLayoutData(gd);
+ fAppearanceColorEditor = new ColorEditor(stylesComposite);
+ Button foregroundColorButton = fAppearanceColorEditor.getButton();
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ foregroundColorButton.setLayoutData(gd);
+ fAppearanceColorList.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ handleAppearanceColorListSelection();
+ }
+ });
+ foregroundColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ int i = fAppearanceColorList.getSelectionIndex();
+ String key = fAppearanceColorListModel[i][1];
+ PreferenceConverter.setValue(fOverlayStore, key,
+ fAppearanceColorEditor.getColorValue());
+ }
+ });
+ return appearanceComposite;
+ }
+
+ // private Control createAnnotationsPage(Composite parent) {
+ // Composite composite = new Composite(parent, SWT.NULL);
+ // GridLayout layout = new GridLayout();
+ // layout.numColumns = 2;
+ // composite.setLayout(layout);
+ // String text = PreferencesMessages
+ // .getString("JavaEditorPreferencePage.analyseAnnotationsWhileTyping");
+ // //$NON-NLS-1$
+ // addCheckBox(composite, text,
+ // PreferenceConstants.EDITOR_EVALUTE_TEMPORARY_PROBLEMS, 0);
+ // text = PreferencesMessages
+ // .getString("JavaEditorPreferencePage.showQuickFixables"); //$NON-NLS-1$
+ // addCheckBox(composite, text,
+ // PreferenceConstants.EDITOR_CORRECTION_INDICATION, 0);
+ // addFiller(composite);
+ // Label label = new Label(composite, SWT.LEFT);
+ // label.setText(PreferencesMessages
+ // .getString("JavaEditorPreferencePage.annotationPresentationOptions"));
+ // //$NON-NLS-1$
+ // GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ // gd.horizontalSpan = 2;
+ // label.setLayoutData(gd);
+ // Composite editorComposite = new Composite(composite, SWT.NONE);
+ // layout = new GridLayout();
+ // layout.numColumns = 2;
+ // layout.marginHeight = 0;
+ // layout.marginWidth = 0;
+ // editorComposite.setLayout(layout);
+ // gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL |
+ // GridData.FILL_VERTICAL);
+ // gd.horizontalSpan = 2;
+ // editorComposite.setLayoutData(gd);
+ // fAnnotationList = new List(editorComposite, SWT.SINGLE | SWT.V_SCROLL
+ // | SWT.BORDER);
+ // gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
+ // | GridData.FILL_HORIZONTAL);
+ // gd.heightHint = convertHeightInCharsToPixels(10);
+ // fAnnotationList.setLayoutData(gd);
+ // Composite optionsComposite = new Composite(editorComposite, SWT.NONE);
+ // layout = new GridLayout();
+ // layout.marginHeight = 0;
+ // layout.marginWidth = 0;
+ // layout.numColumns = 2;
+ // optionsComposite.setLayout(layout);
+ // optionsComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ // fShowInTextCheckBox = new Button(optionsComposite, SWT.CHECK);
+ // fShowInTextCheckBox.setText(PreferencesMessages
+ // .getString("JavaEditorPreferencePage.annotations.showInText"));
+ // //$NON-NLS-1$
+ // gd = new GridData(GridData.FILL_HORIZONTAL);
+ // gd.horizontalAlignment = GridData.BEGINNING;
+ // gd.horizontalSpan = 2;
+ // fShowInTextCheckBox.setLayoutData(gd);
+ // fDecorationStyleCombo = new Combo(optionsComposite, SWT.READ_ONLY);
+ // for (int i = 0; i < fAnnotationDecorationListModel.length; i++)
+ // fDecorationStyleCombo.add(fAnnotationDecorationListModel[i][0]);
+ // gd = new GridData(GridData.FILL_HORIZONTAL);
+ // gd.horizontalAlignment = GridData.BEGINNING;
+ // gd.horizontalSpan = 2;
+ // gd.horizontalIndent = 20;
+ // fDecorationStyleCombo.setLayoutData(gd);
+ // fHighlightInTextCheckBox = new Button(optionsComposite, SWT.CHECK);
+ // fHighlightInTextCheckBox.setText(PreferencesMessages
+ // .getString("TextEditorPreferencePage.annotations.highlightInText"));
+ // //$NON-NLS-1$
+ // gd = new GridData(GridData.FILL_HORIZONTAL);
+ // gd.horizontalAlignment = GridData.BEGINNING;
+ // gd.horizontalSpan = 2;
+ // fHighlightInTextCheckBox.setLayoutData(gd);
+ // fShowInOverviewRulerCheckBox = new Button(optionsComposite, SWT.CHECK);
+ // fShowInOverviewRulerCheckBox.setText(PreferencesMessages
+ // .getString("JavaEditorPreferencePage.annotations.showInOverviewRuler"));
+ // //$NON-NLS-1$
+ // gd = new GridData(GridData.FILL_HORIZONTAL);
+ // gd.horizontalAlignment = GridData.BEGINNING;
+ // gd.horizontalSpan = 2;
+ // fShowInOverviewRulerCheckBox.setLayoutData(gd);
+ // fShowInVerticalRulerCheckBox = new Button(optionsComposite, SWT.CHECK);
+ // fShowInVerticalRulerCheckBox.setText(PreferencesMessages
+ // .getString("JavaEditorPreferencePage.annotations.showInVerticalRuler"));
+ // //$NON-NLS-1$
+ // gd = new GridData(GridData.FILL_HORIZONTAL);
+ // gd.horizontalAlignment = GridData.BEGINNING;
+ // gd.horizontalSpan = 2;
+ // fShowInVerticalRulerCheckBox.setLayoutData(gd);
+ // label = new Label(optionsComposite, SWT.LEFT);
+ // label.setText(PreferencesMessages
+ // .getString("JavaEditorPreferencePage.annotations.color")); //$NON-NLS-1$
+ // gd = new GridData();
+ // gd.horizontalAlignment = GridData.BEGINNING;
+ // label.setLayoutData(gd);
+ // fAnnotationForegroundColorEditor = new ColorEditor(optionsComposite);
+ // Button foregroundColorButton =
+ // fAnnotationForegroundColorEditor.getButton();
+ // gd = new GridData(GridData.FILL_HORIZONTAL);
+ // gd.horizontalAlignment = GridData.BEGINNING;
+ // foregroundColorButton.setLayoutData(gd);
+ // fAnnotationList.addSelectionListener(new SelectionListener() {
+ // public void widgetDefaultSelected(SelectionEvent e) {
+ // // do nothing
+ // }
+ // public void widgetSelected(SelectionEvent e) {
+ // handleAnnotationListSelection();
+ // }
+ // });
+ // fShowInTextCheckBox.addSelectionListener(new SelectionListener() {
+ // public void widgetDefaultSelected(SelectionEvent e) {
+ // // do nothing
+ // }
+ // public void widgetSelected(SelectionEvent e) {
+ // int i = fAnnotationList.getSelectionIndex();
+ // String key = fAnnotationColorListModel[i][2];
+ // fOverlayStore.setValue(key, fShowInTextCheckBox.getSelection());
+ // String decorationKey = fAnnotationColorListModel[i][6];
+ // fDecorationStyleCombo.setEnabled(decorationKey != null
+ // && fShowInTextCheckBox.getSelection());
+ // }
+ // });
+ // fHighlightInTextCheckBox.addSelectionListener(new SelectionListener() {
+ // public void widgetDefaultSelected(SelectionEvent e) {
+ // // do nothing
+ // }
+ // public void widgetSelected(SelectionEvent e) {
+ // int i = fAnnotationList.getSelectionIndex();
+ // String key = fAnnotationColorListModel[i][4];
+ // fOverlayStore.setValue(key, fHighlightInTextCheckBox.getSelection());
+ // }
+ // });
+ // fShowInOverviewRulerCheckBox.addSelectionListener(new SelectionListener()
+ // {
+ // public void widgetDefaultSelected(SelectionEvent e) {
+ // // do nothing
+ // }
+ // public void widgetSelected(SelectionEvent e) {
+ // int i = fAnnotationList.getSelectionIndex();
+ // String key = fAnnotationColorListModel[i][3];
+ // fOverlayStore
+ // .setValue(key, fShowInOverviewRulerCheckBox.getSelection());
+ // }
+ // });
+ // fShowInVerticalRulerCheckBox.addSelectionListener(new SelectionListener()
+ // {
+ // public void widgetDefaultSelected(SelectionEvent e) {
+ // // do nothing
+ // }
+ // public void widgetSelected(SelectionEvent e) {
+ // int i = fAnnotationList.getSelectionIndex();
+ // String key = fAnnotationColorListModel[i][5];
+ // fOverlayStore
+ // .setValue(key, fShowInVerticalRulerCheckBox.getSelection());
+ // }
+ // });
+ // foregroundColorButton.addSelectionListener(new SelectionListener() {
+ // public void widgetDefaultSelected(SelectionEvent e) {
+ // // do nothing
+ // }
+ // public void widgetSelected(SelectionEvent e) {
+ // int i = fAnnotationList.getSelectionIndex();
+ // String key = fAnnotationColorListModel[i][1];
+ // PreferenceConverter.setValue(fOverlayStore, key,
+ // fAnnotationForegroundColorEditor.getColorValue());
+ // }
+ // });
+ // fDecorationStyleCombo.addSelectionListener(new SelectionListener() {
+ // /**
+ // * {@inheritdoc}
+ // */
+ // public void widgetDefaultSelected(SelectionEvent e) {
+ // // do nothing
+ // }
+ // /**
+ // * {@inheritdoc}
+ // */
+ // public void widgetSelected(SelectionEvent e) {
+ // int i = fAnnotationList.getSelectionIndex();
+ // String key = fAnnotationColorListModel[i][6];
+ // if (key != null) {
+ // for (int j = 0; j < fAnnotationDecorationListModel.length; j++) {
+ // if (fAnnotationDecorationListModel[j][0]
+ // .equals(fDecorationStyleCombo.getText())) {
+ // fOverlayStore.setValue(key, fAnnotationDecorationListModel[j][1]);
+ // break;
+ // }
+ // }
+ // }
+ // }
+ // });
+ // return composite;
+ // }
+ private String[][] createAnnotationTypeListModel(
+ MarkerAnnotationPreferences preferences) {
+ ArrayList listModelItems = new ArrayList();
+ SortedSet sortedPreferences = new TreeSet(new Comparator() {
+ /*
+ * @see java.util.Comparator#compare(java.lang.Object,
+ * java.lang.Object)
+ */
+ public int compare(Object o1, Object o2) {
+ if (!(o2 instanceof AnnotationPreference))
+ return -1;
+ if (!(o1 instanceof AnnotationPreference))
+ return 1;
+ AnnotationPreference a1 = (AnnotationPreference) o1;
+ AnnotationPreference a2 = (AnnotationPreference) o2;
+ return Collator.getInstance().compare(a1.getPreferenceLabel(),
+ a2.getPreferenceLabel());
+ }
+ });
+ sortedPreferences.addAll(preferences.getAnnotationPreferences());
+ Iterator e = sortedPreferences.iterator();
+ while (e.hasNext()) {
+ AnnotationPreference info = (AnnotationPreference) e.next();
+ listModelItems.add(new String[] { info.getPreferenceLabel(),
+ info.getColorPreferenceKey(), info.getTextPreferenceKey(),
+ info.getOverviewRulerPreferenceKey(),
+ info.getHighlightPreferenceKey(),
+ info.getVerticalRulerPreferenceKey(),
+ info.getTextStylePreferenceKey() });
+ }
+ String[][] items = new String[listModelItems.size()][];
+ listModelItems.toArray(items);
+ return items;
+ }
+
+ private Control createTypingPage(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+ String label;
+ // label = PreferencesMessages
+ // .getString("JavaEditorPreferencePage.overwriteMode");
+ // //$NON-NLS-1$
+ // addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE, 1);
+ // addFiller(composite);
+ //
+ // label = PreferencesMessages
+ // .getString("JavaEditorPreferencePage.smartHomeEnd");
+ // //$NON-NLS-1$
+ // addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_SMART_HOME_END, 1);
+ //
+ // label = PreferencesMessages
+ // .getString("JavaEditorPreferencePage.subWordNavigation");
+ // //$NON-NLS-1$
+ // addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION, 1);
+ // addFiller(composite);
+ Group group = new Group(composite, SWT.NONE);
+ layout = new GridLayout();
+ layout.numColumns = 2;
+ group.setLayout(layout);
+ group.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.typing.description")); //$NON-NLS-1$
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.wrapWords");//$NON-NLS-1$
+ addCheckBox(group, label, PreferenceConstants.EDITOR_WRAP_WORDS, 1);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.wrapStringsDQ");//$NON-NLS-1$
+ Button button = addCheckBox(group, label,
+ PreferenceConstants.EDITOR_WRAP_STRINGS_DQ, 1);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.escapeStringsDQ");//$NON-NLS-1$
+ fEscapeStringsButtonDQ = addCheckBox(group, label,
+ PreferenceConstants.EDITOR_ESCAPE_STRINGS_DQ, 1);
+ createDependency(button, fEscapeStringsButtonDQ);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.wrapStringsSQ");//$NON-NLS-1$
+ button = addCheckBox(group, label,
+ PreferenceConstants.EDITOR_WRAP_STRINGS_SQ, 1);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.escapeStringsSQ");
+ //$NON-NLS-1$
+ fEscapeStringsButtonSQ = addCheckBox(group, label,
+ PreferenceConstants.EDITOR_ESCAPE_STRINGS_SQ, 1);
+ createDependency(button, fEscapeStringsButtonSQ);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.smartPaste");
+ //$NON-NLS-1$
+ addCheckBox(group, label, PreferenceConstants.EDITOR_SMART_PASTE, 1);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.insertSpaceForTabs");
+ //$NON-NLS-1$
+ addCheckBox(group, label, PreferenceConstants.EDITOR_SPACES_FOR_TABS, 1);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.closeStringsDQ");
+ //$NON-NLS-1$
+ addCheckBox(group, label,
+ PreferenceConstants.EDITOR_CLOSE_STRINGS_DQ_PHP, 1);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.closeStringsSQ");
+ //$NON-NLS-1$
+ addCheckBox(group, label,
+ PreferenceConstants.EDITOR_CLOSE_STRINGS_SQ_PHP, 1);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.closeBrackets");
+ //$NON-NLS-1$
+ addCheckBox(group, label,
+ PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP, 1);
+
+ // label = PreferencesMessages
+ // .getString("JavaEditorPreferencePage.closeBraces");
+ // //$NON-NLS-1$
+ // addCheckBox(group, label, PreferenceConstants.EDITOR_CLOSE_BRACES,
+ // 1);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.closeJavaDocs");
+ //$NON-NLS-1$
+ button = addCheckBox(group, label,
+ PreferenceConstants.EDITOR_CLOSE_JAVADOCS, 1);
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.formatJavaDocs");
+ //$NON-NLS-1$
+ button = addCheckBox(group, label,
+ PreferenceConstants.EDITOR_FORMAT_JAVADOCS, 1);
+
+ //
+ // label = PreferencesMessages
+ // .getString("JavaEditorPreferencePage.addJavaDocTags");
+ // //$NON-NLS-1$
+ // fAddJavaDocTagsButton = addCheckBox(group, label,
+ // PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS, 1);
+ // createDependency(button, fAddJavaDocTagsButton);
+ return composite;
+ }
+
+ private void addFiller(Composite composite) {
+ Label filler = new Label(composite, SWT.LEFT);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ gd.heightHint = convertHeightInCharsToPixels(1) / 2;
+ filler.setLayoutData(gd);
+ }
+
+ private static void indent(Control control) {
+ GridData gridData = new GridData();
+ gridData.horizontalIndent = 20;
+ control.setLayoutData(gridData);
+ }
+
+ private static void createDependency(final Button master,
+ final Control slave) {
+ indent(slave);
+ master.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ slave.setEnabled(master.getSelection());
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ private void addCompletionRadioButtons(Composite contentAssistComposite) {
+ Composite completionComposite = new Composite(contentAssistComposite,
+ SWT.NONE);
+ GridData ccgd = new GridData();
+ ccgd.horizontalSpan = 2;
+ completionComposite.setLayoutData(ccgd);
+ GridLayout ccgl = new GridLayout();
+ ccgl.marginWidth = 0;
+ ccgl.numColumns = 2;
+ completionComposite.setLayout(ccgl);
+ // SelectionListener completionSelectionListener= new SelectionAdapter()
+ // {
+ // public void widgetSelected(SelectionEvent e) {
+ // boolean insert= fCompletionInsertsRadioButton.getSelection();
+ // fOverlayStore.setValue(PreferenceConstants.CODEASSIST_INSERT_COMPLETION,
+ // insert);
+ // }
+ // };
+ //
+ // fCompletionInsertsRadioButton= new Button(completionComposite,
+ // SWT.RADIO
+ // | SWT.LEFT);
+ // fCompletionInsertsRadioButton.setText(PreferencesMessages.getString("JavaEditorPreferencePage.completionInserts"));
+ // //$NON-NLS-1$
+ // fCompletionInsertsRadioButton.setLayoutData(new GridData());
+ // fCompletionInsertsRadioButton.addSelectionListener(completionSelectionListener);
+ //
+ // fCompletionOverwritesRadioButton= new Button(completionComposite,
+ // SWT.RADIO | SWT.LEFT);
+ // fCompletionOverwritesRadioButton.setText(PreferencesMessages.getString("JavaEditorPreferencePage.completionOverwrites"));
+ // //$NON-NLS-1$
+ // fCompletionOverwritesRadioButton.setLayoutData(new GridData());
+ // fCompletionOverwritesRadioButton.addSelectionListener(completionSelectionListener);
+ }
+
+ private Control createNavigationPage(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+ String text = PreferencesMessages
+ .getString("JavaEditorPreferencePage.navigation.browserLikeLinks");
+ //$NON-NLS-1$
+ fBrowserLikeLinksCheckBox = addCheckBox(composite, text,
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS, 0);
+ fBrowserLikeLinksCheckBox.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean state = fBrowserLikeLinksCheckBox.getSelection();
+ fBrowserLikeLinksKeyModifierText.setEnabled(state);
+ handleBrowserLikeLinksKeyModifierModified();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ // Text field for modifier string
+ text = PreferencesMessages
+ .getString("JavaEditorPreferencePage.navigation.browserLikeLinksKeyModifier");
+ //$NON-NLS-1$
+ fBrowserLikeLinksKeyModifierText = addTextField(composite, text,
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER, 20,
+ 0, false);
+ fBrowserLikeLinksKeyModifierText.setTextLimit(Text.LIMIT);
+
+ if (computeStateMask(fOverlayStore
+ .getString(PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER)) == -1) {
+ // Fix possible illegal modifier string
+ int stateMask = fOverlayStore
+ .getInt(PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
+ if (stateMask == -1)
+ fBrowserLikeLinksKeyModifierText.setText(""); //$NON-NLS-1$
+ else
+ fBrowserLikeLinksKeyModifierText.setText(EditorUtility
+ .getModifierString(stateMask));
+ }
+ fBrowserLikeLinksKeyModifierText.addKeyListener(new KeyListener() {
+ private boolean isModifierCandidate;
+
+ public void keyPressed(KeyEvent e) {
+ isModifierCandidate = e.keyCode > 0 && e.character == 0
+ && e.stateMask == 0;
+ }
+
+ public void keyReleased(KeyEvent e) {
+ if (isModifierCandidate && e.stateMask > 0
+ && e.stateMask == e.stateMask && e.character == 0) {// &&
+ // e.time
+ // -time
+ // <
+ // 1000)
+ // {
+ String modifierString = fBrowserLikeLinksKeyModifierText
+ .getText();
+ Point selection = fBrowserLikeLinksKeyModifierText
+ .getSelection();
+ int i = selection.x - 1;
+ while (i > -1
+ && Character.isWhitespace(modifierString.charAt(i))) {
+ i--;
+ }
+ boolean needsPrefixDelimiter = i > -1
+ && !String.valueOf(modifierString.charAt(i))
+ .equals(DELIMITER);
+
+ i = selection.y;
+ while (i < modifierString.length()
+ && Character.isWhitespace(modifierString.charAt(i))) {
+ i++;
+ }
+ boolean needsPostfixDelimiter = i < modifierString.length()
+ && !String.valueOf(modifierString.charAt(i))
+ .equals(DELIMITER);
+
+ String insertString;
+
+ if (needsPrefixDelimiter && needsPostfixDelimiter)
+ insertString = PreferencesMessages
+ .getFormattedString(
+ "JavaEditorPreferencePage.navigation.insertDelimiterAndModifierAndDelimiter",
+ new String[] { Action
+ .findModifierString(e.stateMask) }); //$NON-NLS-1$
+ else if (needsPrefixDelimiter)
+ insertString = PreferencesMessages
+ .getFormattedString(
+ "JavaEditorPreferencePage.navigation.insertDelimiterAndModifier",
+ new String[] { Action
+ .findModifierString(e.stateMask) }); //$NON-NLS-1$
+ else if (needsPostfixDelimiter)
+ insertString = PreferencesMessages
+ .getFormattedString(
+ "JavaEditorPreferencePage.navigation.insertModifierAndDelimiter",
+ new String[] { Action
+ .findModifierString(e.stateMask) }); //$NON-NLS-1$
+ else
+ insertString = Action.findModifierString(e.stateMask);
+
+ fBrowserLikeLinksKeyModifierText.insert(insertString);
+ }
+ }
+ });
+
+ fBrowserLikeLinksKeyModifierText
+ .addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ handleBrowserLikeLinksKeyModifierModified();
+ }
+ });
+ return composite;
+ }
+
+ private void handleBrowserLikeLinksKeyModifierModified() {
+ String modifiers = fBrowserLikeLinksKeyModifierText.getText();
+ int stateMask = computeStateMask(modifiers);
+ if (fBrowserLikeLinksCheckBox.getSelection()
+ && (stateMask == -1 || (stateMask & SWT.SHIFT) != 0)) {
+ if (stateMask == -1)
+ fBrowserLikeLinksKeyModifierStatus = new StatusInfo(
+ IStatus.ERROR,
+ PreferencesMessages
+ .getFormattedString(
+ "JavaEditorPreferencePage.navigation.modifierIsNotValid", modifiers)); //$NON-NLS-1$
+ else
+ fBrowserLikeLinksKeyModifierStatus = new StatusInfo(
+ IStatus.ERROR,
+ PreferencesMessages
+ .getString("JavaEditorPreferencePage.navigation.shiftIsDisabled"));
+ //$NON-NLS-1$
+ setValid(false);
+ StatusUtil.applyToStatusLine(this,
+ fBrowserLikeLinksKeyModifierStatus);
+ } else {
+ fBrowserLikeLinksKeyModifierStatus = new StatusInfo();
+ updateStatus(fBrowserLikeLinksKeyModifierStatus);
+ }
+ }
+
+ private IStatus getBrowserLikeLinksKeyModifierStatus() {
+ if (fBrowserLikeLinksKeyModifierStatus == null)
+ fBrowserLikeLinksKeyModifierStatus = new StatusInfo();
+ return fBrowserLikeLinksKeyModifierStatus;
+ }
+
+ /**
+ * Computes the state mask for the given modifier string.
+ *
+ * @param modifiers
+ * the string with the modifiers, separated by '+', '-', ';', ','
+ * or '.'
+ * @return the state mask or -1 if the input is invalid
+ */
+ private int computeStateMask(String modifiers) {
+ if (modifiers == null)
+ return -1;
+ if (modifiers.length() == 0)
+ return SWT.NONE;
+ int stateMask = 0;
+ StringTokenizer modifierTokenizer = new StringTokenizer(modifiers,
+ ",;.:+-* "); //$NON-NLS-1$
+ while (modifierTokenizer.hasMoreTokens()) {
+ int modifier = EditorUtility
+ .findLocalizedModifier(modifierTokenizer.nextToken());
+ if (modifier == 0 || (stateMask & modifier) == modifier)
+ return -1;
+ stateMask = stateMask | modifier;
+ }
+ return stateMask;
+ }
+
+ /*
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ initializeDefaultColors();
+ fFoldingConfigurationBlock = new FoldingConfigurationBlock(
+ fOverlayStore);
+ fOverlayStore.load();
+ fOverlayStore.start();
+ TabFolder folder = new TabFolder(parent, SWT.NONE);
+ folder.setLayout(new TabFolderLayout());
+ folder.setLayoutData(new GridData(GridData.FILL_BOTH));
+ TabItem item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.general")); //$NON-NLS-1$
+ item.setControl(createAppearancePage(folder));
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.colors")); //$NON-NLS-1$
+ item.setControl(createSyntaxPage(folder));
+
+ // item = new TabItem(folder, SWT.NONE);
+ // item.setText(PreferencesMessages
+ // .getString("JavaEditorPreferencePage.annotationsTab.title"));
+ // //$NON-NLS-1$
+ // item.setControl(createAnnotationsPage(folder));
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.typing.tabTitle"));
+ //$NON-NLS-1$
+ item.setControl(createTypingPage(folder));
+
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.hoverTab.title"));
+ //$NON-NLS-1$
+ fJavaEditorHoverConfigurationBlock = new JavaEditorHoverConfigurationBlock(
+ this, fOverlayStore);
+ item.setControl(fJavaEditorHoverConfigurationBlock
+ .createControl(folder));
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.navigationTab.title"));
+ // //$NON-NLS-1$
+ item.setControl(createNavigationPage(folder));
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(PreferencesMessages
+ .getString("JavaEditorPreferencePage.folding.title")); //$NON-NLS-1$
+ item.setControl(fFoldingConfigurationBlock.createControl(folder));
+
+ initialize();
+ Dialog.applyDialogFont(folder);
+ return folder;
+ }
+
+ private void initialize() {
+ initializeFields();
+ for (int i = 0; i < fSyntaxColorListModel.length; i++)
+ fSyntaxColorList.add(fSyntaxColorListModel[i][0]);
+ fSyntaxColorList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (fSyntaxColorList != null && !fSyntaxColorList.isDisposed()) {
+ fSyntaxColorList.select(0);
+ handleSyntaxColorListSelection();
+ }
+ }
+ });
+ for (int i = 0; i < fAppearanceColorListModel.length; i++)
+ fAppearanceColorList.add(fAppearanceColorListModel[i][0]);
+ fAppearanceColorList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (fAppearanceColorList != null
+ && !fAppearanceColorList.isDisposed()) {
+ fAppearanceColorList.select(0);
+ handleAppearanceColorListSelection();
+ }
+ }
+ });
+ // for (int i = 0; i < fAnnotationColorListModel.length; i++)
+ // fAnnotationList.add(fAnnotationColorListModel[i][0]);
+ // fAnnotationList.getDisplay().asyncExec(new Runnable() {
+ // public void run() {
+ // if (fAnnotationList != null && !fAnnotationList.isDisposed()) {
+ // fAnnotationList.select(0);
+ // handleAnnotationListSelection();
+ // }
+ // }
+ // });
+ // for (int i= 0; i < fContentAssistColorListModel.length; i++)
+ // fContentAssistColorList.add(fContentAssistColorListModel[i][0]);
+ // fContentAssistColorList.getDisplay().asyncExec(new Runnable() {
+ // public void run() {
+ // if (fContentAssistColorList != null &&
+ // !fContentAssistColorList.isDisposed()) {
+ // fContentAssistColorList.select(0);
+ // handleContentAssistColorListSelection();
+ // }
+ // }
+ // });
+ fFoldingConfigurationBlock.initialize();
+ }
+
+ private void initializeFields() {
+ Iterator e = fColorButtons.keySet().iterator();
+ while (e.hasNext()) {
+ ColorEditor c = (ColorEditor) e.next();
+ String key = (String) fColorButtons.get(c);
+ RGB rgb = PreferenceConverter.getColor(fOverlayStore, key);
+ c.setColorValue(rgb);
+ }
+ e = fCheckBoxes.keySet().iterator();
+ while (e.hasNext()) {
+ Button b = (Button) e.next();
+ String key = (String) fCheckBoxes.get(b);
+ b.setSelection(fOverlayStore.getBoolean(key));
+ }
+ e = fTextFields.keySet().iterator();
+ while (e.hasNext()) {
+ Text t = (Text) e.next();
+ String key = (String) fTextFields.get(t);
+ t.setText(fOverlayStore.getString(key));
+ }
+ RGB rgb = PreferenceConverter.getColor(fOverlayStore,
+ PreferenceConstants.EDITOR_BACKGROUND_COLOR);
+ fBackgroundColorEditor.setColorValue(rgb);
+ boolean default_ = fOverlayStore
+ .getBoolean(PreferenceConstants.EDITOR_BACKGROUND_DEFAULT_COLOR);
+ fBackgroundDefaultRadioButton.setSelection(default_);
+ fBackgroundCustomRadioButton.setSelection(!default_);
+ fBackgroundColorButton.setEnabled(!default_);
+ boolean closeJavaDocs = fOverlayStore
+ .getBoolean(PreferenceConstants.EDITOR_CLOSE_JAVADOCS);
+ // fAddJavaDocTagsButton.setEnabled(closeJavaDocs);
+ fEscapeStringsButtonDQ.setEnabled(fOverlayStore
+ .getBoolean(PreferenceConstants.EDITOR_WRAP_STRINGS_DQ));
+ fEscapeStringsButtonSQ.setEnabled(fOverlayStore
+ .getBoolean(PreferenceConstants.EDITOR_WRAP_STRINGS_SQ));
+ // boolean fillMethodArguments=
+ // fOverlayStore.getBoolean(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES);
+ // fGuessMethodArgumentsButton.setEnabled(fillMethodArguments);
+ // boolean completionInserts=
+ // fOverlayStore.getBoolean(PreferenceConstants.CODEASSIST_INSERT_COMPLETION);
+ // fCompletionInsertsRadioButton.setSelection(completionInserts);
+ // fCompletionOverwritesRadioButton.setSelection(! completionInserts);
+ //
+ fBrowserLikeLinksKeyModifierText.setEnabled(fBrowserLikeLinksCheckBox
+ .getSelection());
+ // boolean markOccurrences=
+ // fOverlayStore.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
+ // fStickyOccurrencesButton.setEnabled(markOccurrences);
+ updateAutoactivationControls();
+ }
+
+ private void initializeDefaultColors() {
+ if (!getPreferenceStore().contains(
+ PreferenceConstants.EDITOR_BACKGROUND_COLOR)) {
+ RGB rgb = getControl().getDisplay().getSystemColor(
+ SWT.COLOR_LIST_BACKGROUND).getRGB();
+ PreferenceConverter.setDefault(fOverlayStore,
+ PreferenceConstants.EDITOR_BACKGROUND_COLOR, rgb);
+ PreferenceConverter.setDefault(getPreferenceStore(),
+ PreferenceConstants.EDITOR_BACKGROUND_COLOR, rgb);
+ }
+ if (!getPreferenceStore().contains(
+ PreferenceConstants.EDITOR_FOREGROUND_COLOR)) {
+ RGB rgb = getControl().getDisplay().getSystemColor(
+ SWT.COLOR_LIST_FOREGROUND).getRGB();
+ PreferenceConverter.setDefault(fOverlayStore,
+ PreferenceConstants.EDITOR_FOREGROUND_COLOR, rgb);
+ PreferenceConverter.setDefault(getPreferenceStore(),
+ PreferenceConstants.EDITOR_FOREGROUND_COLOR, rgb);
+ }
+ }
+
+ private void updateAutoactivationControls() {
+ // boolean autoactivation=
+ // fOverlayStore.getBoolean(PreferenceConstants.CODEASSIST_AUTOACTIVATION);
+ // fAutoInsertDelayText.setEnabled(autoactivation);
+ // fAutoInsertDelayLabel.setEnabled(autoactivation);
+ // fAutoInsertJavaTriggerText.setEnabled(autoactivation);
+ // fAutoInsertJavaTriggerLabel.setEnabled(autoactivation);
+ //
+ // fAutoInsertJavaDocTriggerText.setEnabled(autoactivation);
+ // fAutoInsertJavaDocTriggerLabel.setEnabled(autoactivation);
+ }
+
+ /*
+ * @see PreferencePage#performOk()
+ */
+ public boolean performOk() {
+ // fJavaEditorHoverConfigurationBlock.performOk();
+ fFoldingConfigurationBlock.performOk();
+ fOverlayStore
+ .setValue(
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK,
+ computeStateMask(fBrowserLikeLinksKeyModifierText
+ .getText()));
+ fOverlayStore.propagate();
+ WebUI.getDefault().savePluginPreferences();
+ return true;
+ }
+
+ /*
+ * @see PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ fOverlayStore.loadDefaults();
+ initializeFields();
+ handleSyntaxColorListSelection();
+ handleAppearanceColorListSelection();
+ // handleAnnotationListSelection();
+ // handleContentAssistColorListSelection();
+ // fJavaEditorHoverConfigurationBlock.performDefaults();
+ fFoldingConfigurationBlock.performDefaults();
+ super.performDefaults();
+ fPreviewViewer.invalidateTextPresentation();
+ }
+
+ /*
+ * @see DialogPage#dispose()
+ */
+ public void dispose() {
+ fFoldingConfigurationBlock.dispose();
+
+ if (fJavaTextTools != null) {
+ fJavaTextTools.dispose();
+ fJavaTextTools = null;
+ }
+ if (fOverlayStore != null) {
+ fOverlayStore.stop();
+ fOverlayStore = null;
+ }
+ if (fBackgroundColor != null && !fBackgroundColor.isDisposed())
+ fBackgroundColor.dispose();
+ super.dispose();
+ }
+
+ private Button addCheckBox(Composite parent, String label, String key,
+ int indentation) {
+ Button checkBox = new Button(parent, SWT.CHECK);
+ checkBox.setText(label);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ gd.horizontalSpan = 2;
+ checkBox.setLayoutData(gd);
+ checkBox.addSelectionListener(fCheckBoxListener);
+ fCheckBoxes.put(checkBox, key);
+ return checkBox;
+ }
+
+ private Text addTextField(Composite composite, String label, String key,
+ int textLimit, int indentation, boolean isNumber) {
+ return getTextControl(addLabelledTextField(composite, label, key,
+ textLimit, indentation, isNumber));
+ }
+
+ private static Label getLabelControl(Control[] labelledTextField) {
+ return (Label) labelledTextField[0];
+ }
+
+ private static Text getTextControl(Control[] labelledTextField) {
+ return (Text) labelledTextField[1];
+ }
+
+ /**
+ * Returns an array of size 2: - first element is of type Label
-
+ * second element is of type Text
Use
+ * getLabelControl
and getTextControl
to get
+ * the 2 controls.
+ */
+ private Control[] addLabelledTextField(Composite composite, String label,
+ String key, int textLimit, int indentation, boolean isNumber) {
+ Label labelControl = new Label(composite, SWT.NONE);
+ labelControl.setText(label);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ labelControl.setLayoutData(gd);
+ Text textControl = new Text(composite, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.widthHint = convertWidthInCharsToPixels(textLimit + 1);
+ textControl.setLayoutData(gd);
+ textControl.setTextLimit(textLimit);
+ fTextFields.put(textControl, key);
+ if (isNumber) {
+ fNumberFields.add(textControl);
+ textControl.setText("0");
+ textControl.addModifyListener(fNumberFieldListener);
+ } else {
+ textControl.addModifyListener(fTextFieldListener);
+ }
+ return new Control[] { labelControl, textControl };
+ }
+
+ private String loadPreviewContentFromFile(String filename) {
+ String line;
+ String separator = System.getProperty("line.separator"); //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer(512);
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(getClass()
+ .getResourceAsStream(filename)));
+ while ((line = reader.readLine()) != null) {
+ buffer.append(line);
+ buffer.append(separator);
+ }
+ } catch (IOException io) {
+ WebUI.log(io);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return buffer.toString();
+ }
+
+ private void numberFieldChanged(Text textControl) {
+ String number = textControl.getText();
+ IStatus status = validatePositiveNumber(number);
+ if (!status.matches(IStatus.ERROR))
+ fOverlayStore.setValue((String) fTextFields.get(textControl),
+ number);
+ updateStatus(status);
+ }
+
+ private IStatus validatePositiveNumber(String number) {
+ StatusInfo status = new StatusInfo();
+ if (number.length() == 0) {
+ status.setError(PreferencesMessages
+ .getString("JavaEditorPreferencePage.empty_input")); //$NON-NLS-1$
+ } else {
+ try {
+ int value = Integer.parseInt(number);
+ if (value < 0)
+ status.setError(PreferencesMessages.getFormattedString(
+ "JavaEditorPreferencePage.invalid_input", number)); //$NON-NLS-1$
+ } catch (NumberFormatException e) {
+ status.setError(PreferencesMessages.getFormattedString(
+ "JavaEditorPreferencePage.invalid_input", number)); //$NON-NLS-1$
+ }
+ }
+ return status;
+ }
+
+ void updateStatus(IStatus status) {
+ if (!status.matches(IStatus.ERROR)) {
+ for (int i = 0; i < fNumberFields.size(); i++) {
+ Text text = (Text) fNumberFields.get(i);
+ IStatus s = validatePositiveNumber(text.getText());
+ status = StatusUtil.getMoreSevere(s, status);
+ }
+ }
+ // status=
+ // StatusUtil.getMoreSevere(fJavaEditorHoverConfigurationBlock.getStatus(),
+ // status);
+ // status=
+ // StatusUtil.getMoreSevere(getBrowserLikeLinksKeyModifierStatus(),
+ // status);
+ setValid(!status.matches(IStatus.ERROR));
+ StatusUtil.applyToStatusLine(this, status);
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaPreferencesSettings.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaPreferencesSettings.java
new file mode 100644
index 0000000..bbb7687
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaPreferencesSettings.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.internal.corext.codemanipulation.CodeGenerationSettings;
+import net.sourceforge.phpdt.internal.corext.util.CodeFormatterUtil;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+public class JavaPreferencesSettings {
+
+ public static CodeGenerationSettings getCodeGenerationSettings() {
+ IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ CodeGenerationSettings res = new CodeGenerationSettings();
+ res.createComments = store
+ .getBoolean(PreferenceConstants.CODEGEN_ADD_COMMENTS);
+ res.useKeywordThis = store
+ .getBoolean(PreferenceConstants.CODEGEN_KEYWORD_THIS);
+ // res.importOrder= getImportOrderPreference(store);
+ res.importThreshold = getImportNumberThreshold(store);
+ res.tabWidth = CodeFormatterUtil.getTabWidth();
+ return res;
+ }
+
+ public static int getImportNumberThreshold(IPreferenceStore prefs) {
+ int threshold = prefs
+ .getInt(PreferenceConstants.ORGIMPORTS_ONDEMANDTHRESHOLD);
+ if (threshold < 0) {
+ threshold = Integer.MAX_VALUE;
+ }
+ return threshold;
+ }
+
+ // public static String[] getImportOrderPreference(IPreferenceStore prefs) {
+ // String str= prefs.getString(PreferenceConstants.ORGIMPORTS_IMPORTORDER);
+ // if (str != null) {
+ // return unpackList(str, ";"); //$NON-NLS-1$
+ // }
+ // return new String[0];
+ // }
+
+ private static String[] unpackList(String str, String separator) {
+ StringTokenizer tok = new StringTokenizer(str, separator); //$NON-NLS-1$
+ int nTokens = tok.countTokens();
+ String[] res = new String[nTokens];
+ for (int i = 0; i < nTokens; i++) {
+ res[i] = tok.nextToken().trim();
+ }
+ return res;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaSourcePreviewerUpdater.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaSourcePreviewerUpdater.java
new file mode 100644
index 0000000..5fedc3a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaSourcePreviewerUpdater.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Font;
+
+/**
+ * Handles Java editor font changes for Java source preview viewers.
+ *
+ * @since 3.0
+ */
+class JavaSourcePreviewerUpdater {
+
+ /**
+ * Creates a Java source preview updater for the given viewer, configuration
+ * and preference store.
+ *
+ * @param viewer
+ * the viewer
+ * @param configuration
+ * the configuration
+ * @param preferenceStore
+ * the preference store
+ */
+ JavaSourcePreviewerUpdater(final SourceViewer viewer,
+ final PHPSourceViewerConfiguration configuration,
+ final IPreferenceStore preferenceStore) {
+ Assert.isNotNull(viewer);
+ Assert.isNotNull(configuration);
+ Assert.isNotNull(preferenceStore);
+ final IPropertyChangeListener fontChangeListener = new IPropertyChangeListener() {
+ /*
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (event.getProperty().equals(
+ PreferenceConstants.EDITOR_TEXT_FONT)) {
+ Font font = JFaceResources
+ .getFont(PreferenceConstants.EDITOR_TEXT_FONT);
+ viewer.getTextWidget().setFont(font);
+ }
+ }
+ };
+ final IPropertyChangeListener propertyChangeListener = new IPropertyChangeListener() {
+ /*
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (configuration.affectsTextPresentation(event)) {
+ configuration.handlePropertyChangeEvent(event);
+ viewer.invalidateTextPresentation();
+ }
+ }
+ };
+ viewer.getTextWidget().addDisposeListener(new DisposeListener() {
+ /*
+ * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
+ */
+ public void widgetDisposed(DisposeEvent e) {
+ preferenceStore
+ .removePropertyChangeListener(propertyChangeListener);
+ JFaceResources.getFontRegistry().removeListener(
+ fontChangeListener);
+ }
+ });
+ JFaceResources.getFontRegistry().addListener(fontChangeListener);
+ preferenceStore.addPropertyChangeListener(propertyChangeListener);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaTemplatePreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaTemplatePreferencePage.java
new file mode 100644
index 0000000..79c6d07
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/JavaTemplatePreferencePage.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.template.preferences.TemplateVariableProcessor;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.dialogs.Dialog;
+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.Template;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.templates.TemplatePreferencePage;
+
+public class JavaTemplatePreferencePage extends TemplatePreferencePage
+ implements IWorkbenchPreferencePage {
+
+ private TemplateVariableProcessor fTemplateProcessor;
+
+ public JavaTemplatePreferencePage() {
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+ setTemplateStore(WebUI.getDefault().getTemplateStore());
+ setContextTypeRegistry(WebUI.getDefault()
+ .getTemplateContextRegistry());
+ fTemplateProcessor = new TemplateVariableProcessor();
+ }
+
+ /*
+ * @see PreferencePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.JAVA_EDITOR_PREFERENCE_PAGE);
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ boolean ok = super.performOk();
+
+ WebUI.getDefault().savePluginPreferences();
+
+ return ok;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#getFormatterPreferenceKey()
+ */
+ protected String getFormatterPreferenceKey() {
+ return PreferenceConstants.TEMPLATES_USE_CODEFORMATTER;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createTemplateEditDialog(org.eclipse.jface.text.templates.Template,
+ * boolean, boolean)
+ */
+ protected Dialog createTemplateEditDialog(Template template, boolean edit,
+ boolean isNameModifiable) {
+ return new EditTemplateDialog(getShell(), template, edit,
+ isNameModifiable, getContextTypeRegistry());
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createViewer(org.eclipse.swt.widgets.Composite)
+ */
+ protected SourceViewer createViewer(Composite parent) {
+ GridData data = new GridData();
+ IDocument document = new Document();
+ JavaTextTools tools = WebUI.getDefault().getJavaTextTools();
+ tools.setupJavaDocumentPartitioner(document,
+ IPHPPartitions.PHP_PARTITIONING);
+ IPreferenceStore store = WebUI.getDefault()
+ .getCombinedPreferenceStore();
+ SourceViewer viewer = new JavaSourceViewer(parent, null, null, false,
+ SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store);
+ TemplateEditorSourceViewerConfiguration configuration = new TemplateEditorSourceViewerConfiguration(
+ 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 JavaSourcePreviewerUpdater(viewer, configuration, store);
+
+ Control control = viewer.getControl();
+ data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.FILL_VERTICAL);
+ control.setLayoutData(data);
+
+ return viewer;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#updateViewerInput()
+ */
+ protected void updateViewerInput() {
+ IStructuredSelection selection = (IStructuredSelection) getTableViewer()
+ .getSelection();
+ SourceViewer viewer = getViewer();
+
+ if (selection.size() == 1
+ && selection.getFirstElement() instanceof TemplatePersistenceData) {
+ TemplatePersistenceData data = (TemplatePersistenceData) selection
+ .getFirstElement();
+ Template template = data.getTemplate();
+ String contextId = template.getContextTypeId();
+ TemplateContextType type = WebUI.getDefault()
+ .getTemplateContextRegistry().getContextType(contextId);
+ fTemplateProcessor.setContextType(type);
+
+ IDocument doc = viewer.getDocument();
+
+ String start = null;
+ if ("javadoc".equals(contextId)) { //$NON-NLS-1$
+ start = "/**" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$
+ } else
+ start = ""; //$NON-NLS-1$
+
+ doc.set(start + template.getPattern());
+ int startLen = start.length();
+ viewer.setDocument(doc, startLen, doc.getLength() - startLen);
+
+ } else {
+ viewer.getDocument().set(""); //$NON-NLS-1$
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MarkOccurrencesConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MarkOccurrencesConfigurationBlock.java
new file mode 100644
index 0000000..0b580c0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MarkOccurrencesConfigurationBlock.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.text.Assert;
+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.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Configures Java Editor hover preferences.
+ *
+ * @since 2.1
+ */
+class MarkOccurrencesConfigurationBlock implements
+ IPreferenceConfigurationBlock {
+
+ private OverlayPreferenceStore fStore;
+
+ private Map fCheckBoxes = new HashMap();
+
+ private SelectionListener fCheckBoxListener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ Button button = (Button) e.widget;
+ fStore.setValue((String) fCheckBoxes.get(button), button
+ .getSelection());
+ }
+ };
+
+ /**
+ * List of master/slave listeners when there's a dependency.
+ *
+ * @see #createDependency(Button, String, Control)
+ * @since 3.0
+ */
+ private ArrayList fMasterSlaveListeners = new ArrayList();
+
+ private StatusInfo fStatus;
+
+ public MarkOccurrencesConfigurationBlock(OverlayPreferenceStore store) {
+ Assert.isNotNull(store);
+ fStore = store;
+
+ fStore.addKeys(createOverlayStoreKeys());
+ }
+
+ private OverlayPreferenceStore.OverlayKey[] createOverlayStoreKeys() {
+
+ ArrayList overlayKeys = new ArrayList();
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_MARK_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_MARK_IMPLEMENTORS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_STICKY_OCCURRENCES));
+
+ OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys
+ .size()];
+ overlayKeys.toArray(keys);
+ return keys;
+ }
+
+ /**
+ * Creates page for mark occurrences preferences.
+ *
+ * @param parent
+ * the parent composite
+ * @return the control for the preference page
+ */
+ public Control createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+
+ GridData gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_VERTICAL);
+ composite.setLayoutData(gd);
+
+ String label;
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.markOccurrences");
+ Button master = addCheckBox(composite, label,
+ PreferenceConstants.EDITOR_MARK_OCCURRENCES, 0); //$NON-NLS-1$
+
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markTypeOccurrences;
+ // Button slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES, 0); //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_STICKY_OCCURRENCES, slave);
+ //
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markMethodOccurrences;
+ // slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES, 0); //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES, slave);
+ //
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markConstantOccurrences;
+ // slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES, 0);
+ // //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES, slave);
+ //
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markFieldOccurrences;
+ // slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES, 0); //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES, slave);
+ //
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markLocalVariableOccurrences;
+ // slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES, 0);
+ // //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES, slave);
+ //
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markExceptionOccurrences;
+ // slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES, 0);
+ // //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES, slave);
+ //
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markMethodExitPoints;
+ // slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS, 0); //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS, slave);
+ //
+ // label=
+ // PreferencesMessages.MarkOccurrencesConfigurationBlock_markImplementors;
+ // slave= addCheckBox(composite, label,
+ // PreferenceConstants.EDITOR_MARK_IMPLEMENTORS, 0); //$NON-NLS-1$
+ // createDependency(master,
+ // PreferenceConstants.EDITOR_MARK_IMPLEMENTORS, slave);
+
+ //addFiller(composite);
+
+ label = PreferencesMessages
+ .getString("JavaEditorPreferencePage.stickyOccurrences");
+ Button slave = addCheckBox(composite, label,
+ PreferenceConstants.EDITOR_STICKY_OCCURRENCES, 0); //$NON-NLS-1$
+ createDependency(master, PreferenceConstants.EDITOR_STICKY_OCCURRENCES,
+ slave);
+
+ return composite;
+ }
+
+ private void addFiller(Composite composite) {
+ PixelConverter pixelConverter = new PixelConverter(composite);
+
+ Label filler = new Label(composite, SWT.LEFT);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ gd.heightHint = pixelConverter.convertHeightInCharsToPixels(1) / 2;
+ filler.setLayoutData(gd);
+ }
+
+ private Button addCheckBox(Composite parent, String label, String key,
+ int indentation) {
+ Button checkBox = new Button(parent, SWT.CHECK);
+ checkBox.setText(label);
+
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ gd.horizontalSpan = 2;
+ checkBox.setLayoutData(gd);
+ checkBox.addSelectionListener(fCheckBoxListener);
+
+ fCheckBoxes.put(checkBox, key);
+
+ return checkBox;
+ }
+
+ private void createDependency(final Button master, String masterKey,
+ final Control slave) {
+ indent(slave);
+ boolean masterState = fStore.getBoolean(masterKey);
+ slave.setEnabled(masterState);
+ SelectionListener listener = new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ slave.setEnabled(master.getSelection());
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ };
+ master.addSelectionListener(listener);
+ fMasterSlaveListeners.add(listener);
+ }
+
+ private static void indent(Control control) {
+ GridData gridData = new GridData();
+ gridData.horizontalIndent = 20;
+ control.setLayoutData(gridData);
+ }
+
+ public void initialize() {
+ initializeFields();
+ }
+
+ void initializeFields() {
+
+ Iterator iter = fCheckBoxes.keySet().iterator();
+ while (iter.hasNext()) {
+ Button b = (Button) iter.next();
+ String key = (String) fCheckBoxes.get(b);
+ b.setSelection(fStore.getBoolean(key));
+ }
+
+ // Update slaves
+ iter = fMasterSlaveListeners.iterator();
+ while (iter.hasNext()) {
+ SelectionListener listener = (SelectionListener) iter.next();
+ listener.widgetSelected(null);
+ }
+
+ }
+
+ public void performOk() {
+ }
+
+ public void performDefaults() {
+ restoreFromPreferences();
+ initializeFields();
+ }
+
+ private void restoreFromPreferences() {
+
+ }
+
+ IStatus getStatus() {
+ if (fStatus == null)
+ fStatus = new StatusInfo();
+ return fStatus;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.IPreferenceConfigurationBlock#dispose()
+ * @since 3.0
+ */
+ public void dispose() {
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MarkOccurrencesPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MarkOccurrencesPreferencePage.java
new file mode 100644
index 0000000..0cdcb6f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MarkOccurrencesPreferencePage.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * The page for setting the editor options.
+ */
+public final class MarkOccurrencesPreferencePage extends
+ AbstractConfigurationBlockPreferencePage {
+
+ /*
+ * @see org.eclipse.ui.internal.editors.text.AbstractConfigureationBlockPreferencePage#getHelpId()
+ */
+ protected String getHelpId() {
+ return IJavaHelpContextIds.JAVA_EDITOR_PREFERENCE_PAGE;
+ }
+
+ /*
+ * @see org.eclipse.ui.internal.editors.text.AbstractConfigurationBlockPreferencePage#setDescription()
+ */
+ protected void setDescription() {
+ String description = PreferencesMessages
+ .getString("MarkOccurrencesConfigurationBlock.title");
+ setDescription(description);
+ }
+
+ /*
+ * @see org.org.eclipse.ui.internal.editors.text.AbstractConfigurationBlockPreferencePage#setPreferenceStore()
+ */
+ protected void setPreferenceStore() {
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+ }
+
+ protected Label createDescriptionLabel(Composite parent) {
+ return null; // no description for new look.
+ }
+
+ /*
+ * @see org.eclipse.ui.internal.editors.text.AbstractConfigureationBlockPreferencePage#createConfigurationBlock(org.eclipse.ui.internal.editors.text.OverlayPreferenceStore)
+ */
+ protected IPreferenceConfigurationBlock createConfigurationBlock(
+ OverlayPreferenceStore overlayPreferenceStore) {
+ return new MarkOccurrencesConfigurationBlock(overlayPreferenceStore);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferenceCache.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferenceCache.java
new file mode 100644
index 0000000..cf34946
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferenceCache.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ */
+public class MembersOrderPreferenceCache implements IPropertyChangeListener {
+
+ public static final int TYPE_INDEX = 0;
+
+ public static final int CONSTRUCTORS_INDEX = 1;
+
+ public static final int METHOD_INDEX = 2;
+
+ public static final int FIELDS_INDEX = 3;
+
+ public static final int INIT_INDEX = 4;
+
+ public static final int STATIC_FIELDS_INDEX = 5;
+
+ public static final int STATIC_INIT_INDEX = 6;
+
+ public static final int STATIC_METHODS_INDEX = 7;
+
+ public static final int N_CATEGORIES = STATIC_METHODS_INDEX + 1;
+
+ private static final int PUBLIC_INDEX = 0;
+
+ private static final int PRIVATE_INDEX = 1;
+
+ private static final int PROTECTED_INDEX = 2;
+
+ private static final int DEFAULT_INDEX = 3;
+
+ private static final int N_VISIBILITIES = DEFAULT_INDEX + 1;
+
+ private int[] fCategoryOffsets = null;
+
+ private boolean fSortByVisibility;
+
+ private int[] fVisibilityOffsets = null;
+
+ public MembersOrderPreferenceCache() {
+ fCategoryOffsets = null;
+ fSortByVisibility = PreferenceConstants
+ .getPreferenceStore()
+ .getBoolean(
+ PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER);
+ fVisibilityOffsets = null;
+ }
+
+ public static boolean isMemberOrderProperty(String property) {
+ return PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER
+ .equals(property)
+ || PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER
+ .equals(property)
+ || PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER
+ .equals(property);
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+
+ if (PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER.equals(property)) {
+ fCategoryOffsets = null;
+ } else if (PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER
+ .equals(property)) {
+ fVisibilityOffsets = null;
+ } else if (PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER
+ .equals(property)) {
+ fSortByVisibility = PreferenceConstants
+ .getPreferenceStore()
+ .getBoolean(
+ PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER);
+ }
+ }
+
+ public int getCategoryIndex(int kind) {
+ if (fCategoryOffsets == null) {
+ fCategoryOffsets = getCategoryOffsets();
+ }
+ return fCategoryOffsets[kind];
+ }
+
+ private int[] getCategoryOffsets() {
+ int[] offsets = new int[N_CATEGORIES];
+ IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+ String key = PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER;
+ boolean success = fillCategoryOffsetsFromPreferenceString(store
+ .getString(key), offsets);
+ if (!success) {
+ store.setToDefault(key);
+ fillCategoryOffsetsFromPreferenceString(
+ store.getDefaultString(key), offsets);
+ }
+ return offsets;
+ }
+
+ private boolean fillCategoryOffsetsFromPreferenceString(String str,
+ int[] offsets) {
+ StringTokenizer tokenizer = new StringTokenizer(str, ","); //$NON-NLS-1$
+ int i = 0;
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken().trim();
+ if ("T".equals(token)) { //$NON-NLS-1$
+ offsets[TYPE_INDEX] = i++;
+ } else if ("M".equals(token)) { //$NON-NLS-1$
+ offsets[METHOD_INDEX] = i++;
+ } else if ("F".equals(token)) { //$NON-NLS-1$
+ offsets[FIELDS_INDEX] = i++;
+ } else if ("I".equals(token)) { //$NON-NLS-1$
+ offsets[INIT_INDEX] = i++;
+ } else if ("SF".equals(token)) { //$NON-NLS-1$
+ offsets[STATIC_FIELDS_INDEX] = i++;
+ } else if ("SI".equals(token)) { //$NON-NLS-1$
+ offsets[STATIC_INIT_INDEX] = i++;
+ } else if ("SM".equals(token)) { //$NON-NLS-1$
+ offsets[STATIC_METHODS_INDEX] = i++;
+ } else if ("C".equals(token)) { //$NON-NLS-1$
+ offsets[CONSTRUCTORS_INDEX] = i++;
+ }
+ }
+ return i == N_CATEGORIES;
+ }
+
+ public boolean isSortByVisibility() {
+ return fSortByVisibility;
+ }
+
+ public int getVisibilityIndex(int modifierFlags) {
+ if (fVisibilityOffsets == null) {
+ fVisibilityOffsets = getVisibilityOffsets();
+ }
+ int kind = DEFAULT_INDEX;
+ if (Flags.isPublic(modifierFlags)) {
+ kind = PUBLIC_INDEX;
+ } else if (Flags.isProtected(modifierFlags)) {
+ kind = PROTECTED_INDEX;
+ } else if (Flags.isPrivate(modifierFlags)) {
+ kind = PRIVATE_INDEX;
+ }
+
+ return fVisibilityOffsets[kind];
+ }
+
+ private int[] getVisibilityOffsets() {
+ int[] offsets = new int[N_VISIBILITIES];
+ IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+ String key = PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER;
+ boolean success = fillVisibilityOffsetsFromPreferenceString(store
+ .getString(key), offsets);
+ if (!success) {
+ store.setToDefault(key);
+ fillVisibilityOffsetsFromPreferenceString(store
+ .getDefaultString(key), offsets);
+ }
+ return offsets;
+ }
+
+ private boolean fillVisibilityOffsetsFromPreferenceString(String str,
+ int[] offsets) {
+ StringTokenizer tokenizer = new StringTokenizer(str, ","); //$NON-NLS-1$
+ int i = 0;
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken().trim();
+ if ("B".equals(token)) { //$NON-NLS-1$
+ offsets[PUBLIC_INDEX] = i++;
+ } else if ("V".equals(token)) { //$NON-NLS-1$
+ offsets[PRIVATE_INDEX] = i++;
+ } else if ("R".equals(token)) { //$NON-NLS-1$
+ offsets[PROTECTED_INDEX] = i++;
+ } else if ("D".equals(token)) { //$NON-NLS-1$
+ offsets[DEFAULT_INDEX] = i++;
+ }
+ }
+ return i == N_VISIBILITIES;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferencePage.java
new file mode 100644
index 0000000..1bc2806
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferencePage.java
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ImageDescriptorRegistry;
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementImageProvider;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.ListDialogField;
+import net.sourceforge.phpdt.ui.JavaElementImageDescriptor;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.SWT;
+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.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class MembersOrderPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage {
+
+ private static final String ALL_ENTRIES = "T,SI,SF,SM,I,F,C,M"; //$NON-NLS-1$
+
+ private static final String PREF_OUTLINE_SORT_OPTION = PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER;
+
+ public static final String CONSTRUCTORS = "C"; //$NON-NLS-1$
+
+ public static final String FIELDS = "F"; //$NON-NLS-1$
+
+ public static final String METHODS = "M"; //$NON-NLS-1$
+
+ public static final String STATIC_METHODS = "SM"; //$NON-NLS-1$
+
+ public static final String STATIC_FIELDS = "SF"; //$NON-NLS-1$
+
+ public static final String INIT = "I"; //$NON-NLS-1$
+
+ public static final String STATIC_INIT = "SI"; //$NON-NLS-1$
+
+ public static final String TYPES = "T"; //$NON-NLS-1$
+
+ private ListDialogField fSortOrderList;
+
+ private static List getSortOrderList(String string) {
+ StringTokenizer tokenizer = new StringTokenizer(string, ","); //$NON-NLS-1$
+ List entries = new ArrayList();
+ for (int i = 0; tokenizer.hasMoreTokens(); i++) {
+ String token = tokenizer.nextToken();
+ entries.add(token);
+ }
+ return entries;
+ }
+
+ private static boolean isValidEntries(List entries) {
+ StringTokenizer tokenizer = new StringTokenizer(ALL_ENTRIES, ","); //$NON-NLS-1$
+ int i = 0;
+ for (; tokenizer.hasMoreTokens(); i++) {
+ String token = tokenizer.nextToken();
+ if (!entries.contains(token))
+ return false;
+ }
+ return i == entries.size();
+ }
+
+ public MembersOrderPreferencePage() {
+ // set the preference store
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+
+ setDescription(PreferencesMessages
+ .getString("MembersOrderPreferencePage.label.description")); //$NON-NLS-1$
+
+ String string = getPreferenceStore()
+ .getString(PREF_OUTLINE_SORT_OPTION);
+
+ String upLabel = PreferencesMessages
+ .getString("MembersOrderPreferencePage.button.up"); //$NON-NLS-1$
+ String downLabel = PreferencesMessages
+ .getString("MembersOrderPreferencePage.button.down"); //$NON-NLS-1$
+ String[] buttonlabels = new String[] { upLabel, downLabel };
+
+ fSortOrderList = new ListDialogField(null, buttonlabels,
+ new MemberSortLabelProvider());
+ fSortOrderList.setDownButtonIndex(1);
+ fSortOrderList.setUpButtonIndex(0);
+
+ // validate entries stored in store, false get defaults
+ List entries = getSortOrderList(string);
+ if (!isValidEntries(entries)) {
+ string = WebUI.getDefault().getPreferenceStore()
+ .getDefaultString(PREF_OUTLINE_SORT_OPTION);
+ entries = getSortOrderList(string);
+ }
+
+ fSortOrderList.setElements(entries);
+ }
+
+ /*
+ * @see PreferencePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ // WorkbenchHelp.setHelp(getControl(),
+ // IJavaHelpContextIds.SORT_ORDER_PREFERENCE_PAGE);
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ composite.setLayout(layout);
+
+ GridData data = new GridData();
+ data.verticalAlignment = GridData.FILL;
+ data.horizontalAlignment = GridData.FILL_HORIZONTAL;
+ composite.setLayoutData(data);
+
+ createSortOrderListDialogField(composite, 3);
+ Dialog.applyDialogFont(composite);
+ return composite;
+ }
+
+ private void createSortOrderListDialogField(Composite composite, int span) {
+ fSortOrderList.doFillIntoGrid(composite, span);
+
+ fSortOrderList.getLabelControl(null).dispose();
+
+ GridData data = (GridData) fSortOrderList.getListControl(null)
+ .getLayoutData();
+ data.grabExcessHorizontalSpace = true;
+ data.verticalAlignment = 0;
+ data.heightHint = SWTUtil.getTableHeightHint(fSortOrderList
+ .getTableViewer().getTable(), 8);
+ }
+
+ /*
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ String string = getPreferenceStore().getDefaultString(
+ PREF_OUTLINE_SORT_OPTION);
+ fSortOrderList.setElements(getSortOrderList(string));
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ // reorders elements in the Outline based on selection
+ public boolean performOk() {
+ // update outline view
+
+ // save preferences
+ IPreferenceStore store = getPreferenceStore();
+
+ StringBuffer buf = new StringBuffer();
+ List curr = fSortOrderList.getElements();
+ for (Iterator iter = curr.iterator(); iter.hasNext();) {
+ String s = (String) iter.next();
+ buf.append(s);
+ buf.append(',');
+ }
+ store.setValue(PREF_OUTLINE_SORT_OPTION, buf.toString());
+ WebUI.getDefault().savePluginPreferences();
+ return true;
+ }
+
+ private class MemberSortLabelProvider extends LabelProvider {
+
+ public MemberSortLabelProvider() {
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(Object)
+ */
+ public String getText(Object element) {
+
+ if (element instanceof String) {
+ String s = (String) element;
+ if (s.equals(FIELDS)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.fields.label"); //$NON-NLS-1$
+ } else if (s.equals(CONSTRUCTORS)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.constructors.label"); //$NON-NLS-1$
+ } else if (s.equals(METHODS)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.methods.label"); //$NON-NLS-1$
+ } else if (s.equals(STATIC_FIELDS)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.staticfields.label"); //$NON-NLS-1$
+ } else if (s.equals(STATIC_METHODS)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.staticmethods.label"); //$NON-NLS-1$
+ } else if (s.equals(INIT)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.initialisers.label"); //$NON-NLS-1$
+ } else if (s.equals(STATIC_INIT)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.staticinitialisers.label"); //$NON-NLS-1$
+ } else if (s.equals(TYPES)) {
+ return PreferencesMessages
+ .getString("MembersOrderPreferencePage.types.label"); //$NON-NLS-1$
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(Object)
+ */
+ public Image getImage(Object element) {
+ // access to image registry
+ ImageDescriptorRegistry registry = WebUI
+ .getImageDescriptorRegistry();
+ ImageDescriptor descriptor = null;
+
+ if (element instanceof String) {
+ int visibility = Flags.AccPublic;
+ String s = (String) element;
+ if (s.equals(FIELDS)) {
+ // 0 will give the default field image
+ descriptor = JavaElementImageProvider
+ .getFieldImageDescriptor(false, visibility);
+ } else if (s.equals(CONSTRUCTORS)) {
+ descriptor = JavaElementImageProvider
+ .getMethodImageDescriptor(false, visibility);
+ // add a constructor adornment to the image descriptor
+ descriptor = new JavaElementImageDescriptor(descriptor,
+ JavaElementImageDescriptor.CONSTRUCTOR,
+ JavaElementImageProvider.SMALL_SIZE);
+ } else if (s.equals(METHODS)) {
+ descriptor = JavaElementImageProvider
+ .getMethodImageDescriptor(false, visibility);
+ } else if (s.equals(STATIC_FIELDS)) {
+ descriptor = JavaElementImageProvider
+ .getFieldImageDescriptor(false, visibility);
+ // add a constructor adornment to the image descriptor
+ descriptor = new JavaElementImageDescriptor(descriptor,
+ JavaElementImageDescriptor.STATIC,
+ JavaElementImageProvider.SMALL_SIZE);
+ } else if (s.equals(STATIC_METHODS)) {
+ descriptor = JavaElementImageProvider
+ .getMethodImageDescriptor(false, visibility);
+ // add a constructor adornment to the image descriptor
+ descriptor = new JavaElementImageDescriptor(descriptor,
+ JavaElementImageDescriptor.STATIC,
+ JavaElementImageProvider.SMALL_SIZE);
+ } else if (s.equals(INIT)) {
+ descriptor = JavaElementImageProvider
+ .getMethodImageDescriptor(false, visibility);
+ } else if (s.equals(STATIC_INIT)) {
+ descriptor = JavaElementImageProvider
+ .getMethodImageDescriptor(false, visibility);
+ descriptor = new JavaElementImageDescriptor(descriptor,
+ JavaElementImageDescriptor.STATIC,
+ JavaElementImageProvider.SMALL_SIZE);
+ } else if (s.equals(TYPES)) {
+ descriptor = JavaElementImageProvider
+ .getTypeImageDescriptor(false, true,
+ Flags.AccPublic);
+ } else {
+ descriptor = JavaElementImageProvider
+ .getMethodImageDescriptor(false, Flags.AccPublic);
+ }
+ return registry.get(descriptor);
+ }
+ return null;
+ }
+
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MockupPreferenceStore.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MockupPreferenceStore.java
new file mode 100644
index 0000000..bb54cd6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/MockupPreferenceStore.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * Mockup preference store, for registering listeners and firing events, without
+ * being an actual store.
+ * true
iff the file exists and can be opened,
+ * false
otherwise
+ */
+ protected static IStatus validateAbsoluteFilePath(final String path) {
+
+ final StatusInfo status = new StatusInfo();
+ if (path.length() > 0) {
+
+ final File file = new File(path);
+ if (!file.isFile() || !file.isAbsolute() || !file.exists()
+ || !file.canRead() || !file.canWrite())
+ status.setError(PreferencesMessages
+ .getString("SpellingPreferencePage.dictionary.error")); //$NON-NLS-1$
+
+ }
+ return status;
+ }
+
+ /**
+ * Validates that the specified locale is available.
+ *
+ * @param locale
+ * The locale to validate
+ * @return The status of the validation
+ */
+ protected static IStatus validateLocale(final String locale) {
+
+ final StatusInfo status = new StatusInfo(IStatus.ERROR,
+ PreferencesMessages
+ .getString("SpellingPreferencePage.locale.error")); //$NON-NLS-1$
+ final Set locales = SpellCheckEngine.getAvailableLocales();
+
+ Locale current = null;
+ for (final Iterator iterator = locales.iterator(); iterator.hasNext();) {
+
+ current = (Locale) iterator.next();
+ if (current.toString().equals(locale))
+ return new StatusInfo();
+ }
+ return status;
+ }
+
+ /**
+ * Validates that the specified number is positive.
+ *
+ * @param number
+ * The number to validate
+ * @return The status of the validation
+ */
+ protected static IStatus validatePositiveNumber(final String number) {
+
+ final StatusInfo status = new StatusInfo();
+ if (number.length() == 0) {
+ status.setError(PreferencesMessages
+ .getString("SpellingPreferencePage.empty_threshold")); //$NON-NLS-1$
+ } else {
+ try {
+ final int value = Integer.parseInt(number);
+ if (value < 0) {
+ status
+ .setError(PreferencesMessages
+ .getFormattedString(
+ "SpellingPreferencePage.invalid_threshold", number)); //$NON-NLS-1$
+ }
+ } catch (NumberFormatException exception) {
+ status.setError(PreferencesMessages.getFormattedString(
+ "SpellingPreferencePage.invalid_threshold", number)); //$NON-NLS-1$
+ }
+ }
+ return status;
+ }
+
+ /** The dictionary path field */
+ private Text fDictionaryPath = null;
+
+ /** The status for the workspace dictionary file */
+ private IStatus fFileStatus = new StatusInfo();
+
+ /** The status for the platform locale */
+ private IStatus fLocaleStatus = new StatusInfo();
+
+ /** The status for the proposal threshold */
+ private IStatus fThresholdStatus = new StatusInfo();
+
+ /**
+ * Creates a new spelling configuration block.
+ *
+ * @param context
+ * The status change listener
+ * @param project
+ * The Java project
+ */
+ public SpellingConfigurationBlock(final IStatusChangeListener context,
+ final IJavaProject project) {
+ super(context, project, getAllKeys());
+
+ IStatus status = validateAbsoluteFilePath((String) fWorkingValues
+ .get(PREF_SPELLING_USER_DICTIONARY));
+ if (status.getSeverity() != IStatus.OK)
+ fWorkingValues.put(PREF_SPELLING_USER_DICTIONARY, ""); //$NON-NLS-1$
+
+ status = validateLocale((String) fWorkingValues
+ .get(PREF_SPELLING_LOCALE));
+ if (status.getSeverity() != IStatus.OK)
+ fWorkingValues.put(PREF_SPELLING_LOCALE, SpellCheckEngine
+ .getDefaultLocale().toString());
+ }
+
+ protected Combo addComboBox(Composite parent, String label, String key,
+ String[] values, String[] valueLabels, int indent) {
+ ControlData data = new ControlData(key, values);
+
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indent;
+
+ Label labelControl = new Label(parent, SWT.LEFT | SWT.WRAP);
+ labelControl.setText(label);
+ labelControl.setLayoutData(gd);
+
+ Combo comboBox = new Combo(parent, SWT.READ_ONLY);
+ comboBox.setItems(valueLabels);
+ comboBox.setData(data);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ comboBox.setLayoutData(gd);
+ comboBox.addSelectionListener(getSelectionListener());
+
+ fLabels.put(comboBox, labelControl);
+
+ String currValue = (String) fWorkingValues.get(key);
+ comboBox.select(data.getSelection(currValue));
+
+ fComboBoxes.add(comboBox);
+ return comboBox;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(final Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+
+ final PixelConverter converter = new PixelConverter(parent);
+
+ layout = new GridLayout();
+ layout.numColumns = 3;
+
+ final String[] trueFalse = new String[] { IPreferenceStore.TRUE,
+ IPreferenceStore.FALSE };
+
+ Group user = new Group(composite, SWT.NONE);
+ user.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.preferences.user")); //$NON-NLS-1$
+ user.setLayout(new GridLayout());
+ user.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ String label = PreferencesMessages
+ .getString("SpellingPreferencePage.enable.label"); //$NON-NLS-1$
+ final Button master = addCheckBox(user, label,
+ PREF_SPELLING_CHECK_SPELLING, trueFalse, 0);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.digits.label"); //$NON-NLS-1$
+ Control slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_DIGITS,
+ trueFalse, 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.mixed.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_MIXED, trueFalse,
+ 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.sentence.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_SENTENCE,
+ trueFalse, 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.upper.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_UPPER, trueFalse,
+ 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.url.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_URLS, trueFalse,
+ 20);
+ createSelectionDependency(master, slave);
+
+ final Group engine = new Group(composite, SWT.NONE);
+ engine.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.preferences.engine")); //$NON-NLS-1$
+ layout = new GridLayout();
+ layout.numColumns = 4;
+ engine.setLayout(layout);
+ engine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.dictionary.label"); //$NON-NLS-1$
+ final Set locales = SpellCheckEngine.getAvailableLocales();
+
+ Combo combo = addComboBox(engine, label, PREF_SPELLING_LOCALE,
+ getDictionaryCodes(locales), getDictionaryLabels(locales), 0);
+ combo.setEnabled(locales.size() > 1);
+
+ new Label(engine, SWT.NONE); // placeholder
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.workspace.dictionary.label"); //$NON-NLS-1$
+ fDictionaryPath = addTextField(engine, label,
+ PREF_SPELLING_USER_DICTIONARY, 0, 0);
+
+ Button button = new Button(engine, SWT.PUSH);
+ button.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.browse.label")); //$NON-NLS-1$
+ button.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(final SelectionEvent event) {
+ handleBrowseButtonSelected();
+ }
+ });
+ button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
+ SWTUtil.setButtonDimensionHint(button);
+
+ layout = new GridLayout();
+ layout.numColumns = 3;
+
+ Group advanced = new Group(composite, SWT.NONE);
+ advanced.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.preferences.advanced")); //$NON-NLS-1$
+ layout = new GridLayout();
+ layout.numColumns = 3;
+ advanced.setLayout(layout);
+ advanced.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.proposals.threshold"); //$NON-NLS-1$
+ Text text = addTextField(advanced, label,
+ PREF_SPELLING_PROPOSAL_THRESHOLD, 0, 0);
+ text.setTextLimit(3);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ data.widthHint = converter.convertWidthInCharsToPixels(4);
+ text.setLayoutData(data);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.enable.contentassist.label"); //$NON-NLS-1$
+ addCheckBox(advanced, label, PREF_SPELLING_ENABLE_CONTENTASSIST,
+ trueFalse, 0);
+
+ return composite;
+ }
+
+ private static String[] getAllKeys() {
+ return new String[] { PREF_SPELLING_USER_DICTIONARY,
+ PREF_SPELLING_CHECK_SPELLING, PREF_SPELLING_IGNORE_DIGITS,
+ PREF_SPELLING_IGNORE_MIXED, PREF_SPELLING_IGNORE_SENTENCE,
+ PREF_SPELLING_IGNORE_UPPER, PREF_SPELLING_IGNORE_URLS,
+ PREF_SPELLING_LOCALE, PREF_SPELLING_PROPOSAL_THRESHOLD,
+ PREF_SPELLING_ENABLE_CONTENTASSIST };
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getDefaultOptions()
+ */
+ protected Map getDefaultOptions() {
+
+ final String[] keys = fAllKeys;
+ final Map options = new HashMap();
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ options.put(keys[index], store.getDefaultString(keys[index]));
+
+ return options;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
+ */
+ protected final String[] getFullBuildDialogStrings(final boolean workspace) {
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getOptions(boolean)
+ */
+ protected Map getOptions(final boolean inherit) {
+
+ final String[] keys = fAllKeys;
+ final Map options = new HashMap();
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ options.put(keys[index], store.getString(keys[index]));
+
+ return options;
+ }
+
+ /**
+ * Handles selections of the browse button.
+ */
+ protected void handleBrowseButtonSelected() {
+
+ final FileDialog dialog = new FileDialog(fDictionaryPath.getShell(),
+ SWT.OPEN);
+ dialog.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.filedialog.title")); //$NON-NLS-1$
+ dialog
+ .setFilterExtensions(new String[] {
+ PreferencesMessages
+ .getString("SpellingPreferencePage.filter.dictionary.extension"), PreferencesMessages.getString("SpellingPreferencePage.filter.all.extension") }); //$NON-NLS-1$ //$NON-NLS-2$
+ dialog
+ .setFilterNames(new String[] {
+ PreferencesMessages
+ .getString("SpellingPreferencePage.filter.dictionary.label"), PreferencesMessages.getString("SpellingPreferencePage.filter.all.label") }); //$NON-NLS-1$ //$NON-NLS-2$
+
+ final String path = dialog.open();
+ if (path != null)
+ fDictionaryPath.setText(path);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#setOptions(java.util.Map)
+ */
+ protected void setOptions(final Map options) {
+
+ final String[] keys = fAllKeys;
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ store.setValue(keys[index], (String) fWorkingValues
+ .get(keys[index]));
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(java.lang.String,java.lang.String)
+ */
+ protected void validateSettings(final String key, final String value) {
+
+ if (key == null || PREF_SPELLING_PROPOSAL_THRESHOLD.equals(key))
+ fThresholdStatus = validatePositiveNumber((String) fWorkingValues
+ .get(PREF_SPELLING_PROPOSAL_THRESHOLD));
+
+ if (key == null || PREF_SPELLING_USER_DICTIONARY.equals(key))
+ fFileStatus = validateAbsoluteFilePath((String) fWorkingValues
+ .get(PREF_SPELLING_USER_DICTIONARY));
+
+ if (key == null || PREF_SPELLING_LOCALE.equals(key))
+ fLocaleStatus = validateLocale((String) fWorkingValues
+ .get(PREF_SPELLING_LOCALE));
+
+ fContext.statusChanged(StatusUtil.getMostSevere(new IStatus[] {
+ fThresholdStatus, fFileStatus, fLocaleStatus }));
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/SpellingPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/SpellingPreferencePage.java
new file mode 100644
index 0000000..8f7010b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/SpellingPreferencePage.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Preference page for spell checking preferences.
+ *
+ * @since 3.0
+ */
+public class SpellingPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage, IStatusChangeListener {
+
+ /** The spelling configuration block */
+ private final SpellingConfigurationBlock fBlock = new SpellingConfigurationBlock(
+ this, null);
+
+ /**
+ * Creates a new spelling preference page.
+ */
+ public SpellingPreferencePage() {
+
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+ setDescription(PreferencesMessages
+ .getString("SpellingPreferencePage.description")); //$NON-NLS-1$
+ setTitle(PreferencesMessages.getString("SpellingPreferencePage.title")); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(final Composite parent) {
+
+ final Control control = fBlock.createContents(parent);
+ Dialog.applyDialogFont(control);
+
+ return control;
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(final Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.JAVA_EDITOR_PREFERENCE_PAGE);
+ }
+
+ /*
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(final IWorkbench workbench) {
+ // Do nothing
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ fBlock.performDefaults();
+
+ super.performDefaults();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+
+ if (!fBlock.performOk(true))
+ return false;
+
+ return super.performOk();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus)
+ */
+ public void statusChanged(final IStatus status) {
+ setValid(!status.matches(IStatus.ERROR));
+
+ StatusUtil.applyToStatusLine(this, status);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TemplateEditorSourceViewerConfiguration.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TemplateEditorSourceViewerConfiguration.java
new file mode 100644
index 0000000..439288a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TemplateEditorSourceViewerConfiguration.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder;
+import net.sourceforge.phpdt.internal.ui.text.template.preferences.TemplateVariableProcessor;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+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.source.ISourceViewer;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateVariableResolver;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+public class TemplateEditorSourceViewerConfiguration extends
+ PHPSourceViewerConfiguration {
+
+ private static class TemplateVariableTextHover implements ITextHover {
+
+ private TemplateVariableProcessor fProcessor;
+
+ /**
+ * @param type
+ */
+ 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 JavaWordFinder
+ .findWord(textViewer.getDocument(), offset);
+ }
+ return null;
+ }
+
+ }
+
+ private final TemplateVariableProcessor fProcessor;
+
+ public TemplateEditorSourceViewerConfiguration(IColorManager colorManager,
+ IPreferenceStore store, ITextEditor editor,
+ TemplateVariableProcessor processor) {
+ super(colorManager, store, editor, IPHPPartitions.PHP_PARTITIONING);
+ fProcessor = processor;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getContentAssistant(ISourceViewer)
+ */
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ JavaTextTools textTools = WebUI.getDefault()
+ .getJavaTextTools();
+ IColorManager manager = textTools.getColorManager();
+
+ 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,
+ IPHPPartitions.PHP_STRING_DQ);
+ assistant.setContentAssistProcessor(fProcessor,
+ IPHPPartitions.PHP_STRING_SQ);
+ assistant.setContentAssistProcessor(fProcessor,
+ IPHPPartitions.PHP_STRING_HEREDOC);
+ assistant.setContentAssistProcessor(fProcessor,
+ IPHPPartitions.PHP_SINGLELINE_COMMENT);
+ assistant.setContentAssistProcessor(fProcessor,
+ IPHPPartitions.PHP_MULTILINE_COMMENT);
+ assistant.setContentAssistProcessor(fProcessor,
+ IPHPPartitions.PHP_PHPDOC_COMMENT);
+
+ assistant.enableAutoInsert(store
+ .getBoolean(PreferenceConstants.CODEASSIST_AUTOINSERT));
+ assistant.enableAutoActivation(store
+ .getBoolean(PreferenceConstants.CODEASSIST_AUTOACTIVATION));
+ assistant.setAutoActivationDelay(store
+ .getInt(PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY));
+ assistant
+ .setProposalPopupOrientation(ContentAssistant.PROPOSAL_OVERLAY);
+ assistant
+ .setContextInformationPopupOrientation(ContentAssistant.CONTEXT_INFO_ABOVE);
+ assistant
+ .setInformationControlCreator(getInformationControlCreator(sourceViewer));
+
+ Color background = getColor(store,
+ PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND, manager);
+ assistant.setContextInformationPopupBackground(background);
+ assistant.setContextSelectorBackground(background);
+ assistant.setProposalSelectorBackground(background);
+
+ Color foreground = getColor(store,
+ PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND, manager);
+ assistant.setContextInformationPopupForeground(foreground);
+ assistant.setContextSelectorForeground(foreground);
+ assistant.setProposalSelectorForeground(foreground);
+
+ return assistant;
+ }
+
+ private Color getColor(IPreferenceStore store, String key,
+ IColorManager manager) {
+ RGB rgb = PreferenceConverter.getColor(store, key);
+ return manager.getColor(rgb);
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getTextHover(ISourceViewer, String, int)
+ * @since 2.1
+ */
+ public ITextHover getTextHover(ISourceViewer sourceViewer,
+ String contentType, int stateMask) {
+ return new TemplateVariableTextHover(fProcessor);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskConfigurationBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskConfigurationBlock.java
new file mode 100644
index 0000000..e487226
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskConfigurationBlock.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IListAdapter;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.ListDialogField;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+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;
+
+/**
+ */
+public class TodoTaskConfigurationBlock extends OptionsConfigurationBlock {
+
+ private static final String PREF_COMPILER_TASK_TAGS = JavaCore.COMPILER_TASK_TAGS;
+
+ private static final String PREF_COMPILER_TASK_PRIORITIES = JavaCore.COMPILER_TASK_PRIORITIES;
+
+ private static final String PRIORITY_HIGH = JavaCore.COMPILER_TASK_PRIORITY_HIGH;
+
+ private static final String PRIORITY_NORMAL = JavaCore.COMPILER_TASK_PRIORITY_NORMAL;
+
+ private static final String PRIORITY_LOW = JavaCore.COMPILER_TASK_PRIORITY_LOW;
+
+ public static class TodoTask {
+ public String name;
+
+ public String priority;
+ }
+
+ private static class TodoTaskLabelProvider extends LabelProvider implements
+ ITableLabelProvider {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ return null; // JavaPluginImages.get(JavaPluginImages.IMG_OBJS_REFACTORING_INFO);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ return getColumnText(element, 0);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object,
+ * int)
+ */
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object,
+ * int)
+ */
+ public String getColumnText(Object element, int columnIndex) {
+ TodoTask task = (TodoTask) element;
+ if (columnIndex == 0) {
+ return task.name;
+ } else {
+ if (PRIORITY_HIGH.equals(task.priority)) {
+ return PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.high.priority"); //$NON-NLS-1$
+ } else if (PRIORITY_NORMAL.equals(task.priority)) {
+ return PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.normal.priority"); //$NON-NLS-1$
+ } else if (PRIORITY_LOW.equals(task.priority)) {
+ return PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.low.priority"); //$NON-NLS-1$
+ }
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ }
+
+ private static final int IDX_ADD = 0;
+
+ private static final int IDX_EDIT = 1;
+
+ private static final int IDX_REMOVE = 2;
+
+ private IStatus fTaskTagsStatus;
+
+ private ListDialogField fTodoTasksList;
+
+ public TodoTaskConfigurationBlock(IStatusChangeListener context,
+ IJavaProject project) {
+ super(context, project, getKeys());
+
+ TaskTagAdapter adapter = new TaskTagAdapter();
+ String[] buttons = new String[] {
+ /* 0 */PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.add.button"), //$NON-NLS-1$
+ /* 1 */PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.edit.button"), //$NON-NLS-1$
+ /* 2 */PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.remove.button"), //$NON-NLS-1$
+
+ };
+ fTodoTasksList = new ListDialogField(adapter, buttons,
+ new TodoTaskLabelProvider());
+ fTodoTasksList.setDialogFieldListener(adapter);
+ fTodoTasksList.setLabelText(PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.label")); //$NON-NLS-1$
+ fTodoTasksList.setRemoveButtonIndex(IDX_REMOVE);
+
+ String[] columnsHeaders = new String[] {
+ PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.name.column"), //$NON-NLS-1$
+ PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.markers.tasks.priority.column"), //$NON-NLS-1$
+ };
+
+ fTodoTasksList.setTableColumns(new ListDialogField.ColumnsDescription(
+ columnsHeaders, true));
+ unpackTodoTasks();
+ if (fTodoTasksList.getSize() > 0) {
+ fTodoTasksList.selectFirstElement();
+ } else {
+ fTodoTasksList.enableButton(IDX_EDIT, false);
+ }
+
+ fTaskTagsStatus = new StatusInfo();
+ }
+
+ private final static String[] getKeys() {
+ return new String[] { PREF_COMPILER_TASK_TAGS,
+ PREF_COMPILER_TASK_PRIORITIES };
+ }
+
+ public class TaskTagAdapter implements IListAdapter, IDialogFieldListener {
+
+ private boolean canEdit(ListDialogField field) {
+ return field.getSelectedElements().size() == 1;
+ }
+
+ public void customButtonPressed(ListDialogField field, int index) {
+ doTodoButtonPressed(index);
+ }
+
+ public void selectionChanged(ListDialogField field) {
+ field.enableButton(IDX_EDIT, canEdit(field));
+ }
+
+ public void doubleClicked(ListDialogField field) {
+ if (canEdit(field)) {
+ doTodoButtonPressed(IDX_EDIT);
+ }
+ }
+
+ public void dialogFieldChanged(DialogField field) {
+ validateSettings(PREF_COMPILER_TASK_TAGS, null);
+ }
+
+ }
+
+ protected Control createContents(Composite parent) {
+ setShell(parent.getShell());
+
+ Composite markersComposite = createMarkersTabContent(parent);
+
+ validateSettings(null, null);
+
+ return markersComposite;
+ }
+
+ private Composite createMarkersTabContent(Composite folder) {
+
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+
+ Composite markersComposite = new Composite(folder, SWT.NULL);
+ markersComposite.setLayout(layout);
+
+ fTodoTasksList.doFillIntoGrid(markersComposite, 3);
+ LayoutUtil.setHorizontalSpan(fTodoTasksList.getLabelControl(null), 2);
+
+ GridData data = (GridData) fTodoTasksList.getListControl(null)
+ .getLayoutData();
+ data.grabExcessHorizontalSpace = true;
+ data.grabExcessVerticalSpace = true;
+ data.verticalAlignment = GridData.FILL;
+ // data.heightHint= SWTUtil.getTableHeightHint(table, 6);
+
+ return markersComposite;
+ }
+
+ protected void validateSettings(String changedKey, String newValue) {
+ if (changedKey != null) {
+ if (PREF_COMPILER_TASK_TAGS.equals(changedKey)) {
+ fTaskTagsStatus = validateTaskTags();
+ } else {
+ return;
+ }
+ } else {
+ fTaskTagsStatus = validateTaskTags();
+ }
+ IStatus status = fTaskTagsStatus; // StatusUtil.getMostSevere(new
+ // IStatus[] { fTaskTagsStatus });
+ fContext.statusChanged(status);
+ }
+
+ private IStatus validateTaskTags() {
+ return new StatusInfo();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#performOk(boolean)
+ */
+ public boolean performOk(boolean enabled) {
+ packTodoTasks();
+ return super.performOk(enabled);
+ }
+
+ protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
+ String title = PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.needsbuild.title"); //$NON-NLS-1$
+ String message;
+ if (fProject == null) {
+ message = PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.needsfullbuild.message"); //$NON-NLS-1$
+ } else {
+ message = PreferencesMessages
+ .getString("TodoTaskConfigurationBlock.needsprojectbuild.message"); //$NON-NLS-1$
+ }
+ return new String[] { title, message };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls()
+ */
+ protected void updateControls() {
+ unpackTodoTasks();
+ }
+
+ private void unpackTodoTasks() {
+ String currTags = (String) fWorkingValues.get(PREF_COMPILER_TASK_TAGS);
+ String currPrios = (String) fWorkingValues
+ .get(PREF_COMPILER_TASK_PRIORITIES);
+ String[] tags = getTokens(currTags, ","); //$NON-NLS-1$
+ String[] prios = getTokens(currPrios, ","); //$NON-NLS-1$
+ ArrayList elements = new ArrayList(tags.length);
+ for (int i = 0; i < tags.length; i++) {
+ TodoTask task = new TodoTask();
+ task.name = tags[i].trim();
+ task.priority = (i < prios.length) ? prios[i] : PRIORITY_NORMAL;
+ elements.add(task);
+ }
+ fTodoTasksList.setElements(elements);
+ }
+
+ private void packTodoTasks() {
+ StringBuffer tags = new StringBuffer();
+ StringBuffer prios = new StringBuffer();
+ List list = fTodoTasksList.getElements();
+ for (int i = 0; i < list.size(); i++) {
+ if (i > 0) {
+ tags.append(',');
+ prios.append(',');
+ }
+ TodoTask elem = (TodoTask) list.get(i);
+ tags.append(elem.name);
+ prios.append(elem.priority);
+ }
+ fWorkingValues.put(PREF_COMPILER_TASK_TAGS, tags.toString());
+ fWorkingValues.put(PREF_COMPILER_TASK_PRIORITIES, prios.toString());
+ }
+
+ private void doTodoButtonPressed(int index) {
+ TodoTask edited = null;
+ if (index != IDX_ADD) {
+ edited = (TodoTask) fTodoTasksList.getSelectedElements().get(0);
+ }
+
+ TodoTaskInputDialog dialog = new TodoTaskInputDialog(getShell(),
+ edited, fTodoTasksList.getElements());
+ if (dialog.open() == Window.OK) {
+ if (edited != null) {
+ fTodoTasksList.replaceElement(edited, dialog.getResult());
+ } else {
+ fTodoTasksList.addElement(dialog.getResult());
+ }
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskInputDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskInputDialog.java
new file mode 100644
index 0000000..0d6effb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskInputDialog.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusDialog;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.preferences.TodoTaskConfigurationBlock.TodoTask;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.ComboDialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.StringDialogField;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Dialog to enter a na new task tag
+ */
+public class TodoTaskInputDialog extends StatusDialog {
+
+ private class CompilerTodoTaskInputAdapter implements IDialogFieldListener {
+ public void dialogFieldChanged(DialogField field) {
+ doValidation();
+ }
+ }
+
+ private StringDialogField fNameDialogField;
+
+ private ComboDialogField fPriorityDialogField;
+
+ private List fExistingNames;
+
+ public TodoTaskInputDialog(Shell parent, TodoTask task, List existingEntries) {
+ super(parent);
+
+ fExistingNames = new ArrayList(existingEntries.size());
+ for (int i = 0; i < existingEntries.size(); i++) {
+ TodoTask curr = (TodoTask) existingEntries.get(i);
+ if (!curr.equals(task)) {
+ fExistingNames.add(curr.name);
+ }
+ }
+
+ if (task == null) {
+ setTitle(PreferencesMessages
+ .getString("TodoTaskInputDialog.new.title")); //$NON-NLS-1$
+ } else {
+ setTitle(PreferencesMessages
+ .getString("TodoTaskInputDialog.edit.title")); //$NON-NLS-1$
+ }
+
+ CompilerTodoTaskInputAdapter adapter = new CompilerTodoTaskInputAdapter();
+
+ fNameDialogField = new StringDialogField();
+ fNameDialogField.setLabelText(PreferencesMessages
+ .getString("TodoTaskInputDialog.name.label")); //$NON-NLS-1$
+ fNameDialogField.setDialogFieldListener(adapter);
+
+ fNameDialogField.setText((task != null) ? task.name : ""); //$NON-NLS-1$
+
+ String[] items = new String[] {
+ PreferencesMessages
+ .getString("TodoTaskInputDialog.priority.high"), //$NON-NLS-1$
+ PreferencesMessages
+ .getString("TodoTaskInputDialog.priority.normal"), //$NON-NLS-1$
+ PreferencesMessages
+ .getString("TodoTaskInputDialog.priority.low") //$NON-NLS-1$
+ };
+
+ fPriorityDialogField = new ComboDialogField(SWT.READ_ONLY);
+ fPriorityDialogField.setLabelText(PreferencesMessages
+ .getString("TodoTaskInputDialog.priority.label")); //$NON-NLS-1$
+ fPriorityDialogField.setItems(items);
+ if (task != null) {
+ if (JavaCore.COMPILER_TASK_PRIORITY_HIGH.equals(task.priority)) {
+ fPriorityDialogField.selectItem(0);
+ } else if (JavaCore.COMPILER_TASK_PRIORITY_NORMAL
+ .equals(task.priority)) {
+ fPriorityDialogField.selectItem(1);
+ } else {
+ fPriorityDialogField.selectItem(2);
+ }
+ } else {
+ fPriorityDialogField.selectItem(1);
+ }
+ }
+
+ public TodoTask getResult() {
+ TodoTask task = new TodoTask();
+ task.name = fNameDialogField.getText().trim();
+ switch (fPriorityDialogField.getSelectionIndex()) {
+ case 0:
+ task.priority = JavaCore.COMPILER_TASK_PRIORITY_HIGH;
+ break;
+ case 1:
+ task.priority = JavaCore.COMPILER_TASK_PRIORITY_NORMAL;
+ break;
+ default:
+ task.priority = JavaCore.COMPILER_TASK_PRIORITY_LOW;
+ break;
+ }
+ return task;
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ Composite inner = new Composite(composite, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ inner.setLayout(layout);
+
+ fNameDialogField.doFillIntoGrid(inner, 2);
+ fPriorityDialogField.doFillIntoGrid(inner, 2);
+
+ LayoutUtil.setHorizontalGrabbing(fNameDialogField.getTextControl(null));
+ LayoutUtil.setWidthHint(fNameDialogField.getTextControl(null),
+ convertWidthInCharsToPixels(45));
+
+ fNameDialogField.postSetFocusOnDialogField(parent.getDisplay());
+
+ applyDialogFont(composite);
+ return composite;
+ }
+
+ private void doValidation() {
+ StatusInfo status = new StatusInfo();
+ String newText = fNameDialogField.getText();
+ if (newText.length() == 0) {
+ status.setError(PreferencesMessages
+ .getString("TodoTaskInputDialog.error.enterName")); //$NON-NLS-1$
+ } else {
+ if (newText.indexOf(',') != -1) {
+ status.setError(PreferencesMessages
+ .getString("TodoTaskInputDialog.error.comma")); //$NON-NLS-1$
+ } else if (fExistingNames.contains(newText)) {
+ status.setError(PreferencesMessages
+ .getString("TodoTaskInputDialog.error.entryExists")); //$NON-NLS-1$
+ } else if (Character.isWhitespace(newText.charAt(0))
+ || Character.isWhitespace(newText
+ .charAt(newText.length() - 1))) {
+ status.setError(PreferencesMessages
+ .getString("TodoTaskInputDialog.error.noSpace")); //$NON-NLS-1$
+ }
+ }
+ updateStatus(status);
+ }
+
+ /*
+ * @see org.eclipse.jface.window.Window#configureShell(Shell)
+ */
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
+ IJavaHelpContextIds.TODO_TASK_INPUT_DIALOG);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskPreferencePage.java
new file mode 100644
index 0000000..3667bdc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskPreferencePage.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+
+/*
+ * The page to configure the compiler options.
+ */
+public class TodoTaskPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage, IStatusChangeListener {
+
+ public static final String ID = "net.sourceforge.phpdt.ui.preferences.TodoTaskPreferencePage"; //$NON-NLS-1$
+
+ private TodoTaskConfigurationBlock fConfigurationBlock;
+
+ public TodoTaskPreferencePage() {
+ setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+ // setDescription(PreferencesMessages.getString("TodoTaskPreferencePage.description"));
+ // //$NON-NLS-1$
+
+ // only used when page is shown programatically
+ setTitle(PreferencesMessages.getString("TodoTaskPreferencePage.title")); //$NON-NLS-1$
+
+ fConfigurationBlock = new TodoTaskConfigurationBlock(this, null);
+ }
+
+ /*
+ * @see IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * @see PreferencePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ // added for 1GEUGE6: ITPJUI:WIN2000 - Help is the same on all
+ // preference pages
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.TODOTASK_PREFERENCE_PAGE);
+ }
+
+ /*
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ Control result = fConfigurationBlock.createContents(parent);
+ Dialog.applyDialogFont(result);
+ return result;
+ }
+
+ /*
+ * @see IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ if (!fConfigurationBlock.performOk(true)) {
+ return false;
+ }
+ return super.performOk();
+ }
+
+ /*
+ * @see PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ fConfigurationBlock.performDefaults();
+ super.performDefaults();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus)
+ */
+ public void statusChanged(IStatus status) {
+ setValid(!status.matches(IStatus.ERROR));
+ StatusUtil.applyToStatusLine(this, status);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskPropertyPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskPropertyPage.java
new file mode 100644
index 0000000..b9395f4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/preferences/TodoTaskPropertyPage.java
@@ -0,0 +1,234 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.ControlEnableState;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.IPreferenceNode;
+import org.eclipse.jface.preference.IPreferencePage;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.preference.PreferenceManager;
+import org.eclipse.jface.preference.PreferenceNode;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+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.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Property page used to configure project specific task tags settings
+ */
+public class TodoTaskPropertyPage extends PropertyPage {
+
+ private TodoTaskConfigurationBlock fConfigurationBlock;
+
+ private Control fConfigurationBlockControl;
+
+ private ControlEnableState fBlockEnableState;
+
+ private SelectionButtonDialogField fUseWorkspaceSettings;
+
+ private SelectionButtonDialogField fChangeWorkspaceSettings;
+
+ private SelectionButtonDialogField fUseProjectSettings;
+
+ private IStatus fBlockStatus;
+
+ public TodoTaskPropertyPage() {
+ fBlockStatus = new StatusInfo();
+ fBlockEnableState = null;
+
+ IDialogFieldListener listener = new IDialogFieldListener() {
+ public void dialogFieldChanged(DialogField field) {
+ doDialogFieldChanged(field);
+ }
+ };
+
+ fUseWorkspaceSettings = new SelectionButtonDialogField(SWT.RADIO);
+ fUseWorkspaceSettings.setDialogFieldListener(listener);
+ fUseWorkspaceSettings.setLabelText(PreferencesMessages
+ .getString("TodoTaskPropertyPage.useworkspacesettings.label")); //$NON-NLS-1$
+
+ fChangeWorkspaceSettings = new SelectionButtonDialogField(SWT.PUSH);
+ fChangeWorkspaceSettings.setLabelText(PreferencesMessages
+ .getString("TodoTaskPropertyPage.useworkspacesettings.change")); //$NON-NLS-1$
+ fChangeWorkspaceSettings.setDialogFieldListener(listener);
+
+ fUseWorkspaceSettings.attachDialogField(fChangeWorkspaceSettings);
+
+ fUseProjectSettings = new SelectionButtonDialogField(SWT.RADIO);
+ fUseProjectSettings.setDialogFieldListener(listener);
+ fUseProjectSettings.setLabelText(PreferencesMessages
+ .getString("TodoTaskPropertyPage.useprojectsettings.label")); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+ IJavaHelpContextIds.TODOTASK_PROPERTY_PAGE);
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ IStatusChangeListener listener = new IStatusChangeListener() {
+ public void statusChanged(IStatus status) {
+ fBlockStatus = status;
+ doStatusChanged();
+ }
+ };
+ fConfigurationBlock = new TodoTaskConfigurationBlock(listener,
+ getProject());
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+
+ fUseWorkspaceSettings.doFillIntoGrid(composite, 1);
+ LayoutUtil.setHorizontalGrabbing(fUseWorkspaceSettings
+ .getSelectionButton(null));
+
+ fChangeWorkspaceSettings.doFillIntoGrid(composite, 1);
+ GridData data = (GridData) fChangeWorkspaceSettings.getSelectionButton(
+ null).getLayoutData();
+ data.horizontalIndent = convertWidthInCharsToPixels(3);
+ data.horizontalAlignment = GridData.BEGINNING;
+
+ fUseProjectSettings.doFillIntoGrid(composite, 1);
+
+ data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.VERTICAL_ALIGN_FILL);
+ data.horizontalSpan = 1;
+ data.horizontalIndent = convertWidthInCharsToPixels(2);
+
+ fConfigurationBlockControl = fConfigurationBlock
+ .createContents(composite);
+ fConfigurationBlockControl.setLayoutData(data);
+
+ boolean useProjectSettings = fConfigurationBlock
+ .hasProjectSpecificOptions();
+
+ fUseProjectSettings.setSelection(useProjectSettings);
+ fUseWorkspaceSettings.setSelection(!useProjectSettings);
+
+ updateEnableState();
+ Dialog.applyDialogFont(composite);
+ return composite;
+ }
+
+ private boolean useProjectSettings() {
+ return fUseProjectSettings.isSelected();
+ }
+
+ private void doDialogFieldChanged(DialogField field) {
+ if (field == fChangeWorkspaceSettings) {
+ TodoTaskPreferencePage page = new TodoTaskPreferencePage();
+ showPreferencePage(TodoTaskPreferencePage.ID, page);
+ } else {
+ updateEnableState();
+ doStatusChanged();
+ }
+ }
+
+ /**
+ * Method statusChanged.
+ */
+ private void doStatusChanged() {
+ updateStatus(useProjectSettings() ? fBlockStatus : new StatusInfo());
+ }
+
+ /**
+ * Method getProject.
+ */
+ private IJavaProject getProject() {
+ return (IJavaProject) getElement().getAdapter(IJavaElement.class);
+ }
+
+ private void updateEnableState() {
+ if (useProjectSettings()) {
+ if (fBlockEnableState != null) {
+ fBlockEnableState.restore();
+ fBlockEnableState = null;
+ }
+ } else {
+ if (fBlockEnableState == null) {
+ fBlockEnableState = ControlEnableState
+ .disable(fConfigurationBlockControl);
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ if (useProjectSettings()) {
+ fUseProjectSettings.setSelection(false);
+ fUseWorkspaceSettings.setSelection(true);
+ fConfigurationBlock.performDefaults();
+ }
+ super.performDefaults();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ return fConfigurationBlock.performOk(useProjectSettings());
+ }
+
+ private void updateStatus(IStatus status) {
+ setValid(!status.matches(IStatus.ERROR));
+ StatusUtil.applyToStatusLine(this, status);
+ }
+
+ private boolean showPreferencePage(String id, IPreferencePage page) {
+ final IPreferenceNode targetNode = new PreferenceNode(id, page);
+
+ PreferenceManager manager = new PreferenceManager();
+ manager.addToRoot(targetNode);
+ final PreferenceDialog dialog = new PreferenceDialog(getShell(),
+ manager);
+ final boolean[] result = new boolean[] { false };
+ BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
+ public void run() {
+ dialog.create();
+ dialog.setMessage(targetNode.getLabelText());
+ result[0] = (dialog.open() == Window.OK);
+ }
+ });
+ return result[0];
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/AbstractJavaScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/AbstractJavaScanner.java
new file mode 100644
index 0000000..0aa214b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/AbstractJavaScanner.java
@@ -0,0 +1,183 @@
+package net.sourceforge.phpdt.internal.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpdt.ui.text.IColorManagerExtension;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.resource.StringConverter;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Initialized with a color manager and a preference store, its subclasses are
+ * only responsible for providing a list of preference keys based on which
+ * tokens are generated and to use this tokens to define the rules controlling
+ * this scanner.
+ */
+public abstract class AbstractJavaScanner extends BufferedRuleBasedScanner {
+
+ private IColorManager fColorManager;
+
+ private IPreferenceStore fPreferenceStore;
+
+ private Map fTokenMap = new HashMap();
+
+ private String[] fPropertyNamesColor;
+
+ private String[] fPropertyNamesStyle;
+
+ /**
+ * Returns the list of preference keys which define the tokens used in the
+ * rules of this scanner.
+ */
+ abstract protected String[] getTokenProperties();
+
+ /**
+ * Creates the list of rules controlling this scanner.
+ */
+ abstract protected List createRules();
+
+ /**
+ * Creates an abstract Java scanner.
+ */
+ public AbstractJavaScanner(IColorManager manager, IPreferenceStore store) {
+ super();
+ fColorManager = manager;
+ fPreferenceStore = store;
+ }
+
+ /**
+ * Must be called after the constructor has been called.
+ */
+ public final void initialize() {
+
+ fPropertyNamesColor = getTokenProperties();
+ int length = fPropertyNamesColor.length;
+ fPropertyNamesStyle = new String[length];
+ for (int i = 0; i < length; i++) {
+ fPropertyNamesStyle[i] = fPropertyNamesColor[i] + "_bold"; //$NON-NLS-1$
+ addToken(fPropertyNamesColor[i], fPropertyNamesStyle[i]);
+ }
+
+ initializeRules();
+ }
+
+ private void addToken(String colorKey, String styleKey) {
+ RGB rgb = PreferenceConverter.getColor(fPreferenceStore, colorKey);
+ if (fColorManager instanceof IColorManagerExtension) {
+ IColorManagerExtension ext = (IColorManagerExtension) fColorManager;
+ ext.unbindColor(colorKey);
+ ext.bindColor(colorKey, rgb);
+ }
+
+ boolean bold = fPreferenceStore.getBoolean(styleKey);
+ fTokenMap.put(colorKey, new Token(new TextAttribute(fColorManager
+ .getColor(colorKey), null, bold ? SWT.BOLD : SWT.NORMAL)));
+ }
+
+ protected Token getToken(String key) {
+ return (Token) fTokenMap.get(key);
+ }
+
+ private void initializeRules() {
+ List rules = createRules();
+ if (rules != null) {
+ IRule[] result = new IRule[rules.size()];
+ rules.toArray(result);
+ setRules(result);
+ }
+ }
+
+ private int indexOf(String property) {
+ if (property != null) {
+ int length = fPropertyNamesColor.length;
+ for (int i = 0; i < length; i++) {
+ if (property.equals(fPropertyNamesColor[i])
+ || property.equals(fPropertyNamesStyle[i]))
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public boolean affectsBehavior(PropertyChangeEvent event) {
+ return indexOf(event.getProperty()) >= 0;
+ }
+
+ public void adaptToPreferenceChange(PropertyChangeEvent event) {
+ String p = event.getProperty();
+ int index = indexOf(p);
+ Token token = getToken(fPropertyNamesColor[index]);
+ if (fPropertyNamesColor[index].equals(p))
+ adaptToColorChange(token, event);
+ else
+ adaptToStyleChange(token, event);
+ }
+
+ private void adaptToColorChange(Token token, PropertyChangeEvent event) {
+ RGB rgb = null;
+
+ Object value = event.getNewValue();
+ if (value instanceof RGB)
+ rgb = (RGB) value;
+ else if (value instanceof String)
+ rgb = StringConverter.asRGB((String) value);
+
+ if (rgb != null) {
+
+ String property = event.getProperty();
+
+ if (fColorManager instanceof IColorManagerExtension) {
+ IColorManagerExtension ext = (IColorManagerExtension) fColorManager;
+ ext.unbindColor(property);
+ ext.bindColor(property, rgb);
+ }
+
+ Object data = token.getData();
+ if (data instanceof TextAttribute) {
+ TextAttribute oldAttr = (TextAttribute) data;
+ token.setData(new TextAttribute(fColorManager
+ .getColor(property), oldAttr.getBackground(), oldAttr
+ .getStyle()));
+ }
+ }
+ }
+
+ private void adaptToStyleChange(Token token, PropertyChangeEvent event) {
+ boolean bold = false;
+ Object value = event.getNewValue();
+ if (value instanceof Boolean)
+ bold = ((Boolean) value).booleanValue();
+ else if (value instanceof String) {
+ String s = (String) value;
+ if (IPreferenceStore.TRUE.equals(s))
+ bold = true;
+ else if (IPreferenceStore.FALSE.equals(s))
+ bold = false;
+ }
+
+ Object data = token.getData();
+ if (data instanceof TextAttribute) {
+ TextAttribute oldAttr = (TextAttribute) data;
+ boolean isBold = (oldAttr.getStyle() == SWT.BOLD);
+ if (isBold != bold)
+ token.setData(new TextAttribute(oldAttr.getForeground(),
+ oldAttr.getBackground(), bold ? SWT.BOLD : SWT.NORMAL));
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/BufferedDocumentScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/BufferedDocumentScanner.java
new file mode 100644
index 0000000..cd6833f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/BufferedDocumentScanner.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+
+/**
+ * A buffered document scanner. The buffer always contains a section of a fixed
+ * size of the document to be scanned.
+ */
+
+public final class BufferedDocumentScanner implements ICharacterScanner {
+
+ /** The document being scanned. */
+ private IDocument fDocument;
+
+ /** The offset of the document range to scan. */
+ private int fRangeOffset;
+
+ /** The length of the document range to scan. */
+ private int fRangeLength;
+
+ /** The delimiters of the document. */
+ private char[][] fDelimiters;
+
+ /** The buffer. */
+ private final char[] fBuffer;
+
+ /** The offset of the buffer within the document. */
+ private int fBufferOffset;
+
+ /** The valid length of the buffer for access. */
+ private int fBufferLength;
+
+ /** The offset of the scanner within the buffer. */
+ private int fOffset;
+
+ /**
+ * Creates a new buffered document scanner. The buffer size is set to the
+ * given number of characters.
+ *
+ * @param size
+ * the buffer size
+ */
+ public BufferedDocumentScanner(int size) {
+ Assert.isTrue(size >= 1);
+ fBuffer = new char[size];
+ }
+
+ /**
+ * Fills the buffer with the contens of the document starting at the given
+ * offset.
+ *
+ * @param offset
+ * the document offset at which the buffer starts
+ */
+ private final void updateBuffer(int offset) {
+
+ fBufferOffset = offset;
+
+ if (fBufferOffset + fBuffer.length > fRangeOffset + fRangeLength)
+ fBufferLength = fRangeLength - (fBufferOffset - fRangeOffset);
+ else
+ fBufferLength = fBuffer.length;
+
+ try {
+ final String content = fDocument.get(fBufferOffset, fBufferLength);
+ if (content != null) {
+ content.getChars(0, fBufferLength, fBuffer, 0);
+ }
+ } catch (BadLocationException e) {
+ }
+ }
+
+ /**
+ * Configures the scanner by providing access to the document range over
+ * which to scan.
+ *
+ * @param document
+ * the document to scan
+ * @param offset
+ * the offset of the document range to scan
+ * @param length
+ * the length of the document range to scan
+ */
+ public final void setRange(IDocument document, int offset, int length) {
+
+ fDocument = document;
+ fRangeOffset = offset;
+ fRangeLength = length;
+
+ String[] delimiters = document.getLegalLineDelimiters();
+ fDelimiters = new char[delimiters.length][];
+ for (int i = 0; i < delimiters.length; i++)
+ fDelimiters[i] = delimiters[i].toCharArray();
+
+ updateBuffer(offset);
+ fOffset = 0;
+ }
+
+ /*
+ * @see ICharacterScanner#read()
+ */
+ public final int read() {
+
+ if (fOffset == fBufferLength) {
+ if (fBufferOffset + fBufferLength == fDocument.getLength())
+ return EOF;
+ else {
+ updateBuffer(fBufferOffset + fBufferLength);
+ fOffset = 0;
+ }
+ }
+ try {
+ return fBuffer[fOffset++];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println("Offset:" + fOffset);
+ System.out.println("Buffer:" + fBuffer.toString());
+ throw e;
+ }
+ }
+
+ /*
+ * @see ICharacterScanner#unread
+ */
+ public final void unread() {
+
+ if (fOffset == 0) {
+ if (fBufferOffset == fRangeOffset) {
+ // error: BOF
+ } else {
+ updateBuffer(fBufferOffset - fBuffer.length);
+ fOffset = fBuffer.length - 1;
+ }
+ } else {
+ --fOffset;
+ }
+ }
+
+ /*
+ * @see ICharacterScanner#getColumn()
+ */
+ public final int getColumn() {
+
+ try {
+ final int offset = fBufferOffset + fOffset;
+ final int line = fDocument.getLineOfOffset(offset);
+ final int start = fDocument.getLineOffset(line);
+ return offset - start;
+ } catch (BadLocationException e) {
+ }
+
+ return -1;
+ }
+
+ /*
+ * @see ICharacterScanner#getLegalLineDelimiters()
+ */
+ public final char[][] getLegalLineDelimiters() {
+ return fDelimiters;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CombinedWordRule.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CombinedWordRule.java
new file mode 100644
index 0000000..dedad70
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CombinedWordRule.java
@@ -0,0 +1,408 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ * An implementation of IRule
capable of detecting words.
+ * null
+ * @param token
+ * the token to be returned if the word has been found, may
+ * not be null
+ */
+ public void addWord(String word, IToken token) {
+ Assert.isNotNull(word);
+ Assert.isNotNull(token);
+
+ fWords.put(new CharacterBuffer(word), token);
+ }
+
+ /**
+ * Returns the token associated to the given word and the scanner state.
+ *
+ * @param scanner
+ * the scanner
+ * @param word
+ * the word
+ * @return the token or null
if none is associated by
+ * this matcher
+ */
+ public IToken evaluate(ICharacterScanner scanner, CharacterBuffer word) {
+ IToken token = (IToken) fWords.get(word);
+ if (token != null)
+ return token;
+ return Token.UNDEFINED;
+ }
+
+ /**
+ * Removes all words.
+ */
+ public void clearWords() {
+ fWords.clear();
+ }
+ }
+
+ /**
+ * Character buffer, mutable or suitable for use as key in hash
+ * maps.
+ */
+ public static class CharacterBuffer {
+
+ /** Buffer content */
+ private char[] fContent;
+
+ /** Buffer content size */
+ private int fLength = 0;
+
+ /** Is hash code cached? */
+ private boolean fIsHashCached = false;
+
+ /** The hash code */
+ private int fHashCode;
+
+ /**
+ * Initialize with the given capacity.
+ *
+ * @param capacity
+ * the initial capacity
+ */
+ public CharacterBuffer(int capacity) {
+ fContent = new char[capacity];
+ }
+
+ /**
+ * Initialize with the given content.
+ *
+ * @param string
+ * the initial content
+ */
+ public CharacterBuffer(String content) {
+ fContent = content.toCharArray();
+ fLength = content.length();
+ }
+
+ /**
+ * Empties this buffer.
+ */
+ public void clear() {
+ fIsHashCached = false;
+ fLength = 0;
+ }
+
+ /**
+ * Appends the given character to the buffer.
+ *
+ * @param c
+ * the character
+ */
+ public void append(char c) {
+ fIsHashCached = false;
+ if (fLength == fContent.length) {
+ char[] old = fContent;
+ fContent = new char[old.length << 1];
+ System.arraycopy(old, 0, fContent, 0, old.length);
+ }
+ fContent[fLength++] = c;
+ }
+
+ /**
+ * Returns the length of the content.
+ *
+ * @return the length
+ */
+ public int length() {
+ return fLength;
+ }
+
+ /**
+ * Returns the content as string.
+ *
+ * @return the content
+ */
+ public String toString() {
+ return new String(fContent, 0, fLength);
+ }
+
+ /**
+ * Returns the character at the given position.
+ *
+ * @param i
+ * the position
+ * @return the character at position i
+ */
+ public char charAt(int i) {
+ return fContent[i];
+ }
+
+ /*
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ if (fIsHashCached)
+ return fHashCode;
+
+ int hash = 0;
+ for (int i = 0, n = fLength; i < n; i++)
+ hash = 29 * hash + fContent[i];
+ fHashCode = hash;
+ fIsHashCached = true;
+ return hash;
+ }
+
+ /*
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (!(obj instanceof CharacterBuffer))
+ return false;
+ CharacterBuffer buffer = (CharacterBuffer) obj;
+ int length = buffer.length();
+ if (length != fLength)
+ return false;
+ for (int i = 0; i < length; i++)
+ if (buffer.charAt(i) != fContent[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * Is the content equal to the given string?
+ *
+ * @param string
+ * the string
+ * @return true
iff the content is the same character
+ * sequence as in the string
+ */
+ public boolean equals(String string) {
+ int length = string.length();
+ if (length != fLength)
+ return false;
+ for (int i = 0; i < length; i++)
+ if (string.charAt(i) != fContent[i])
+ return false;
+ return true;
+ }
+ }
+
+ /** Internal setting for the uninitialized column constraint */
+ private static final int UNDEFINED = -1;
+
+ /** The word detector used by this rule */
+ private IWordDetector fDetector;
+
+ /**
+ * The default token to be returned on success and if nothing else has been
+ * specified.
+ */
+ private IToken fDefaultToken;
+
+ /** The column constraint */
+ private int fColumn = UNDEFINED;
+
+ /** Buffer used for pattern detection */
+ private CharacterBuffer fBuffer = new CharacterBuffer(16);
+
+ /** List of word matchers */
+ private List fMatchers = new ArrayList();
+
+ /**
+ * Creates a rule which, with the help of an word detector, will return the
+ * token associated with the detected word. If no token has been associated,
+ * the scanner will be rolled back and an undefined token will be returned
+ * in order to allow any subsequent rules to analyze the characters.
+ *
+ * @param detector
+ * the word detector to be used by this rule, may not be
+ * null
+ *
+ * @see #addWord(String, IToken)
+ */
+ public CombinedWordRule(IWordDetector detector) {
+ this(detector, null, Token.UNDEFINED);
+ }
+
+ /**
+ * Creates a rule which, with the help of an word detector, will return the
+ * token associated with the detected word. If no token has been associated,
+ * the specified default token will be returned.
+ *
+ * @param detector
+ * the word detector to be used by this rule, may not be
+ * null
+ * @param defaultToken
+ * the default token to be returned on success if nothing else is
+ * specified, may not be null
+ *
+ * @see #addWord(String, IToken)
+ */
+ public CombinedWordRule(IWordDetector detector, IToken defaultToken) {
+ this(detector, null, defaultToken);
+ }
+
+ /**
+ * Creates a rule which, with the help of an word detector, will return the
+ * token associated with the detected word. If no token has been associated,
+ * the scanner will be rolled back and an undefined token will be returned
+ * in order to allow any subsequent rules to analyze the characters.
+ *
+ * @param detector
+ * the word detector to be used by this rule, may not be
+ * null
+ * @param matcher
+ * the initial word matcher
+ *
+ * @see #addWord(String, IToken)
+ */
+ public CombinedWordRule(IWordDetector detector, WordMatcher matcher) {
+ this(detector, matcher, Token.UNDEFINED);
+ }
+
+ /**
+ * Creates a rule which, with the help of an word detector, will return the
+ * token associated with the detected word. If no token has been associated,
+ * the specified default token will be returned.
+ *
+ * @param detector
+ * the word detector to be used by this rule, may not be
+ * null
+ * @param matcher
+ * the initial word matcher
+ * @param defaultToken
+ * the default token to be returned on success if nothing else is
+ * specified, may not be null
+ *
+ * @see #addWord(String, IToken)
+ */
+ public CombinedWordRule(IWordDetector detector, WordMatcher matcher,
+ IToken defaultToken) {
+
+ Assert.isNotNull(detector);
+ Assert.isNotNull(defaultToken);
+
+ fDetector = detector;
+ fDefaultToken = defaultToken;
+ if (matcher != null)
+ addWordMatcher(matcher);
+ }
+
+ /**
+ * Adds the given matcher.
+ *
+ * @param matcher
+ * the matcher
+ */
+ public void addWordMatcher(WordMatcher matcher) {
+ fMatchers.add(matcher);
+ }
+
+ /**
+ * Sets a column constraint for this rule. If set, the rule's token will
+ * only be returned if the pattern is detected starting at the specified
+ * column. If the column is smaller then 0, the column constraint is
+ * considered removed.
+ *
+ * @param column
+ * the column in which the pattern starts
+ */
+ public void setColumnConstraint(int column) {
+ if (column < 0)
+ column = UNDEFINED;
+ fColumn = column;
+ }
+
+ /*
+ * @see IRule#evaluate(ICharacterScanner)
+ */
+ public IToken evaluate(ICharacterScanner scanner) {
+ int c = scanner.read();
+ if (fDetector.isWordStart((char) c)) {
+ if (fColumn == UNDEFINED || (fColumn == scanner.getColumn() - 1)) {
+
+ fBuffer.clear();
+ do {
+ fBuffer.append((char) c);
+ c = scanner.read();
+ } while (c != ICharacterScanner.EOF
+ && fDetector.isWordPart((char) c));
+ scanner.unread();
+
+ for (int i = 0, n = fMatchers.size(); i < n; i++) {
+ IToken token = ((WordMatcher) fMatchers.get(i)).evaluate(
+ scanner, fBuffer);
+ if (!token.isUndefined())
+ return token;
+ }
+
+ if (fDefaultToken.isUndefined())
+ unreadBuffer(scanner);
+
+ return fDefaultToken;
+ }
+ }
+
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+ /**
+ * Returns the characters in the buffer to the scanner.
+ *
+ * @param scanner
+ * the scanner to be used
+ */
+ private void unreadBuffer(ICharacterScanner scanner) {
+ for (int i = fBuffer.length() - 1; i >= 0; i--)
+ scanner.unread();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CompositeReconcilingStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CompositeReconcilingStrategy.java
new file mode 100644
index 0000000..5733b4f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CompositeReconcilingStrategy.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+
+/**
+ * A reconciling strategy consisting of a sequence of internal reconciling
+ * strategies. By default, all requests are passed on to the contained
+ * strategies.
+ *
+ * @since 3.0
+ */
+public class CompositeReconcilingStrategy implements IReconcilingStrategy,
+ IReconcilingStrategyExtension {
+
+ /** The list of internal reconciling strategies. */
+ private IReconcilingStrategy[] fStrategies;
+
+ /**
+ * Creates a new, empty composite reconciling strategy.
+ */
+ public CompositeReconcilingStrategy() {
+ }
+
+ /**
+ * Sets the reconciling strategies for this composite strategy.
+ *
+ * @param strategies
+ * the strategies to be set or null
+ */
+ public void setReconcilingStrategies(IReconcilingStrategy[] strategies) {
+ fStrategies = strategies;
+ }
+
+ /**
+ * Returns the previously set stratgies or null
.
+ *
+ * @return the contained strategies or null
+ */
+ public IReconcilingStrategy[] getReconcilingStrategies() {
+ return fStrategies;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
+ */
+ public void setDocument(IDocument document) {
+ if (fStrategies == null)
+ return;
+
+ for (int i = 0; i < fStrategies.length; i++)
+ fStrategies[i].setDocument(document);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,
+ * org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ if (fStrategies == null)
+ return;
+
+ for (int i = 0; i < fStrategies.length; i++)
+ fStrategies[i].reconcile(dirtyRegion, subRegion);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(IRegion partition) {
+ if (fStrategies == null)
+ return;
+
+ for (int i = 0; i < fStrategies.length; i++)
+ fStrategies[i].reconcile(partition);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ if (fStrategies == null)
+ return;
+
+ for (int i = 0; i < fStrategies.length; i++) {
+ if (fStrategies[i] instanceof IReconcilingStrategyExtension) {
+ IReconcilingStrategyExtension extension = (IReconcilingStrategyExtension) fStrategies[i];
+ extension.setProgressMonitor(monitor);
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
+ */
+ public void initialReconcile() {
+ if (fStrategies == null)
+ return;
+
+ for (int i = 0; i < fStrategies.length; i++) {
+ if (fStrategies[i] instanceof IReconcilingStrategyExtension) {
+ IReconcilingStrategyExtension extension = (IReconcilingStrategyExtension) fStrategies[i];
+ extension.initialReconcile();
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/ContentAssistPreference.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/ContentAssistPreference.java
new file mode 100644
index 0000000..b391165
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/ContentAssistPreference.java
@@ -0,0 +1,330 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.PHPDocCompletionProcessor;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.php.HTMLCompletionProcessor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPCompletionProcessor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+
+public class ContentAssistPreference {
+
+ /** Preference key for content assist auto activation */
+ private final static String AUTOACTIVATION = PreferenceConstants.CODEASSIST_AUTOACTIVATION;
+
+ /** Preference key for content assist auto activation delay */
+ private final static String AUTOACTIVATION_DELAY = PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY;
+
+ /** Preference key for content assist proposal color */
+ private final static String PROPOSALS_FOREGROUND = PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND;
+
+ /** Preference key for content assist proposal color */
+ private final static String PROPOSALS_BACKGROUND = PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND;
+
+ /** Preference key for content assist parameters color */
+ private final static String PARAMETERS_FOREGROUND = PreferenceConstants.CODEASSIST_PARAMETERS_FOREGROUND;
+
+ /** Preference key for content assist parameters color */
+ private final static String PARAMETERS_BACKGROUND = PreferenceConstants.CODEASSIST_PARAMETERS_BACKGROUND;
+
+ /** Preference key for content assist completion replacement color */
+ private final static String COMPLETION_REPLACEMENT_FOREGROUND = PreferenceConstants.CODEASSIST_REPLACEMENT_FOREGROUND;
+
+ /** Preference key for content assist completion replacement color */
+ private final static String COMPLETION_REPLACEMENT_BACKGROUND = PreferenceConstants.CODEASSIST_REPLACEMENT_BACKGROUND;
+
+ /** Preference key for content assist auto insert */
+ private final static String AUTOINSERT = PreferenceConstants.CODEASSIST_AUTOINSERT;
+
+ /** Preference key for php content assist auto activation triggers */
+ private final static String AUTOACTIVATION_TRIGGERS_JAVA = PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA;
+
+ /** Preference key for phpdoc content assist auto activation triggers */
+ private final static String AUTOACTIVATION_TRIGGERS_JAVADOC = PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC;
+
+ /** Preference key for html content assist auto activation triggers */
+ private final static String AUTOACTIVATION_TRIGGERS_HTML = PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_HTML;
+
+ /** Preference key for visibility of proposals */
+ private final static String SHOW_VISIBLE_PROPOSALS = PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS;
+
+ /** Preference key for alphabetic ordering of proposals */
+ private final static String ORDER_PROPOSALS = PreferenceConstants.CODEASSIST_ORDER_PROPOSALS;
+
+ /** Preference key for case sensitivity of propsals */
+ private final static String CASE_SENSITIVITY = PreferenceConstants.CODEASSIST_CASE_SENSITIVITY;
+
+ /** Preference key for adding imports on code assist */
+ private final static String ADD_IMPORT = PreferenceConstants.CODEASSIST_ADDIMPORT;
+
+ /** Preference key for inserting content assist */
+ private static final String INSERT_COMPLETION = PreferenceConstants.CODEASSIST_INSERT_COMPLETION;
+
+ /** Preference key for filling argument names on method completion */
+ private static final String FILL_METHOD_ARGUMENTS = PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES;
+
+ /** Preference key for guessing argument names on method completion */
+ private static final String GUESS_METHOD_ARGUMENTS = PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS;
+
+ private static Color getColor(IPreferenceStore store, String key,
+ IColorManager manager) {
+ RGB rgb = PreferenceConverter.getColor(store, key);
+ return manager.getColor(rgb);
+ }
+
+ private static Color getColor(IPreferenceStore store, String key) {
+ JavaTextTools textTools = WebUI.getDefault()
+ .getJavaTextTools();
+ return getColor(store, key, textTools.getColorManager());
+ }
+
+ private static PHPCompletionProcessor getJavaProcessor(
+ ContentAssistant assistant) {
+ IContentAssistProcessor p = assistant
+ .getContentAssistProcessor(IPHPPartitions.PHP_PARTITIONING);
+ if (p instanceof PHPCompletionProcessor)
+ return (PHPCompletionProcessor) p;
+ return null;
+ }
+
+ private static PHPDocCompletionProcessor getJavaDocProcessor(
+ ContentAssistant assistant) {
+ IContentAssistProcessor p = assistant
+ .getContentAssistProcessor(IPHPPartitions.PHP_PHPDOC_COMMENT);
+ if (p instanceof PHPDocCompletionProcessor)
+ return (PHPDocCompletionProcessor) p;
+ return null;
+ }
+
+ private static HTMLCompletionProcessor getHTMLProcessor(
+ ContentAssistant assistant) {
+ IContentAssistProcessor p = assistant
+ .getContentAssistProcessor(IPHPPartitions.HTML);
+ if (p instanceof HTMLCompletionProcessor)
+ return (HTMLCompletionProcessor) p;
+ return null;
+ }
+
+ private static void configureJavaProcessor(ContentAssistant assistant,
+ IPreferenceStore store) {
+ PHPCompletionProcessor pcp = getJavaProcessor(assistant);
+ if (pcp == null)
+ return;
+
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_JAVA);
+ if (triggers != null)
+ pcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+ boolean enabled;
+ // boolean enabled= store.getBoolean(SHOW_VISIBLE_PROPOSALS);
+ // jcp.restrictProposalsToVisibility(enabled);
+ //
+ // enabled= store.getBoolean(CASE_SENSITIVITY);
+ // jcp.restrictProposalsToMatchingCases(enabled);
+ //
+ enabled = store.getBoolean(ORDER_PROPOSALS);
+ pcp.orderProposalsAlphabetically(enabled);
+ //
+ // enabled= store.getBoolean(ADD_IMPORT);
+ // jcp.allowAddingImports(enabled);
+ }
+
+ private static void configureJavaDocProcessor(ContentAssistant assistant,
+ IPreferenceStore store) {
+ PHPDocCompletionProcessor pdcp = getJavaDocProcessor(assistant);
+ if (pdcp == null)
+ return;
+
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_JAVADOC);
+ if (triggers != null)
+ pdcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+
+ boolean enabled = store.getBoolean(CASE_SENSITIVITY);
+ pdcp.restrictProposalsToMatchingCases(enabled);
+
+ enabled = store.getBoolean(ORDER_PROPOSALS);
+ pdcp.orderProposalsAlphabetically(enabled);
+ }
+
+ private static void configureHTMLProcessor(ContentAssistant assistant,
+ IPreferenceStore store) {
+ HTMLCompletionProcessor hcp = getHTMLProcessor(assistant);
+ if (hcp == null)
+ return;
+
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_HTML);
+ if (triggers != null)
+ hcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+
+ boolean enabled;
+ // boolean enabled = store.getBoolean(CASE_SENSITIVITY);
+ // jdcp.restrictProposalsToMatchingCases(enabled);
+
+ enabled = store.getBoolean(ORDER_PROPOSALS);
+ hcp.orderProposalsAlphabetically(enabled);
+ }
+
+ /**
+ * Configure the given content assistant from the given store.
+ */
+ public static void configure(ContentAssistant assistant,
+ IPreferenceStore store) {
+
+ JavaTextTools textTools = WebUI.getDefault()
+ .getJavaTextTools();
+ IColorManager manager = textTools.getColorManager();
+
+ boolean enabled = store.getBoolean(AUTOACTIVATION);
+ assistant.enableAutoActivation(enabled);
+
+ int delay = store.getInt(AUTOACTIVATION_DELAY);
+ assistant.setAutoActivationDelay(delay);
+
+ Color c = getColor(store, PROPOSALS_FOREGROUND, manager);
+ assistant.setProposalSelectorForeground(c);
+
+ c = getColor(store, PROPOSALS_BACKGROUND, manager);
+ assistant.setProposalSelectorBackground(c);
+
+ c = getColor(store, PARAMETERS_FOREGROUND, manager);
+ assistant.setContextInformationPopupForeground(c);
+ assistant.setContextSelectorForeground(c);
+
+ c = getColor(store, PARAMETERS_BACKGROUND, manager);
+ assistant.setContextInformationPopupBackground(c);
+ assistant.setContextSelectorBackground(c);
+
+ enabled = store.getBoolean(AUTOINSERT);
+ assistant.enableAutoInsert(enabled);
+
+ configureJavaProcessor(assistant, store);
+ configureJavaDocProcessor(assistant, store);
+ configureHTMLProcessor(assistant, store);
+ }
+
+ private static void changeJavaProcessor(ContentAssistant assistant,
+ IPreferenceStore store, String key) {
+ PHPCompletionProcessor jcp = getJavaProcessor(assistant);
+ if (jcp == null)
+ return;
+
+ if (AUTOACTIVATION_TRIGGERS_JAVA.equals(key)) {
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_JAVA);
+ if (triggers != null)
+ jcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+ }
+ // else if (SHOW_VISIBLE_PROPOSALS.equals(key)) {
+ // boolean enabled= store.getBoolean(SHOW_VISIBLE_PROPOSALS);
+ // jcp.restrictProposalsToVisibility(enabled);
+ // } else if (CASE_SENSITIVITY.equals(key)) {
+ // boolean enabled= store.getBoolean(CASE_SENSITIVITY);
+ // jcp.restrictProposalsToMatchingCases(enabled); }
+ else if (ORDER_PROPOSALS.equals(key)) {
+ boolean enable = store.getBoolean(ORDER_PROPOSALS);
+ jcp.orderProposalsAlphabetically(enable);
+ // } else if (ADD_IMPORT.equals(key)) {
+ // boolean enabled= store.getBoolean(ADD_IMPORT);
+ // jcp.allowAddingImports(enabled);
+ }
+ }
+
+ private static void changeJavaDocProcessor(ContentAssistant assistant,
+ IPreferenceStore store, String key) {
+ PHPDocCompletionProcessor jdcp = getJavaDocProcessor(assistant);
+ if (jdcp == null)
+ return;
+
+ if (AUTOACTIVATION_TRIGGERS_JAVADOC.equals(key)) {
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_JAVADOC);
+ if (triggers != null)
+ jdcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+ } else if (CASE_SENSITIVITY.equals(key)) {
+ boolean enabled = store.getBoolean(CASE_SENSITIVITY);
+ jdcp.restrictProposalsToMatchingCases(enabled);
+ } else if (ORDER_PROPOSALS.equals(key)) {
+ boolean enable = store.getBoolean(ORDER_PROPOSALS);
+ jdcp.orderProposalsAlphabetically(enable);
+ }
+ }
+
+ private static void changeHTMLProcessor(ContentAssistant assistant,
+ IPreferenceStore store, String key) {
+ HTMLCompletionProcessor jdcp = getHTMLProcessor(assistant);
+ if (jdcp == null)
+ return;
+
+ if (AUTOACTIVATION_TRIGGERS_HTML.equals(key)) {
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_HTML);
+ if (triggers != null)
+ jdcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+ // } else if (CASE_SENSITIVITY.equals(key)) {
+ // boolean enabled = store.getBoolean(CASE_SENSITIVITY);
+ // jdcp.restrictProposalsToMatchingCases(enabled);
+ } else if (ORDER_PROPOSALS.equals(key)) {
+ boolean enable = store.getBoolean(ORDER_PROPOSALS);
+ jdcp.orderProposalsAlphabetically(enable);
+ }
+ }
+
+ /**
+ * Changes the configuration of the given content assistant according to the
+ * given property change event and the given preference store.
+ */
+ public static void changeConfiguration(ContentAssistant assistant,
+ IPreferenceStore store, PropertyChangeEvent event) {
+
+ String p = event.getProperty();
+
+ if (AUTOACTIVATION.equals(p)) {
+ boolean enabled = store.getBoolean(AUTOACTIVATION);
+ assistant.enableAutoActivation(enabled);
+ } else if (AUTOACTIVATION_DELAY.equals(p)) {
+ int delay = store.getInt(AUTOACTIVATION_DELAY);
+ assistant.setAutoActivationDelay(delay);
+ } else if (PROPOSALS_FOREGROUND.equals(p)) {
+ Color c = getColor(store, PROPOSALS_FOREGROUND);
+ assistant.setProposalSelectorForeground(c);
+ } else if (PROPOSALS_BACKGROUND.equals(p)) {
+ Color c = getColor(store, PROPOSALS_BACKGROUND);
+ assistant.setProposalSelectorBackground(c);
+ } else if (PARAMETERS_FOREGROUND.equals(p)) {
+ Color c = getColor(store, PARAMETERS_FOREGROUND);
+ assistant.setContextInformationPopupForeground(c);
+ assistant.setContextSelectorForeground(c);
+ } else if (PARAMETERS_BACKGROUND.equals(p)) {
+ Color c = getColor(store, PARAMETERS_BACKGROUND);
+ assistant.setContextInformationPopupBackground(c);
+ assistant.setContextSelectorBackground(c);
+ } else if (AUTOINSERT.equals(p)) {
+ boolean enabled = store.getBoolean(AUTOINSERT);
+ assistant.enableAutoInsert(enabled);
+ }
+
+ changeJavaProcessor(assistant, store, p);
+ changeJavaDocProcessor(assistant, store, p);
+ changeHTMLProcessor(assistant, store, p);
+ }
+
+ public static boolean fillArgumentsOnMethodCompletion(IPreferenceStore store) {
+ return store.getBoolean(FILL_METHOD_ARGUMENTS);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CustomSourceInformationControl.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CustomSourceInformationControl.java
new file mode 100644
index 0000000..3f3c40a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/CustomSourceInformationControl.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.internal.ui.text.java.hover.SourceViewerInformationControl;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Source viewer used to display quick diff hovers.
+ *
+ * @since 3.0
+ */
+public class CustomSourceInformationControl extends
+ SourceViewerInformationControl {
+
+ /** The font name for the viewer font - the same as the java editor's. */
+ private static final String SYMBOLIC_FONT_NAME = "net.sourceforge.phpdt.ui.editors.textfont"; //$NON-NLS-1$
+
+ /**
+ * The maximum width of the control, set in
+ * setSizeConstraints(int, int)
.
+ */
+ int fMaxWidth = Integer.MAX_VALUE;
+
+ /**
+ * The maximum height of the control, set in
+ * setSizeConstraints(int, int)
.
+ */
+ int fMaxHeight = Integer.MAX_VALUE;
+
+ /**
+ * The partition type to be used as the starting partition type by the
+ * paritition scanner.
+ */
+ private String fPartition;
+
+ /** The horizontal scroll index. */
+ private int fHorizontalScrollPixel;
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int,
+ * int)
+ */
+ public void setSizeConstraints(int maxWidth, int maxHeight) {
+ fMaxWidth = maxWidth;
+ fMaxHeight = maxHeight;
+ }
+
+ /**
+ * Creates a new information control.
+ *
+ * @param parent
+ * the shell that is the parent of this hover / control
+ * @param partition
+ * the initial partition type to be used for the underlying
+ * viewer
+ */
+ public CustomSourceInformationControl(Shell parent, String partition) {
+ super(parent);
+ setViewerFont();
+ setStartingPartitionType(partition);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControl#computeSizeHint()
+ */
+ public Point computeSizeHint() {
+ Point size = super.computeSizeHint();
+ size.x = Math.min(size.x, fMaxWidth);
+ size.y = Math.min(size.y, fMaxHeight);
+ return size;
+ }
+
+ /**
+ * Sets the font for this viewer sustaining selection and scroll position.
+ */
+ private void setViewerFont() {
+ Font font = JFaceResources.getFont(SYMBOLIC_FONT_NAME);
+
+ if (getViewer().getDocument() != null) {
+
+ Point selection = getViewer().getSelectedRange();
+ int topIndex = getViewer().getTopIndex();
+
+ StyledText styledText = getViewer().getTextWidget();
+ Control parent = styledText;
+ if (getViewer() instanceof ITextViewerExtension) {
+ ITextViewerExtension extension = (ITextViewerExtension) getViewer();
+ parent = extension.getControl();
+ }
+
+ parent.setRedraw(false);
+
+ styledText.setFont(font);
+
+ getViewer().setSelectedRange(selection.x, selection.y);
+ getViewer().setTopIndex(topIndex);
+
+ if (parent instanceof Composite) {
+ Composite composite = (Composite) parent;
+ composite.layout(true);
+ }
+
+ parent.setRedraw(true);
+
+ } else {
+ StyledText styledText = getViewer().getTextWidget();
+ styledText.setFont(font);
+ }
+ }
+
+ /**
+ * Sets the initial partition for the underlying source viewer.
+ *
+ * @param partition
+ * the partition type
+ */
+ public void setStartingPartitionType(String partition) {
+ if (partition == null)
+ fPartition = IDocument.DEFAULT_CONTENT_TYPE;
+ else
+ fPartition = partition;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String)
+ */
+ public void setInformation(String content) {
+ super.setInformation(content);
+ IDocument doc = getViewer().getDocument();
+ if (doc == null)
+ return;
+
+ // ensure that we can scroll enough
+ ensureScrollable();
+
+ String start = null;
+ if (IPHPPartitions.PHP_PHPDOC_COMMENT.equals(fPartition)) {
+ start = "/**" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$
+ } else if (IPHPPartitions.PHP_MULTILINE_COMMENT.equals(fPartition)) {
+ start = "/*" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$
+ }
+ if (start != null) {
+ try {
+ doc.replace(0, 0, start);
+ int startLen = start.length();
+ getViewer().setDocument(doc, startLen,
+ doc.getLength() - startLen);
+ } catch (BadLocationException e) {
+ // impossible
+ Assert.isTrue(false);
+ }
+ }
+
+ getViewer().getTextWidget().setHorizontalPixel(fHorizontalScrollPixel);
+ }
+
+ /**
+ * Ensures that the control can be scrolled at least to
+ * fHorizontalScrollPixel
and adjusts fMaxWidth
+ * accordingly.
+ */
+ private void ensureScrollable() {
+ IDocument doc = getViewer().getDocument();
+ if (doc == null)
+ return;
+
+ StyledText widget = getViewer().getTextWidget();
+ if (widget == null || widget.isDisposed())
+ return;
+
+ int last = doc.getNumberOfLines() - 1;
+ GC gc = new GC(widget);
+ gc.setFont(widget.getFont());
+ int maxWidth = 0;
+ String content = new String();
+
+ try {
+ for (int i = 0; i <= last; i++) {
+ IRegion line;
+ line = doc.getLineInformation(i);
+ content = doc.get(line.getOffset(), line.getLength());
+ int width = gc.textExtent(content).x;
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ }
+ } catch (BadLocationException e) {
+ return;
+ } finally {
+ gc.dispose();
+ }
+
+ // limit the size of the window to the maximum width minus scrolling,
+ // but never more than the configured max size (viewport size).
+ fMaxWidth = Math.max(0, Math.min(fMaxWidth, maxWidth
+ - fHorizontalScrollPixel + 8));
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.java.hover.SourceViewerInformationControl#hasContents()
+ */
+ public boolean hasContents() {
+ return super.hasContents() && fMaxWidth > 0;
+ }
+
+ /**
+ * Sets the horizontal scroll index in pixels.
+ *
+ * @param scrollIndex
+ * the new horizontal scroll index
+ */
+ public void setHorizontalScrollPixel(int scrollIndex) {
+ scrollIndex = Math.max(0, scrollIndex);
+ fHorizontalScrollPixel = scrollIndex;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/DocumentCharacterIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/DocumentCharacterIterator.java
new file mode 100644
index 0000000..416ddaf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/DocumentCharacterIterator.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.text;
+
+import java.text.CharacterIterator;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * An IDocument
based implementation of
+ * CharacterIterator
and CharSequence
. Note that
+ * the supplied document is not copied; if the document is modified during the
+ * lifetime of a DocumentCharacterIterator
, the methods
+ * returning document content may not always return the same values. Also, if
+ * accessing the document fails with a {@link BadLocationException}, any of
+ * CharacterIterator
methods as well as charAt
may
+ * return {@link CharacterIterator#DONE}.
+ *
+ * @since 3.0
+ */
+public class DocumentCharacterIterator implements CharacterIterator,
+ CharSequence {
+
+ private int fIndex = -1;
+
+ private final IDocument fDocument;
+
+ private final int fFirst;
+
+ private final int fLast;
+
+ private void invariant() {
+ Assert.isTrue(fIndex >= fFirst);
+ Assert.isTrue(fIndex <= fLast);
+ }
+
+ /**
+ * Creates an iterator for the entire document.
+ *
+ * @param document
+ * the document backing this iterator
+ */
+ public DocumentCharacterIterator(IDocument document) {
+ this(document, 0);
+ }
+
+ /**
+ * Creates an iterator, starting at offset first
.
+ *
+ * @param document
+ * the document backing this iterator
+ * @param first
+ * the first character to consider
+ * @throws IllegalArgumentException
+ * if the indices are out of bounds
+ */
+ public DocumentCharacterIterator(IDocument document, int first)
+ throws IllegalArgumentException {
+ this(document, first, document.getLength());
+ }
+
+ /**
+ * Creates an iterator for the document contents from first
+ * (inclusive) to last
(exclusive).
+ *
+ * @param document
+ * the document backing this iterator
+ * @param first
+ * the first character to consider
+ * @param last
+ * the last character index to consider
+ * @throws IllegalArgumentException
+ * if the indices are out of bounds
+ */
+ public DocumentCharacterIterator(IDocument document, int first, int last)
+ throws IllegalArgumentException {
+ if (document == null)
+ throw new NullPointerException();
+ if (first < 0 || first > last)
+ throw new IllegalArgumentException();
+ if (last > document.getLength())
+ throw new IllegalArgumentException();
+ fDocument = document;
+ fFirst = first;
+ fLast = last;
+ fIndex = first;
+ invariant();
+ }
+
+ /*
+ * @see java.text.CharacterIterator#first()
+ */
+ public char first() {
+ return setIndex(getBeginIndex());
+ }
+
+ /*
+ * @see java.text.CharacterIterator#last()
+ */
+ public char last() {
+ if (fFirst == fLast)
+ return setIndex(getEndIndex());
+ else
+ return setIndex(getEndIndex() - 1);
+ }
+
+ /*
+ * @see java.text.CharacterIterator#current()
+ */
+ public char current() {
+ if (fIndex >= fFirst && fIndex < fLast)
+ try {
+ return fDocument.getChar(fIndex);
+ } catch (BadLocationException e) {
+ // ignore
+ }
+ return DONE;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#next()
+ */
+ public char next() {
+ return setIndex(Math.min(fIndex + 1, getEndIndex()));
+ }
+
+ /*
+ * @see java.text.CharacterIterator#previous()
+ */
+ public char previous() {
+ if (fIndex > getBeginIndex()) {
+ return setIndex(fIndex - 1);
+ } else {
+ return DONE;
+ }
+ }
+
+ /*
+ * @see java.text.CharacterIterator#setIndex(int)
+ */
+ public char setIndex(int position) {
+ if (position >= getBeginIndex() && position <= getEndIndex())
+ fIndex = position;
+ else
+ throw new IllegalArgumentException();
+
+ invariant();
+ return current();
+ }
+
+ /*
+ * @see java.text.CharacterIterator#getBeginIndex()
+ */
+ public int getBeginIndex() {
+ return fFirst;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#getEndIndex()
+ */
+ public int getEndIndex() {
+ return fLast;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#getIndex()
+ */
+ public int getIndex() {
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#clone()
+ */
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new InternalError();
+ }
+ }
+
+ /*
+ * @see java.lang.CharSequence#length()
+ */
+ public int length() {
+ return getEndIndex() - getBeginIndex();
+ }
+
+ /**
+ * {@inheritDoc}
+ * This is an example.
+ fTokenLength--;
+ fScanner.unread();
+ fScanner.unread();
+ return postFix(fState);
+ } else {
+ // bug #1404228: Crash on
+ if (nextch != ICharacterScanner.EOF) {
+ fScanner.unread();
+ }
+ }
+ }
+
+ default:
+ if (!fEmulate && fLast == CARRIAGE_RETURN) {
+ switch (fState) {
+ case SINGLE_LINE_COMMENT:
+ // case CHARACTER:
+ // case STRING_DQ:
+ // case STRING_SQ:
+ int last;
+ int newState;
+ switch (ch) {
+ case '/':
+ last = SLASH;
+ newState = PHP;
+ break;
+
+ case '*':
+ last = STAR;
+ newState = PHP;
+ break;
+
+ case '\'':
+ last = NONE;
+ newState = STRING_SQ;
+ break;
+
+ case '"':
+ last = NONE;
+ newState = STRING_DQ;
+ break;
+
+ case '\r':
+ last = CARRIAGE_RETURN;
+ newState = PHP;
+ break;
+
+ case '\\':
+ last = BACKSLASH;
+ newState = PHP;
+ break;
+
+ default:
+ last = NONE;
+ newState = PHP;
+ break;
+ }
+
+ fLast = NONE; // ignore fLast
+ return preFix(fState, newState, last, 1);
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // states
+ switch (fState) {
+ case PHP:
+ switch (ch) {
+ case '#':
+ if (fTokenLength > 0) {
+ return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
+ } else {
+ preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
+ fTokenOffset += fTokenLength;
+ fTokenLength = fPrefixLength;
+ break;
+ }
+ case '/':
+ if (fLast == SLASH) {
+ if (fTokenLength - getLastLength(fLast) > 0) {
+ return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
+ } else {
+ preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
+ fTokenOffset += fTokenLength;
+ fTokenLength = fPrefixLength;
+ break;
+ }
+
+ } else {
+ fTokenLength++;
+ fLast = SLASH;
+ break;
+ }
+
+ case '*':
+ if (fLast == SLASH) {
+ if (fTokenLength - getLastLength(fLast) > 0)
+ return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR,
+ 2);
+ else {
+ preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
+ fTokenOffset += fTokenLength;
+ fTokenLength = fPrefixLength;
+ break;
+ }
+
+ } else {
+ consume();
+ break;
+ }
+
+ case '\'':
+ fLast = NONE; // ignore fLast
+ if (fTokenLength > 0)
+ return preFix(PHP, STRING_SQ, NONE, 1);
+ else {
+ preFix(PHP, STRING_SQ, NONE, 1);
+ fTokenOffset += fTokenLength;
+ fTokenLength = fPrefixLength;
+ break;
+ }
+
+ case '"':
+ fLast = NONE; // ignore fLast
+ if (fTokenLength > 0)
+ return preFix(PHP, STRING_DQ, NONE, 1);
+ else {
+ preFix(PHP, STRING_DQ, NONE, 1);
+ fTokenOffset += fTokenLength;
+ fTokenLength = fPrefixLength;
+ break;
+ }
+
+ default:
+ consume();
+ break;
+ }
+ break;
+
+ case SINGLE_LINE_COMMENT:
+ consume();
+ break;
+
+ case PHPDOC:
+ switch (ch) {
+ case '/':
+ switch (fLast) {
+ case SLASH_STAR_STAR:
+ return postFix(MULTI_LINE_COMMENT);
+
+ case STAR:
+ return postFix(PHPDOC);
+
+ default:
+ consume();
+ break;
+ }
+ break;
+
+ case '*':
+ fTokenLength++;
+ fLast = STAR;
+ break;
+
+ default:
+ consume();
+ break;
+ }
+ break;
+
+ case MULTI_LINE_COMMENT:
+ switch (ch) {
+ case '*':
+ if (fLast == SLASH_STAR) {
+ fLast = SLASH_STAR_STAR;
+ fTokenLength++;
+ fState = PHPDOC;
+ } else {
+ fTokenLength++;
+ fLast = STAR;
+ }
+ break;
+
+ case '/':
+ if (fLast == STAR) {
+ return postFix(MULTI_LINE_COMMENT);
+ } else {
+ consume();
+ break;
+ }
+
+ default:
+ consume();
+ break;
+ }
+ break;
+
+ case STRING_DQ:
+ switch (ch) {
+ case '\\':
+ fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
+ fTokenLength++;
+ break;
+
+ case '\"':
+ if (fLast != BACKSLASH) {
+ return postFix(STRING_DQ);
+
+ } else {
+ consume();
+ break;
+ }
+
+ default:
+ consume();
+ break;
+ }
+ break;
+ case STRING_SQ:
+ switch (ch) {
+ case '\\':
+ fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
+ fTokenLength++;
+ break;
+
+ case '\'':
+ if (fLast != BACKSLASH) {
+ return postFix(STRING_SQ);
+
+ } else {
+ consume();
+ break;
+ }
+
+ default:
+ consume();
+ break;
+ }
+ break;
+ // case CHARACTER:
+ // switch (ch) {
+ // case '\\':
+ // fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
+ // fTokenLength++;
+ // break;
+ //
+ // case '\'':
+ // if (fLast != BACKSLASH) {
+ // return postFix(CHARACTER);
+ //
+ // } else {
+ // consume();
+ // break;
+ // }
+ //
+ // default:
+ // consume();
+ // break;
+ // }
+ // break;
+ }
+ }
+ }
+
+ private static final int getLastLength(int last) {
+ switch (last) {
+ default:
+ return -1;
+
+ case NONE:
+ return 0;
+
+ case CARRIAGE_RETURN:
+ case BACKSLASH:
+ case SLASH:
+ case STAR:
+ return 1;
+
+ case SLASH_STAR:
+ return 2;
+
+ case SLASH_STAR_STAR:
+ return 3;
+ }
+ }
+
+ private final void consume() {
+ fTokenLength++;
+ fLast = NONE;
+ }
+
+ private final IToken postFix(int state) {
+ fTokenLength++;
+ fLast = NONE;
+ fState = PHP;
+ fPrefixLength = 0;
+ return fTokens[state];
+ }
+
+ private final IToken preFix(int state, int newState, int last,
+ int prefixLength) {
+ // emulate JavaPartitionScanner
+ if (fEmulate && state == PHP
+ && (fTokenLength - getLastLength(fLast) > 0)) {
+ fTokenLength -= getLastLength(fLast);
+ fJavaOffset = fTokenOffset;
+ fJavaLength = fTokenLength;
+ fTokenLength = 1;
+ fState = newState;
+ fPrefixLength = prefixLength;
+ fLast = last;
+ return fTokens[state];
+
+ } else {
+ fTokenLength -= getLastLength(fLast);
+ fLast = last;
+ fPrefixLength = prefixLength;
+ IToken token = fTokens[state];
+ fState = newState;
+ return token;
+ }
+ }
+
+ private static int getState(String contentType) {
+
+ if (contentType == null)
+ return PHP;
+
+ else if (contentType.equals(PHP_SINGLELINE_COMMENT))
+ return SINGLE_LINE_COMMENT;
+
+ else if (contentType.equals(PHP_MULTILINE_COMMENT))
+ return MULTI_LINE_COMMENT;
+
+ else if (contentType.equals(PHP_PHPDOC_COMMENT))
+ return PHPDOC;
+
+ else if (contentType.equals(PHP_STRING_DQ))
+ return STRING_DQ;
+
+ else if (contentType.equals(PHP_STRING_SQ))
+ return STRING_SQ;
+
+ else if (contentType.equals(PHP_STRING_HEREDOC))
+ return STRING_HEREDOC;
+
+ // else if (contentType.equals(JAVA_CHARACTER))
+ // return CHARACTER;
+
+ else
+ return PHP;
+ }
+
+ /*
+ * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String,
+ * int)
+ */
+ public void setPartialRange(IDocument document, int offset, int length,
+ String contentType, int partitionOffset) {
+ fScanner.setRange(document, offset, length);
+ setRange(document, offset, length);
+ fTokenOffset = partitionOffset;
+ fTokenLength = 0;
+ fPrefixLength = offset - partitionOffset;
+ fLast = NONE;
+
+ if (offset == partitionOffset) {
+ // restart at beginning of partition
+ fState = PHP;
+ } else {
+ fState = getState(contentType);
+ }
+
+ // emulate JavaPartitionScanner
+ if (fEmulate) {
+ fJavaOffset = -1;
+ fJavaLength = 0;
+ }
+ }
+
+ /*
+ * @see ITokenScanner#setRange(IDocument, int, int)
+ */
+ public void setRange(IDocument document, int offset, int length) {
+ fScanner.setRange(document, offset, length);
+ fTokenOffset = offset;
+ fTokenLength = 0;
+ fPrefixLength = 0;
+ fLast = NONE;
+ fState = PHP;
+
+ // emulate JavaPartitionScanner
+ if (fEmulate) {
+ fJavaOffset = -1;
+ fJavaLength = 0;
+ }
+ }
+
+ /*
+ * @see ITokenScanner#getTokenLength()
+ */
+ public int getTokenLength() {
+ return fTokenLength;
+ }
+
+ /*
+ * @see ITokenScanner#getTokenOffset()
+ */
+ public int getTokenOffset() {
+ if (AbstractPartitioner.DEBUG) {
+ Assert.isTrue(fTokenOffset >= 0, Integer.toString(fTokenOffset));
+ }
+ return fTokenOffset;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTML2TextReader.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTML2TextReader.java
new file mode 100644
index 0000000..1fe8811
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTML2TextReader.java
@@ -0,0 +1,301 @@
+package net.sourceforge.phpdt.internal.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+
+/**
+ * Reads the text contents from a reader of HTML contents and translates the
+ * tags or cut them out.
+ */
+public class HTML2TextReader extends SubstitutionTextReader {
+
+ private static final String LINE_DELIM = System.getProperty(
+ "line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+ private static final Map fgEntityLookup;
+
+ private static final Set fgTags;
+
+ static {
+
+ fgTags = new HashSet();
+ fgTags.add("b"); //$NON-NLS-1$
+ fgTags.add("br"); //$NON-NLS-1$
+ fgTags.add("h5"); //$NON-NLS-1$
+ fgTags.add("p"); //$NON-NLS-1$
+ fgTags.add("dl"); //$NON-NLS-1$
+ fgTags.add("dt"); //$NON-NLS-1$
+ fgTags.add("dd"); //$NON-NLS-1$
+ fgTags.add("li"); //$NON-NLS-1$
+ fgTags.add("ul"); //$NON-NLS-1$
+ fgTags.add("pre"); //$NON-NLS-1$
+
+ fgEntityLookup = new HashMap(7);
+ fgEntityLookup.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$
+ fgEntityLookup.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$
+ fgEntityLookup.put("nbsp", " "); //$NON-NLS-1$ //$NON-NLS-2$
+ fgEntityLookup.put("amp", "&"); //$NON-NLS-1$ //$NON-NLS-2$
+ fgEntityLookup.put("circ", "^"); //$NON-NLS-1$ //$NON-NLS-2$
+ fgEntityLookup.put("tilde", "~"); //$NON-NLS-2$ //$NON-NLS-1$
+ fgEntityLookup.put("quot", "\""); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private int fCounter = 0;
+
+ private TextPresentation fTextPresentation;
+
+ private int fBold = 0;
+
+ private int fStartOffset = -1;
+
+ private boolean fInParagraph = false;
+
+ private boolean fIsPreformattedText = false;
+
+ /**
+ * Transforms the html text from the reader to formatted text.
+ *
+ * @param presentation
+ * If not null
, formattings will be applied to
+ * the presentation.
+ */
+ public HTML2TextReader(Reader reader, TextPresentation presentation) {
+ super(new PushbackReader(reader));
+ fTextPresentation = presentation;
+ }
+
+ public int read() throws IOException {
+ int c = super.read();
+ if (c != -1)
+ ++fCounter;
+ return c;
+ }
+
+ protected void startBold() {
+ if (fBold == 0)
+ fStartOffset = fCounter;
+ ++fBold;
+ }
+
+ protected void startPreformattedText() {
+ fIsPreformattedText = true;
+ setSkipWhitespace(false);
+ }
+
+ protected void stopPreformattedText() {
+ fIsPreformattedText = false;
+ setSkipWhitespace(true);
+ }
+
+ protected void stopBold() {
+ --fBold;
+ if (fBold == 0) {
+ if (fTextPresentation != null) {
+ fTextPresentation.addStyleRange(new StyleRange(fStartOffset,
+ fCounter - fStartOffset, null, null, SWT.BOLD));
+ }
+ fStartOffset = -1;
+ }
+ }
+
+ /**
+ * @see SubstitutionTextReader#computeSubstitution(char)
+ */
+ protected String computeSubstitution(int c) throws IOException {
+
+ if (c == '<')
+ return processHTMLTag();
+ else if (c == '&')
+ return processEntity();
+ else if (fIsPreformattedText)
+ return processPreformattedText(c);
+
+ return null;
+ }
+
+ private String html2Text(String html) {
+
+ String tag = html;
+ if ('/' == tag.charAt(0))
+ tag = tag.substring(1);
+
+ if (!fgTags.contains(tag))
+ return EMPTY_STRING;
+
+ if ("pre".equals(html)) { //$NON-NLS-1$
+ startPreformattedText();
+ return EMPTY_STRING;
+ }
+
+ if ("/pre".equals(html)) { //$NON-NLS-1$
+ stopPreformattedText();
+ return EMPTY_STRING;
+ }
+
+ if (fIsPreformattedText)
+ return EMPTY_STRING;
+
+ if ("b".equals(html)) { //$NON-NLS-1$
+ startBold();
+ return EMPTY_STRING;
+ }
+
+ if ("h5".equals(html) || "dt".equals(html)) { //$NON-NLS-1$ //$NON-NLS-2$
+ startBold();
+ return EMPTY_STRING;
+ }
+
+ if ("dl".equals(html)) //$NON-NLS-1$
+ return LINE_DELIM;
+
+ if ("dd".equals(html)) //$NON-NLS-1$
+ return "\t"; //$NON-NLS-1$
+
+ if ("li".equals(html)) //$NON-NLS-1$
+ return LINE_DELIM
+ + "\t" + PHPUIMessages.getString("HTML2TextReader.dash"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ if ("/b".equals(html)) { //$NON-NLS-1$
+ stopBold();
+ return EMPTY_STRING;
+ }
+
+ if ("p".equals(html)) { //$NON-NLS-1$
+ fInParagraph = true;
+ return LINE_DELIM;
+ }
+
+ if ("br".equals(html)) //$NON-NLS-1$
+ return LINE_DELIM;
+
+ if ("/p".equals(html)) { //$NON-NLS-1$
+ boolean inParagraph = fInParagraph;
+ fInParagraph = false;
+ return inParagraph ? EMPTY_STRING : LINE_DELIM;
+ }
+
+ if ("/h5".equals(html) || "/dt".equals(html)) { //$NON-NLS-1$ //$NON-NLS-2$
+ stopBold();
+ return LINE_DELIM;
+ }
+
+ if ("/dd".equals(html)) //$NON-NLS-1$
+ return LINE_DELIM;
+
+ return EMPTY_STRING;
+ }
+
+ /*
+ * A '<' has been read. Process a html tag
+ */
+ private String processHTMLTag() throws IOException {
+
+ StringBuffer buf = new StringBuffer();
+ int ch;
+ do {
+
+ ch = nextChar();
+
+ while (ch != -1 && ch != '>') {
+ buf.append(Character.toLowerCase((char) ch));
+ ch = nextChar();
+ if (ch == '"') {
+ buf.append(Character.toLowerCase((char) ch));
+ ch = nextChar();
+ while (ch != -1 && ch != '"') {
+ buf.append(Character.toLowerCase((char) ch));
+ ch = nextChar();
+ }
+ }
+ if (ch == '<') {
+ unread(ch);
+ return '<' + buf.toString();
+ }
+ }
+
+ if (ch == -1)
+ return null;
+
+ int tagLen = buf.length();
+ // needs special treatment for comments
+ if ((tagLen >= 3 && "!--".equals(buf.substring(0, 3))) //$NON-NLS-1$
+ && !(tagLen >= 5 && "--!".equals(buf.substring(tagLen - 3)))) { //$NON-NLS-1$
+ // unfinished comment
+ buf.append(ch);
+ } else {
+ break;
+ }
+ } while (true);
+
+ return html2Text(buf.toString());
+ }
+
+ private String processPreformattedText(int c) {
+ if (c == '\r' || c == '\n')
+ fCounter++;
+ return null;
+ }
+
+ private void unread(int ch) throws IOException {
+ ((PushbackReader) getReader()).unread(ch);
+ }
+
+ protected String entity2Text(String symbol) {
+ if (symbol.length() > 1 && symbol.charAt(0) == '#') {
+ int ch;
+ try {
+ if (symbol.charAt(1) == 'x') {
+ ch = Integer.parseInt(symbol.substring(2), 16);
+ } else {
+ ch = Integer.parseInt(symbol.substring(1), 10);
+ }
+ return EMPTY_STRING + (char) ch;
+ } catch (NumberFormatException e) {
+ }
+ } else {
+ String str = (String) fgEntityLookup.get(symbol);
+ if (str != null) {
+ return str;
+ }
+ }
+ return "&" + symbol; // not found //$NON-NLS-1$
+ }
+
+ /*
+ * A '&' has been read. Process a entity
+ */
+ private String processEntity() throws IOException {
+ StringBuffer buf = new StringBuffer();
+ int ch = nextChar();
+ while (Character.isLetterOrDigit((char) ch) || ch == '#') {
+ buf.append((char) ch);
+ ch = nextChar();
+ }
+
+ if (ch == ';')
+ return entity2Text(buf.toString());
+
+ buf.insert(0, '&');
+ if (ch != -1)
+ buf.append((char) ch);
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTMLPrinter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTMLPrinter.java
new file mode 100644
index 0000000..47484da
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/HTMLPrinter.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Provides a set of convenience methods for creating HTML pages.
+ */
+public class HTMLPrinter {
+
+ private HTMLPrinter() {
+ }
+
+ private static String replace(String text, char c, String s) {
+
+ int previous = 0;
+ int current = text.indexOf(c, previous);
+
+ if (current == -1)
+ return text;
+
+ StringBuffer buffer = new StringBuffer();
+ while (current > -1) {
+ buffer.append(text.substring(previous, current));
+ buffer.append(s);
+ previous = current + 1;
+ current = text.indexOf(c, previous);
+ }
+ buffer.append(text.substring(previous));
+
+ return buffer.toString();
+ }
+
+ public static String convertToHTMLContent(String content) {
+ content = replace(content, '<', "<"); //$NON-NLS-1$
+ return replace(content, '>', ">"); //$NON-NLS-1$
+ }
+
+ public static String read(Reader rd) {
+
+ StringBuffer buffer = new StringBuffer();
+ char[] readBuffer = new char[2048];
+
+ try {
+ int n = rd.read(readBuffer);
+ while (n > 0) {
+ buffer.append(readBuffer, 0, n);
+ n = rd.read(readBuffer);
+ }
+ return buffer.toString();
+ } catch (IOException x) {
+ }
+
+ return null;
+ }
+
+ public static void insertPageProlog(StringBuffer buffer, int position,
+ RGB bgRGB) {
+ if (bgRGB == null)
+ insertPageProlog(buffer, position);
+ else {
+ StringBuffer pageProlog = new StringBuffer(60);
+ pageProlog.append(""); //$NON-NLS-1$
+ buffer.insert(position, pageProlog.toString());
+ }
+ }
+
+ private static void appendColor(StringBuffer buffer, RGB rgb) {
+ buffer.append('#');
+ buffer.append(Integer.toHexString(rgb.red));
+ buffer.append(Integer.toHexString(rgb.green));
+ buffer.append(Integer.toHexString(rgb.blue));
+ }
+
+ public static void insertPageProlog(StringBuffer buffer, int position) {
+ RGB bgColor = null;
+ IWorkbenchWindow window = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow();
+ if (window != null) {
+ Display display = window.getShell().getDisplay();
+ if (display != null && !display.isDisposed())
+ bgColor = display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)
+ .getRGB();
+ }
+ if (bgColor == null)
+ bgColor = new RGB(255, 255, 225); // RGB value of info bg color on
+ // WindowsXP
+
+ insertPageProlog(buffer, position, bgColor); //$NON-NLS-1$
+ }
+
+ public static void addPageProlog(StringBuffer buffer) {
+ insertPageProlog(buffer, buffer.length());
+ }
+
+ public static void addPageEpilog(StringBuffer buffer) {
+ buffer.append(""); //$NON-NLS-1$
+ }
+
+ public static void startBulletList(StringBuffer buffer) {
+ buffer.append(""); //$NON-NLS-1$
+ }
+
+ public static void endBulletList(StringBuffer buffer) {
+ buffer.append("
"); //$NON-NLS-1$
+ }
+
+ public static void addBullet(StringBuffer buffer, String bullet) {
+ if (bullet != null) {
+ buffer.append(""); //$NON-NLS-1$
+ buffer.append(header);
+ buffer.append("
"); //$NON-NLS-1$
+ }
+ }
+
+ public static void addParagraph(StringBuffer buffer, String paragraph) {
+ if (paragraph != null) {
+ buffer.append("TypingRun
events.
+ *
+ * @since 3.0
+ */
+public interface ITypingRunListener {
+ /**
+ * Called when a new TypingRun
is started.
+ *
+ * @param run
+ * the newly started run
+ */
+ void typingRunStarted(TypingRun run);
+
+ /**
+ * Called whenever a TypingRun
is ended.
+ *
+ * @param run
+ * the ended run
+ * @param reason
+ * the type of change that caused the end of the run
+ */
+ void typingRunEnded(TypingRun run, ChangeType reason);
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaAnnotationHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaAnnotationHover.java
new file mode 100644
index 0000000..3b564d5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaAnnotationHover.java
@@ -0,0 +1,354 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.corext.Assert;
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+
+/**
+ * Determines all markers for the given line and collects, concatenates, and
+ * formates their messages.
+ */
+public class JavaAnnotationHover implements IAnnotationHover {
+ private static class JavaAnnotationHoverType {
+ }
+
+ public static final JavaAnnotationHoverType OVERVIEW_RULER_HOVER = new JavaAnnotationHoverType();
+
+ public static final JavaAnnotationHoverType TEXT_RULER_HOVER = new JavaAnnotationHoverType();
+
+ public static final JavaAnnotationHoverType VERTICAL_RULER_HOVER = new JavaAnnotationHoverType();
+
+ // private IPreferenceStore fStore =
+ // PHPeclipsePlugin.getDefault().getPreferenceStore();
+ private IPreferenceStore fStore = EditorsUI.getPreferenceStore();
+
+ private JavaAnnotationHoverType fType;
+
+ public JavaAnnotationHover(JavaAnnotationHoverType type) {
+ Assert.isTrue(OVERVIEW_RULER_HOVER.equals(type)
+ || TEXT_RULER_HOVER.equals(type)
+ || VERTICAL_RULER_HOVER.equals(type));
+ fType = type;
+ }
+
+ /**
+ * Returns the distance to the ruler line.
+ */
+ protected int compareRulerLine(Position position, IDocument document,
+ int line) {
+
+ if (position.getOffset() > -1 && position.getLength() > -1) {
+ try {
+ int javaAnnotationLine = document.getLineOfOffset(position
+ .getOffset());
+ if (line == javaAnnotationLine)
+ return 1;
+ if (javaAnnotationLine <= line
+ && line <= document.getLineOfOffset(position
+ .getOffset()
+ + position.getLength()))
+ return 2;
+ } catch (BadLocationException x) {
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Selects a set of markers from the two lists. By default, it just returns
+ * the set of exact matches.
+ */
+ protected List select(List exactMatch, List including) {
+ return exactMatch;
+ }
+
+ /**
+ * Returns one marker which includes the ruler's line of activity.
+ */
+ protected List getJavaAnnotationsForLine(ISourceViewer viewer, int line) {
+
+ IDocument document = viewer.getDocument();
+ IAnnotationModel model = viewer.getAnnotationModel();
+
+ if (model == null)
+ return null;
+
+ List exact = new ArrayList();
+ List including = new ArrayList();
+
+ Iterator e = model.getAnnotationIterator();
+ HashMap messagesAtPosition = new HashMap();
+ while (e.hasNext()) {
+ Annotation annotation = (Annotation) e.next();
+
+ if (annotation.getText() == null)
+ continue;
+
+ Position position = model.getPosition(annotation);
+ if (position == null)
+ continue;
+
+ AnnotationPreference preference = getAnnotationPreference(annotation);
+ if (preference == null)
+ continue;
+
+ if (OVERVIEW_RULER_HOVER.equals(fType)) {
+ String key = preference.getOverviewRulerPreferenceKey();
+ if (key == null || !fStore.getBoolean(key))
+ continue;
+ } else if (TEXT_RULER_HOVER.equals(fType)) {
+ String key = preference.getTextPreferenceKey();
+ if (key != null) {
+ if (!fStore.getBoolean(key))
+ continue;
+ } else {
+ key = preference.getHighlightPreferenceKey();
+ if (key == null || !fStore.getBoolean(key))
+ continue;
+ }
+ } else if (VERTICAL_RULER_HOVER.equals(fType)) {
+ String key = preference.getVerticalRulerPreferenceKey();
+ // backward compatibility
+ if (key != null && !fStore.getBoolean(key))
+ continue;
+ }
+
+ if (isDuplicateJavaAnnotation(messagesAtPosition, position,
+ annotation.getText()))
+ continue;
+
+ switch (compareRulerLine(position, document, line)) {
+ case 1:
+ exact.add(annotation);
+ break;
+ case 2:
+ including.add(annotation);
+ break;
+ }
+ }
+
+ return select(exact, including);
+ }
+
+ // /**
+ // * Returns one marker which includes the ruler's line of activity.
+ // */
+ // protected List getJavaAnnotationsForLine(ISourceViewer viewer, int line)
+ // {
+ //
+ // IDocument document= viewer.getDocument();
+ // IAnnotationModel model= viewer.getAnnotationModel();
+ //
+ // if (model == null)
+ // return null;
+ //
+ // List exact= new ArrayList();
+ // List including= new ArrayList();
+ //
+ // Iterator e= model.getAnnotationIterator();
+ // HashMap messagesAtPosition= new HashMap();
+ // while (e.hasNext()) {
+ // Object o= e.next();
+ // if (o instanceof IJavaAnnotation) {
+ // IJavaAnnotation a= (IJavaAnnotation)o;
+ // if (!a.hasOverlay()) {
+ // Position position= model.getPosition((Annotation)a);
+ // if (position == null)
+ // continue;
+ //
+ // if (isDuplicateJavaAnnotation(messagesAtPosition, position,
+ // a.getMessage()))
+ // continue;
+ //
+ // switch (compareRulerLine(position, document, line)) {
+ // case 1:
+ // exact.add(a);
+ // break;
+ // case 2:
+ // including.add(a);
+ // break;
+ // }
+ // }
+ // }
+ // }
+ //
+ // return select(exact, including);
+ // }
+
+ private boolean isDuplicateJavaAnnotation(Map messagesAtPosition,
+ Position position, String message) {
+ if (messagesAtPosition.containsKey(position)) {
+ Object value = messagesAtPosition.get(position);
+ if (message.equals(value))
+ return true;
+
+ if (value instanceof List) {
+ List messages = (List) value;
+ if (messages.contains(message))
+ return true;
+ else
+ messages.add(message);
+ } else {
+ ArrayList messages = new ArrayList();
+ messages.add(value);
+ messages.add(message);
+ messagesAtPosition.put(position, messages);
+ }
+ } else
+ messagesAtPosition.put(position, message);
+ return false;
+ }
+
+ /*
+ * @see IVerticalRulerHover#getHoverInfo(ISourceViewer, int)
+ */
+ public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
+ List javaAnnotations = getJavaAnnotationsForLine(sourceViewer,
+ lineNumber);
+ if (javaAnnotations != null) {
+
+ if (javaAnnotations.size() == 1) {
+
+ // optimization
+ Annotation annotation = (Annotation) javaAnnotations.get(0);
+ String message = annotation.getText();
+ if (message != null && message.trim().length() > 0)
+ return formatSingleMessage(message);
+
+ } else {
+
+ List messages = new ArrayList();
+
+ Iterator e = javaAnnotations.iterator();
+ while (e.hasNext()) {
+ Annotation annotation = (Annotation) e.next();
+ String message = annotation.getText();
+ if (message != null && message.trim().length() > 0)
+ messages.add(message.trim());
+ }
+
+ if (messages.size() == 1)
+ return formatSingleMessage((String) messages.get(0));
+
+ if (messages.size() > 1)
+ return formatMultipleMessages(messages);
+ }
+ }
+
+ return null;
+ }
+
+ /*
+ * @see IVerticalRulerHover#getHoverInfo(ISourceViewer, int)
+ */
+ // public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
+ // List javaAnnotations= getJavaAnnotationsForLine(sourceViewer,
+ // lineNumber);
+ // if (javaAnnotations != null) {
+ //
+ // if (javaAnnotations.size() == 1) {
+ //
+ // // optimization
+ // IJavaAnnotation javaAnnotation= (IJavaAnnotation) javaAnnotations.get(0);
+ // String message= javaAnnotation.getMessage();
+ // if (message != null && message.trim().length() > 0)
+ // return formatSingleMessage(message);
+ //
+ // } else {
+ //
+ // List messages= new ArrayList();
+ //
+ // Iterator e= javaAnnotations.iterator();
+ // while (e.hasNext()) {
+ // IJavaAnnotation javaAnnotation= (IJavaAnnotation) e.next();
+ // String message= javaAnnotation.getMessage();
+ // if (message != null && message.trim().length() > 0)
+ // messages.add(message.trim());
+ // }
+ //
+ // if (messages.size() == 1)
+ // return formatSingleMessage((String) messages.get(0));
+ //
+ // if (messages.size() > 1)
+ // return formatMultipleMessages(messages);
+ // }
+ // }
+ //
+ // return null;
+ // }
+ /*
+ * Formats a message as HTML text.
+ */
+ private String formatSingleMessage(String message) {
+ StringBuffer buffer = new StringBuffer();
+ HTMLPrinter.addPageProlog(buffer);
+ HTMLPrinter.addParagraph(buffer, HTMLPrinter
+ .convertToHTMLContent(message));
+ HTMLPrinter.addPageEpilog(buffer);
+ return buffer.toString();
+ }
+
+ /*
+ * Formats several message as HTML text.
+ */
+ private String formatMultipleMessages(List messages) {
+ StringBuffer buffer = new StringBuffer();
+ HTMLPrinter.addPageProlog(buffer);
+ HTMLPrinter
+ .addParagraph(
+ buffer,
+ HTMLPrinter
+ .convertToHTMLContent(PHPUIMessages
+ .getString("JavaAnnotationHover.multipleMarkersAtThisLine"))); //$NON-NLS-1$
+
+ HTMLPrinter.startBulletList(buffer);
+ Iterator e = messages.iterator();
+ while (e.hasNext())
+ HTMLPrinter.addBullet(buffer, HTMLPrinter
+ .convertToHTMLContent((String) e.next()));
+ HTMLPrinter.endBulletList(buffer);
+
+ HTMLPrinter.addPageEpilog(buffer);
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the annotation preference for the given annotation.
+ *
+ * @param annotation
+ * the annotation
+ * @return the annotation preference or null
if none
+ */
+ private AnnotationPreference getAnnotationPreference(Annotation annotation) {
+ return EditorsUI.getAnnotationPreferenceLookup()
+ .getAnnotationPreference(annotation);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaBreakIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaBreakIterator.java
new file mode 100644
index 0000000..f80d88a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaBreakIterator.java
@@ -0,0 +1,444 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.Assert;
+
+/**
+ * A java break iterator. It returns all breaks, including before and after
+ * whitespace, and it returns all camelcase breaks.
+ * true
if this run consumes ch
,
+ * false
otherwise. If true
is returned,
+ * the length of the receiver is adjusted accordingly.
+ *
+ * @param ch
+ * the character to test
+ * @return true
if ch
was consumed
+ */
+ protected boolean consume(char ch) {
+ if (isValid(ch)) {
+ length++;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Whether this run accepts that character; does not update state.
+ * Called from the default implementation of consume
.
+ *
+ * @param ch
+ * the character to test
+ * @return true
if ch
is accepted
+ */
+ protected abstract boolean isValid(char ch);
+
+ /**
+ * Resets this run to the initial state.
+ */
+ protected void init() {
+ length = 0;
+ }
+ }
+
+ static final class Whitespace extends Run {
+ protected boolean isValid(char ch) {
+ return Character.isWhitespace(ch) && ch != '\n' && ch != '\r';
+ }
+ }
+
+ static final class LineDelimiter extends Run {
+ /** State: INIT -> delimiter -> EXIT. */
+ private char fState;
+
+ private static final char INIT = '\0';
+
+ private static final char EXIT = '\1';
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaBreakIterator.Run#init()
+ */
+ protected void init() {
+ super.init();
+ fState = INIT;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaBreakIterator.Run#consume(char)
+ */
+ protected boolean consume(char ch) {
+ if (!isValid(ch) || fState == EXIT)
+ return false;
+
+ if (fState == INIT) {
+ fState = ch;
+ length++;
+ return true;
+ } else if (fState != ch) {
+ fState = EXIT;
+ length++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected boolean isValid(char ch) {
+ return ch == '\n' || ch == '\r';
+ }
+ }
+
+ static final class Identifier extends Run {
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaBreakIterator.Run#isValid(char)
+ */
+ protected boolean isValid(char ch) {
+ return Scanner.isPHPIdentifierPart(ch);
+ }
+ }
+
+ static final class CamelCaseIdentifier extends Run {
+ /* states */
+ private static final int S_INIT = 0;
+
+ private static final int S_LOWER = 1;
+
+ private static final int S_ONE_CAP = 2;
+
+ private static final int S_ALL_CAPS = 3;
+
+ private static final int S_EXIT = 4;
+
+ private static final int S_EXIT_MINUS_ONE = 5;
+
+ /* character types */
+ private static final int K_INVALID = 0;
+
+ private static final int K_LOWER = 1;
+
+ private static final int K_UPPER = 2;
+
+ private static final int K_OTHER = 3;
+
+ private int fState;
+
+ private final static int[][] MATRIX = new int[][] {
+ // K_INVALID, K_LOWER, K_UPPER, K_OTHER
+ { S_EXIT, S_LOWER, S_ONE_CAP, S_LOWER }, // S_INIT
+ { S_EXIT, S_LOWER, S_EXIT, S_LOWER }, // S_LOWER
+ { S_EXIT, S_LOWER, S_ALL_CAPS, S_LOWER }, // S_ONE_CAP
+ { S_EXIT, S_EXIT_MINUS_ONE, S_ALL_CAPS, S_LOWER }, // S_ALL_CAPS
+ };
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaBreakIterator.Run#init()
+ */
+ protected void init() {
+ super.init();
+ fState = S_INIT;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaBreakIterator.Run#consumes(char)
+ */
+ protected boolean consume(char ch) {
+ int kind = getKind(ch);
+ fState = MATRIX[fState][kind];
+ switch (fState) {
+ case S_LOWER:
+ case S_ONE_CAP:
+ case S_ALL_CAPS:
+ length++;
+ return true;
+ case S_EXIT:
+ return false;
+ case S_EXIT_MINUS_ONE:
+ length--;
+ return false;
+ default:
+ Assert.isTrue(false);
+ return false;
+ }
+ }
+
+ /**
+ * Determines the kind of a character.
+ *
+ * @param ch
+ * the character to test
+ */
+ private int getKind(char ch) {
+ if (Character.isUpperCase(ch))
+ return K_UPPER;
+ if (Character.isLowerCase(ch))
+ return K_LOWER;
+ if (Scanner.isPHPIdentifierPart(ch)) // _, digits...
+ return K_OTHER;
+ return K_INVALID;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaBreakIterator.Run#isValid(char)
+ */
+ protected boolean isValid(char ch) {
+ return Scanner.isPHPIdentifierPart(ch);
+ }
+ }
+
+ static final class Other extends Run {
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaBreakIterator.Run#isValid(char)
+ */
+ protected boolean isValid(char ch) {
+ return !Character.isWhitespace(ch)
+ && !Scanner.isPHPIdentifierPart(ch);
+ }
+ }
+
+ private static final Run WHITESPACE = new Whitespace();
+
+ private static final Run DELIMITER = new LineDelimiter();
+
+ private static final Run CAMELCASE = new CamelCaseIdentifier(); // new
+ // Identifier();
+
+ private static final Run OTHER = new Other();
+
+ /** The platform break iterator (word instance) used as a base. */
+ protected final BreakIterator fIterator;
+
+ /** The text we operate on. */
+ protected CharSequence fText;
+
+ /** our current position for the stateful methods. */
+ private int fIndex;
+
+ /**
+ * Creates a new break iterator.
+ */
+ public JavaBreakIterator() {
+ fIterator = BreakIterator.getWordInstance();
+ fIndex = fIterator.current();
+ }
+
+ /*
+ * @see java.text.BreakIterator#current()
+ */
+ public int current() {
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#first()
+ */
+ public int first() {
+ fIndex = fIterator.first();
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#following(int)
+ */
+ public int following(int offset) {
+ // work around too eager IAEs in standard impl
+ if (offset == getText().getEndIndex())
+ return DONE;
+
+ int next = fIterator.following(offset);
+ if (next == DONE)
+ return DONE;
+
+ // TODO deal with complex script word boundaries
+ // Math.min(offset + run.length, next) does not work
+ // since wordinstance considers _ as boundaries
+ // seems to work fine, however
+ Run run = consumeRun(offset);
+ return offset + run.length;
+
+ }
+
+ /**
+ * Consumes a run of characters at the limits of which we introduce a break.
+ *
+ * @param offset
+ * the offset to start at
+ * @return the run that was consumed
+ */
+ private Run consumeRun(int offset) {
+ // assert offset < length
+
+ char ch = fText.charAt(offset);
+ int length = fText.length();
+ Run run = getRun(ch);
+ while (run.consume(ch) && offset < length - 1) {
+ offset++;
+ ch = fText.charAt(offset);
+ }
+
+ return run;
+ }
+
+ /**
+ * Retunrs a run based on a character.
+ *
+ * @param ch
+ * the character to test
+ * @return the correct character given ch
+ */
+ private Run getRun(char ch) {
+ Run run;
+ if (WHITESPACE.isValid(ch))
+ run = WHITESPACE;
+ else if (DELIMITER.isValid(ch))
+ run = DELIMITER;
+ else if (CAMELCASE.isValid(ch))
+ run = CAMELCASE;
+ else if (OTHER.isValid(ch))
+ run = OTHER;
+ else {
+ Assert.isTrue(false);
+ return null;
+ }
+
+ run.init();
+ return run;
+ }
+
+ /*
+ * @see java.text.BreakIterator#getText()
+ */
+ public CharacterIterator getText() {
+ return fIterator.getText();
+ }
+
+ /*
+ * @see java.text.BreakIterator#isBoundary(int)
+ */
+ public boolean isBoundary(int offset) {
+ if (offset == getText().getBeginIndex())
+ return true;
+ else
+ return following(offset - 1) == offset;
+ }
+
+ /*
+ * @see java.text.BreakIterator#last()
+ */
+ public int last() {
+ fIndex = fIterator.last();
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#next()
+ */
+ public int next() {
+ fIndex = following(fIndex);
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#next(int)
+ */
+ public int next(int n) {
+ return fIterator.next(n);
+ }
+
+ /*
+ * @see java.text.BreakIterator#preceding(int)
+ */
+ public int preceding(int offset) {
+ if (offset == getText().getBeginIndex())
+ return DONE;
+
+ if (isBoundary(offset - 1))
+ return offset - 1;
+
+ int previous = offset - 1;
+ do {
+ previous = fIterator.preceding(previous);
+ } while (!isBoundary(previous));
+
+ int last = DONE;
+ while (previous < offset) {
+ last = previous;
+ previous = following(previous);
+ }
+
+ return last;
+ }
+
+ /*
+ * @see java.text.BreakIterator#previous()
+ */
+ public int previous() {
+ fIndex = preceding(fIndex);
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#setText(java.lang.String)
+ */
+ public void setText(String newText) {
+ setText((CharSequence) newText);
+ }
+
+ /**
+ * Creates a break iterator given a char sequence.
+ *
+ * @param newText
+ * the new text
+ */
+ public void setText(CharSequence newText) {
+ fText = newText;
+ fIterator.setText(new SequenceCharacterIterator(newText));
+ first();
+ }
+
+ /*
+ * @see java.text.BreakIterator#setText(java.text.CharacterIterator)
+ */
+ public void setText(CharacterIterator newText) {
+ if (newText instanceof CharSequence) {
+ fText = (CharSequence) newText;
+ fIterator.setText(newText);
+ first();
+ } else {
+ throw new UnsupportedOperationException(
+ "CharacterIterator not supported"); //$NON-NLS-1$
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaColorManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaColorManager.java
new file mode 100644
index 0000000..7578353
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaColorManager.java
@@ -0,0 +1,137 @@
+package net.sourceforge.phpdt.internal.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpdt.ui.text.IColorManagerExtension;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Java color manager.
+ */
+public class JavaColorManager implements IColorManager, IColorManagerExtension {
+ protected Map fKeyTable = new HashMap(10);
+
+ protected Map fDisplayTable = new HashMap(2);
+
+ /**
+ * Flag which tells if the colors are automatically disposed when the
+ * current display gets disposed.
+ */
+ private boolean fAutoDisposeOnDisplayDispose;
+
+ /**
+ * Creates a new Java color manager which automatically disposes the
+ * allocated colors when the current display gets disposed.
+ */
+ public JavaColorManager() {
+ this(true);
+ }
+
+ /**
+ * Creates a new Java color manager.
+ *
+ * @param autoDisposeOnDisplayDispose
+ * if true
the color manager automatically
+ * disposes all managed colors when the current display gets
+ * disposed and all calls to
+ * {@link org.eclipse.jface.text.source.ISharedTextColors#dispose()}
+ * are ignored.
+ *
+ * @since 2.1
+ */
+ public JavaColorManager(boolean autoDisposeOnDisplayDispose) {
+ fAutoDisposeOnDisplayDispose = autoDisposeOnDisplayDispose;
+ }
+
+ public void dispose(Display display) {
+ Map colorTable = (Map) fDisplayTable.get(display);
+ if (colorTable != null) {
+ Iterator e = colorTable.values().iterator();
+ while (e.hasNext()) {
+ Color color = (Color) e.next();
+ if (color != null && !color.isDisposed())
+ color.dispose();
+ }
+ }
+ }
+
+ /*
+ * @see IColorManager#getColor(RGB)
+ */
+ public Color getColor(RGB rgb) {
+
+ if (rgb == null)
+ return null;
+
+ final Display display = Display.getCurrent();
+ Map colorTable = (Map) fDisplayTable.get(display);
+ if (colorTable == null) {
+ colorTable = new HashMap(10);
+ fDisplayTable.put(display, colorTable);
+ if (fAutoDisposeOnDisplayDispose) {
+ display.disposeExec(new Runnable() {
+ public void run() {
+ dispose(display);
+ }
+ });
+ }
+ }
+
+ Color color = (Color) colorTable.get(rgb);
+ if (color == null) {
+ color = new Color(Display.getCurrent(), rgb);
+ colorTable.put(rgb, color);
+ }
+
+ return color;
+ }
+
+ /*
+ * @see IColorManager#dispose
+ */
+ public void dispose() {
+ if (!fAutoDisposeOnDisplayDispose)
+ dispose(Display.getCurrent());
+ }
+
+ /*
+ * @see IColorManager#getColor(String)
+ */
+ public Color getColor(String key) {
+
+ if (key == null)
+ return null;
+
+ RGB rgb = (RGB) fKeyTable.get(key);
+ return getColor(rgb);
+ }
+
+ /*
+ * @see IColorManagerExtension#bindColor(String, RGB)
+ */
+ public void bindColor(String key, RGB rgb) {
+ Object value = fKeyTable.get(key);
+ if (value != null)
+ throw new UnsupportedOperationException();
+
+ fKeyTable.put(key, rgb);
+ }
+
+ /*
+ * @see IColorManagerExtension#unbindColor(String)
+ */
+ public void unbindColor(String key) {
+ fKeyTable.remove(key);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaCompositeReconcilingStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaCompositeReconcilingStrategy.java
new file mode 100644
index 0000000..77423a6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaCompositeReconcilingStrategy.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.internal.ui.text.java.IProblemRequestorExtension;
+import net.sourceforge.phpdt.internal.ui.text.java.JavaReconcilingStrategy;
+import net.sourceforge.phpdt.internal.ui.text.spelling.SpellReconcileStrategy;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Reconciling strategy for Java code. This is a composite strategy containing
+ * the regular java model reconciler and the comment spell checking strategy.
+ *
+ * @since 3.0
+ */
+public class JavaCompositeReconcilingStrategy extends
+ CompositeReconcilingStrategy {
+
+ private ITextEditor fEditor;
+
+ private JavaReconcilingStrategy fJavaStrategy;
+
+ /**
+ * Creates a new Java reconciling strategy.
+ *
+ * @param editor
+ * the editor of the strategy's reconciler
+ * @param documentPartitioning
+ * the document partitioning this strategy uses for configuration
+ */
+ public JavaCompositeReconcilingStrategy(ITextEditor editor,
+ String documentPartitioning) {
+ fEditor = editor;
+ fJavaStrategy = new JavaReconcilingStrategy(editor);
+ setReconcilingStrategies(new IReconcilingStrategy[] {
+ fJavaStrategy,
+ new SpellReconcileStrategy(editor, documentPartitioning,
+ PreferenceConstants.getPreferenceStore()) });
+ }
+
+ /**
+ * Returns the problem requestor for the editor's input element.
+ *
+ * @return the problem requestor for the editor's input element
+ */
+ private IProblemRequestorExtension getProblemRequestorExtension() {
+ IDocumentProvider p = fEditor.getDocumentProvider();
+ if (p == null) {
+ try {
+ // work around for
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=51522
+ p = WebUI.getDefault()
+ .getCompilationUnitDocumentProvider();
+ } catch (NullPointerException npe) {
+ return null;
+ }
+ }
+ IAnnotationModel m = p.getAnnotationModel(fEditor.getEditorInput());
+ if (m instanceof IProblemRequestorExtension)
+ return (IProblemRequestorExtension) m;
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.CompositeReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,
+ * org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ IProblemRequestorExtension e = getProblemRequestorExtension();
+ if (e != null) {
+ try {
+ e.beginReportingSequence();
+ super.reconcile(dirtyRegion, subRegion);
+ } finally {
+ e.endReportingSequence();
+ }
+ } else {
+ super.reconcile(dirtyRegion, subRegion);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.CompositeReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(IRegion partition) {
+ IProblemRequestorExtension e = getProblemRequestorExtension();
+ if (e != null) {
+ try {
+ e.beginReportingSequence();
+ super.reconcile(partition);
+ } finally {
+ e.endReportingSequence();
+ }
+ } else {
+ super.reconcile(partition);
+ }
+ }
+
+ /**
+ * Tells this strategy whether to inform its listeners.
+ *
+ * @param notify
+ * true
if listeners should be notified
+ */
+ public void notifyListeners(boolean notify) {
+ fJavaStrategy.notifyListeners(notify);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.CompositeReconcilingStrategy#initialReconcile()
+ */
+ public void initialReconcile() {
+ IProblemRequestorExtension e = getProblemRequestorExtension();
+ if (e != null) {
+ try {
+ e.beginReportingSequence();
+ super.initialReconcile();
+ } finally {
+ e.endReportingSequence();
+ }
+ } else {
+ super.initialReconcile();
+ }
+ }
+
+ /**
+ * Called before reconciling is started.
+ *
+ * @since 3.0
+ */
+ public void aboutToBeReconciled() {
+ fJavaStrategy.aboutToBeReconciled();
+
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaElementProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaElementProvider.java
new file mode 100644
index 0000000..db4ef87
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaElementProvider.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.actions.SelectionConverter;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.IInformationProviderExtension;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Provides a Java element to be displayed in by an information presenter.
+ */
+public class JavaElementProvider implements IInformationProvider,
+ IInformationProviderExtension {
+
+ private PHPEditor fEditor;
+
+ private boolean fUseCodeResolve;
+
+ public JavaElementProvider(IEditorPart editor) {
+ fUseCodeResolve = false;
+ if (editor instanceof PHPEditor)
+ fEditor = (PHPEditor) editor;
+ }
+
+ public JavaElementProvider(IEditorPart editor, boolean useCodeResolve) {
+ this(editor);
+ fUseCodeResolve = useCodeResolve;
+ }
+
+ /*
+ * @see IInformationProvider#getSubject(ITextViewer, int)
+ */
+ public IRegion getSubject(ITextViewer textViewer, int offset) {
+ if (textViewer != null && fEditor != null) {
+ IRegion region = JavaWordFinder.findWord(textViewer.getDocument(),
+ offset);
+ if (region != null)
+ return region;
+ else
+ return new Region(offset, 0);
+ }
+ return null;
+ }
+
+ /*
+ * @see IInformationProvider#getInformation(ITextViewer, IRegion)
+ */
+ public String getInformation(ITextViewer textViewer, IRegion subject) {
+ return getInformation2(textViewer, subject).toString();
+ }
+
+ /*
+ * @see IInformationProviderExtension#getElement(ITextViewer, IRegion)
+ */
+ public Object getInformation2(ITextViewer textViewer, IRegion subject) {
+ if (fEditor == null)
+ return null;
+
+ try {
+ if (fUseCodeResolve) {
+ IStructuredSelection sel = SelectionConverter
+ .getStructuredSelection(fEditor);
+ if (!sel.isEmpty())
+ return sel.getFirstElement();
+ }
+ IJavaElement element = SelectionConverter
+ .getElementAtOffset(fEditor);
+ if (element != null)
+ return element;
+ return SelectionConverter.getInput(fEditor);
+ } catch (JavaModelException e) {
+ return null;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaHeuristicScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaHeuristicScanner.java
new file mode 100644
index 0000000..0ca33ab
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaHeuristicScanner.java
@@ -0,0 +1,1030 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.Arrays;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+
+/**
+ * Utility methods for heuristic based Java manipulations in an incomplete Java
+ * source file.
+ *
+ * fDocument.getLength()
(forward scanning).
+ */
+ public static final int UNBOUND = -2;
+
+ /* character constants */
+ private static final char LBRACE = '{';
+
+ private static final char RBRACE = '}';
+
+ private static final char LPAREN = '(';
+
+ private static final char RPAREN = ')';
+
+ private static final char SEMICOLON = ';';
+
+ private static final char COLON = ':';
+
+ private static final char COMMA = ',';
+
+ private static final char LBRACKET = '[';
+
+ private static final char RBRACKET = ']';
+
+ private static final char QUESTIONMARK = '?';
+
+ private static final char EQUAL = '=';
+
+ /**
+ * Specifies the stop condition, upon which the scanXXX
+ * methods will decide whether to keep scanning or not. This interface may
+ * implemented by clients.
+ */
+ public interface StopCondition {
+ /**
+ * Instructs the scanner to return the current position.
+ *
+ * @param ch
+ * the char at the current position
+ * @param position
+ * the current position
+ * @param forward
+ * the iteration direction
+ * @return true
if the stop condition is met.
+ */
+ boolean stop(char ch, int position, boolean forward);
+ }
+
+ /**
+ * Stops upon a non-whitespace (as defined by
+ * {@link Character#isWhitespace(char)}) character.
+ */
+ private static class NonWhitespace implements StopCondition {
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+ */
+ public boolean stop(char ch, int position, boolean forward) {
+ return !Character.isWhitespace(ch);
+ }
+ }
+
+ /**
+ * Stops upon a non-whitespace character in the default partition.
+ *
+ * @see NonWhitespace
+ */
+ private class NonWhitespaceDefaultPartition extends NonWhitespace {
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+ */
+ public boolean stop(char ch, int position, boolean forward) {
+ return super.stop(ch, position, true)
+ && isDefaultPartition(position);
+ }
+ }
+
+ /**
+ * Stops upon a non-java identifier (as defined by
+ * {@link Scanner#isPHPIdentifierPart(char)}) character.
+ */
+ private static class NonJavaIdentifierPart implements StopCondition {
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+ */
+ public boolean stop(char ch, int position, boolean forward) {
+ return !Scanner.isPHPIdentifierPart(ch);
+ }
+ }
+
+ /**
+ * Stops upon a non-java identifier character in the default partition.
+ *
+ * @see NonJavaIdentifierPart
+ */
+ private class NonJavaIdentifierPartDefaultPartition extends
+ NonJavaIdentifierPart {
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+ */
+ public boolean stop(char ch, int position, boolean forward) {
+ return super.stop(ch, position, true)
+ || !isDefaultPartition(position);
+ }
+ }
+
+ /**
+ * Stops upon a character in the default partition that matches the given
+ * character list.
+ */
+ private class CharacterMatch implements StopCondition {
+ private final char[] fChars;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param ch
+ * the single character to match
+ */
+ public CharacterMatch(char ch) {
+ this(new char[] { ch });
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param chars
+ * the chars to match.
+ */
+ public CharacterMatch(char[] chars) {
+ Assert.isNotNull(chars);
+ Assert.isTrue(chars.length > 0);
+ fChars = chars;
+ Arrays.sort(chars);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char,
+ * int)
+ */
+ public boolean stop(char ch, int position, boolean forward) {
+ return Arrays.binarySearch(fChars, ch) >= 0
+ && isDefaultPartition(position);
+ }
+ }
+
+ /**
+ * Acts like character match, but skips all scopes introduced by
+ * parenthesis, brackets, and braces.
+ */
+ protected class SkippingScopeMatch extends CharacterMatch {
+ private char fOpening, fClosing;
+
+ private int fDepth = 0;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param ch
+ * the single character to match
+ */
+ public SkippingScopeMatch(char ch) {
+ super(ch);
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param chars
+ * the chars to match.
+ */
+ public SkippingScopeMatch(char[] chars) {
+ super(chars);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char,
+ * int)
+ */
+ public boolean stop(char ch, int position, boolean forward) {
+
+ if (fDepth == 0 && super.stop(ch, position, true))
+ return true;
+ else if (ch == fOpening)
+ fDepth++;
+ else if (ch == fClosing) {
+ fDepth--;
+ if (fDepth == 0) {
+ fOpening = 0;
+ fClosing = 0;
+ }
+ } else if (fDepth == 0) {
+ fDepth = 1;
+ if (forward) {
+
+ switch (ch) {
+ case LBRACE:
+ fOpening = LBRACE;
+ fClosing = RBRACE;
+ break;
+ case LPAREN:
+ fOpening = LPAREN;
+ fClosing = RPAREN;
+ break;
+ case LBRACKET:
+ fOpening = LBRACKET;
+ fClosing = RBRACKET;
+ break;
+ }
+
+ } else {
+ switch (ch) {
+ case RBRACE:
+ fOpening = RBRACE;
+ fClosing = LBRACE;
+ break;
+ case RPAREN:
+ fOpening = RPAREN;
+ fClosing = LPAREN;
+ break;
+ case RBRACKET:
+ fOpening = RBRACKET;
+ fClosing = LBRACKET;
+ break;
+ }
+
+ }
+ }
+
+ return false;
+
+ }
+
+ }
+
+ /** The document being scanned. */
+ private IDocument fDocument;
+
+ /** The partitioning being used for scanning. */
+ private String fPartitioning;
+
+ /** The partition to scan in. */
+ private String fPartition;
+
+ /* internal scan state */
+
+ /** the most recently read character. */
+ private char fChar;
+
+ /** the most recently read position. */
+ private int fPos;
+
+ /* preset stop conditions */
+ private final StopCondition fNonWSDefaultPart = new NonWhitespaceDefaultPartition();
+
+ private final static StopCondition fNonWS = new NonWhitespace();
+
+ private final StopCondition fNonIdent = new NonJavaIdentifierPartDefaultPartition();
+
+ /**
+ * Creates a new instance.
+ *
+ * @param document
+ * the document to scan
+ * @param partitioning
+ * the partitioning to use for scanning
+ * @param partition
+ * the partition to scan in
+ */
+ public JavaHeuristicScanner(IDocument document, String partitioning,
+ String partition) {
+ Assert.isNotNull(document);
+ Assert.isNotNull(partitioning);
+ Assert.isNotNull(partition);
+ fDocument = document;
+ fPartitioning = partitioning;
+ fPartition = partition;
+ }
+
+ /**
+ * Calls
+ * this(document, IJavaPartitions.JAVA_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE)
.
+ *
+ * @param document
+ * the document to scan.
+ */
+ public JavaHeuristicScanner(IDocument document) {
+// this(document, IPHPPartitions.PHP_PARTITIONING,
+// IDocument.DEFAULT_CONTENT_TYPE);
+ this(document, IPHPPartitions.PHP_PARTITIONING,
+ PHPDocumentPartitioner.PHP_SCRIPT_CODE);
+ }
+
+ /**
+ * Returns the most recent internal scan position.
+ *
+ * @return the most recent internal scan position.
+ */
+ public int getPosition() {
+ return fPos;
+ }
+
+ /**
+ * Returns the next token in forward direction, starting at
+ * start
, and not extending further than bound
.
+ * The return value is one of the constants defined in {@link Symbols}.
+ * After a call, {@link #getPosition()} will return the position just after
+ * the scanned token (i.e. the next position that will be scanned).
+ *
+ * @param start
+ * the first character position in the document to consider
+ * @param bound
+ * the first position not to consider any more
+ * @return a constant from {@link Symbols} describing the next token
+ */
+ public int nextToken(int start, int bound) {
+ int pos = scanForward(start, bound, fNonWSDefaultPart);
+ if (pos == NOT_FOUND)
+ return TokenEOF;
+
+ fPos++;
+
+ switch (fChar) {
+ case LBRACE:
+ return TokenLBRACE;
+ case RBRACE:
+ return TokenRBRACE;
+ case LBRACKET:
+ return TokenLBRACKET;
+ case RBRACKET:
+ return TokenRBRACKET;
+ case LPAREN:
+ return TokenLPAREN;
+ case RPAREN:
+ return TokenRPAREN;
+ case SEMICOLON:
+ return TokenSEMICOLON;
+ case COMMA:
+ return TokenCOMMA;
+ case QUESTIONMARK:
+ return TokenQUESTIONMARK;
+ case EQUAL:
+ try {
+ if (fDocument.getChar(fPos) == '>') {
+ fPos++;
+ return TokenOTHER;
+ }
+ } catch (BadLocationException e) {
+ }
+ return TokenEQUAL;
+ case '<':
+ try {
+ if (fDocument.get(fPos, 4).equalsIgnoreCase("?php")) {
+ fPos += 4;
+ return TokenEOF;
+ } else if (fDocument.getChar(fPos) == '?') {
+ fPos++;
+ return TokenEOF;
+ }
+ } catch (BadLocationException e) {
+ }
+ }
+
+ // else
+ if (Scanner.isPHPIdentifierPart(fChar)) {
+ // assume an ident or keyword
+ int from = pos, to;
+ pos = scanForward(pos + 1, bound, fNonIdent);
+ if (pos == NOT_FOUND)
+ to = bound == UNBOUND ? fDocument.getLength() : bound;
+ else
+ to = pos;
+
+ String identOrKeyword;
+ try {
+ identOrKeyword = fDocument.get(from, to - from);
+ } catch (BadLocationException e) {
+ return TokenEOF;
+ }
+
+ return getToken(identOrKeyword);
+
+ } else {
+ // operators, number literals etc
+ return TokenOTHER;
+ }
+ }
+
+ /**
+ * Returns the next token in backward direction, starting at
+ * start
, and not extending further than bound
.
+ * The return value is one of the constants defined in {@link Symbols}.
+ * After a call, {@link #getPosition()} will return the position just before
+ * the scanned token starts (i.e. the next position that will be scanned).
+ *
+ * @param start
+ * the first character position in the document to consider
+ * @param bound
+ * the first position not to consider any more
+ * @return a constant from {@link Symbols} describing the previous token
+ */
+ public int previousToken(int start, int bound) {
+ int pos = scanBackward(start, bound, fNonWSDefaultPart);
+ if (pos == NOT_FOUND)
+ return TokenEOF;
+
+ fPos--;
+
+ switch (fChar) {
+ case LBRACE:
+ return TokenLBRACE;
+ case RBRACE:
+ return TokenRBRACE;
+ case LBRACKET:
+ return TokenLBRACKET;
+ case RBRACKET:
+ return TokenRBRACKET;
+ case LPAREN:
+ return TokenLPAREN;
+ case RPAREN:
+ return TokenRPAREN;
+ case SEMICOLON:
+ return TokenSEMICOLON;
+ case COLON:
+ return TokenCOLON;
+ case COMMA:
+ return TokenCOMMA;
+ case QUESTIONMARK:
+ return TokenQUESTIONMARK;
+ case EQUAL:
+ return TokenEQUAL;
+ case '>':
+ try {
+ switch (fDocument.getChar(fPos)) {
+ case '=':
+ fPos--;
+ return TokenOTHER;
+ case '?':
+ fPos--;
+ return TokenEOF;
+ }
+ } catch (BadLocationException e) {
+ }
+ }
+
+ // else
+ if (Scanner.isPHPIdentifierPart(fChar)) {
+ // assume an ident or keyword
+ int from, to = pos + 1;
+ pos = scanBackward(pos - 1, bound, fNonIdent);
+ if (pos == NOT_FOUND)
+ from = bound == UNBOUND ? 0 : bound + 1;
+ else
+ from = pos + 1;
+
+ String identOrKeyword;
+ try {
+ identOrKeyword = fDocument.get(from, to - from);
+ } catch (BadLocationException e) {
+ return TokenEOF;
+ }
+
+ return getToken(identOrKeyword);
+
+ } else {
+ // operators, number literals etc
+ return TokenOTHER;
+ }
+
+ }
+
+ /**
+ * Returns one of the keyword constants or TokenIDENT
for a
+ * scanned identifier.
+ *
+ * @param s
+ * a scanned identifier
+ * @return one of the constants defined in {@link Symbols}
+ */
+ private int getToken(String s) {
+ Assert.isNotNull(s);
+
+ switch (s.length()) {
+ case 2:
+ if ("if".equals(s)) //$NON-NLS-1$
+ return TokenIF;
+ if ("do".equals(s)) //$NON-NLS-1$
+ return TokenDO;
+ break;
+ case 3:
+ if ("for".equals(s)) //$NON-NLS-1$
+ return TokenFOR;
+ if ("try".equals(s)) //$NON-NLS-1$
+ return TokenTRY;
+ if ("new".equals(s)) //$NON-NLS-1$
+ return TokenNEW;
+ break;
+ case 4:
+ if ("case".equals(s)) //$NON-NLS-1$
+ return TokenCASE;
+ if ("else".equals(s)) //$NON-NLS-1$
+ return TokenELSE;
+ if ("goto".equals(s)) //$NON-NLS-1$
+ return TokenGOTO;
+ break;
+ case 5:
+ if ("break".equals(s)) //$NON-NLS-1$
+ return TokenBREAK;
+ if ("catch".equals(s)) //$NON-NLS-1$
+ return TokenCATCH;
+ if ("while".equals(s)) //$NON-NLS-1$
+ return TokenWHILE;
+ break;
+ case 6:
+ if ("return".equals(s)) //$NON-NLS-1$
+ return TokenRETURN;
+ if ("static".equals(s)) //$NON-NLS-1$
+ return TokenSTATIC;
+ if ("switch".equals(s)) //$NON-NLS-1$
+ return TokenSWITCH;
+ break;
+ case 7:
+ if ("default".equals(s)) //$NON-NLS-1$
+ return TokenDEFAULT;
+ if ("finally".equals(s)) //$NON-NLS-1$
+ return TokenFINALLY;
+ break;
+ case 12:
+ if ("synchronized".equals(s)) //$NON-NLS-1$
+ return TokenSYNCHRONIZED;
+ break;
+ }
+ return TokenIDENT;
+ }
+
+ /**
+ * Returns the position of the closing peer character (forward search). Any
+ * scopes introduced by opening peers are skipped. All peers accounted for
+ * must reside in the default partition.
+ *
+ * start
must not point to the opening peer, but to
+ * the first character being searched.
+ * NOT_FOUND
+ */
+ public int findClosingPeer(int start, final char openingPeer,
+ final char closingPeer) {
+ Assert.isNotNull(fDocument);
+ Assert.isTrue(start >= 0);
+
+ try {
+ int depth = 1;
+ start -= 1;
+ while (true) {
+ start = scanForward(start + 1, UNBOUND, new CharacterMatch(
+ new char[] { openingPeer, closingPeer }));
+ if (start == NOT_FOUND)
+ return NOT_FOUND;
+
+ if (fDocument.getChar(start) == openingPeer)
+ depth++;
+ else
+ depth--;
+
+ if (depth == 0)
+ return start;
+ }
+
+ } catch (BadLocationException e) {
+ return NOT_FOUND;
+ }
+ }
+
+ /**
+ * Returns the position of the opening peer character (backward search). Any
+ * scopes introduced by closing peers are skipped. All peers accounted for
+ * must reside in the default partition.
+ *
+ * start
must not point to the closing peer, but to
+ * the first character being searched.
+ * NOT_FOUND
+ */
+ public int findOpeningPeer(int start, char openingPeer, char closingPeer) {
+ Assert.isTrue(start < fDocument.getLength());
+
+ try {
+ int depth = 1;
+ start += 1;
+ while (true) {
+ start = scanBackward(start - 1, UNBOUND, new CharacterMatch(
+ new char[] { openingPeer, closingPeer }));
+ if (start == NOT_FOUND)
+ return NOT_FOUND;
+
+ if (fDocument.getChar(start) == closingPeer)
+ depth++;
+ else
+ depth--;
+
+ if (depth == 0)
+ return start;
+ }
+
+ } catch (BadLocationException e) {
+ return NOT_FOUND;
+ }
+ }
+
+ /**
+ * Computes the surrounding block around offset
. The search
+ * is started at the beginning of offset
, i.e. an opening
+ * brace at offset
will not be part of the surrounding block,
+ * but a closing brace will.
+ *
+ * @param offset
+ * the offset for which the surrounding block is computed
+ * @return a region describing the surrounding block, or null
+ * if none can be found
+ */
+ public IRegion findSurroundingBlock(int offset) {
+ if (offset < 1 || offset >= fDocument.getLength())
+ return null;
+
+ int begin = findOpeningPeer(offset - 1, LBRACE, RBRACE);
+ int end = findClosingPeer(offset, LBRACE, RBRACE);
+ if (begin == NOT_FOUND || end == NOT_FOUND)
+ return null;
+ return new Region(begin, end + 1 - begin);
+ }
+
+ /**
+ * Finds the smallest position in fDocument
such that the
+ * position is >= position
and < bound
+ * and Character.isWhitespace(fDocument.getChar(pos))
+ * evaluates to false
and the position is in the default
+ * partition.
+ *
+ * @param position
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
> position
,
+ * or UNBOUND
+ * @return the smallest position of a non-whitespace character in [position
,
+ * bound
) that resides in a Java partition, or
+ * NOT_FOUND
if none can be found
+ */
+ public int findNonWhitespaceForward(int position, int bound) {
+ return scanForward(position, bound, fNonWSDefaultPart);
+ }
+
+ /**
+ * Finds the smallest position in fDocument
such that the
+ * position is >= position
and < bound
+ * and Character.isWhitespace(fDocument.getChar(pos))
+ * evaluates to false
.
+ *
+ * @param position
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
> position
,
+ * or UNBOUND
+ * @return the smallest position of a non-whitespace character in [position
,
+ * bound
), or NOT_FOUND
if none can
+ * be found
+ */
+ public int findNonWhitespaceForwardInAnyPartition(int position, int bound) {
+ return scanForward(position, bound, fNonWS);
+ }
+
+ /**
+ * Finds the highest position in fDocument
such that the
+ * position is <= position
and > bound
+ * and Character.isWhitespace(fDocument.getChar(pos))
+ * evaluates to false
and the position is in the default
+ * partition.
+ *
+ * @param position
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
< position
,
+ * or UNBOUND
+ * @return the highest position of a non-whitespace character in (bound
,
+ * position
] that resides in a Java partition, or
+ * NOT_FOUND
if none can be found
+ */
+ public int findNonWhitespaceBackward(int position, int bound) {
+ return scanBackward(position, bound, fNonWSDefaultPart);
+ }
+
+ /**
+ * Finds the lowest position p
in fDocument
+ * such that start
<= p < bound
and
+ * condition.stop(fDocument.getChar(p), p)
evaluates to
+ * true
.
+ *
+ * @param start
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
> start
,
+ * or UNBOUND
+ * @param condition
+ * the StopCondition
to check
+ * @return the lowest position in [start
,
+ * bound
) for which condition
holds,
+ * or NOT_FOUND
if none can be found
+ */
+ public int scanForward(int start, int bound, StopCondition condition) {
+ Assert.isTrue(start >= 0);
+
+ if (bound == UNBOUND)
+ bound = fDocument.getLength();
+
+ Assert.isTrue(bound <= fDocument.getLength());
+
+ try {
+ fPos = start;
+ while (fPos < bound) {
+
+ fChar = fDocument.getChar(fPos);
+ // omit closing tag
+ if (fChar == '?') {
+ if (fPos < fDocument.getLength() - 1) {
+ if (fDocument.get(fPos - 1, 2).equalsIgnoreCase("?>")) {
+ fPos++;
+ return NOT_FOUND;
+ }
+ }
+ }
+ if (condition.stop(fChar, fPos, true))
+ return fPos;
+
+ fPos++;
+ }
+ } catch (BadLocationException e) {
+ }
+ return NOT_FOUND;
+ }
+
+ /**
+ * Finds the lowest position in fDocument
such that the
+ * position is >= position
and < bound
+ * and fDocument.getChar(position) == ch
evaluates to
+ * true
and the position is in the default partition.
+ *
+ * @param position
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
> position
,
+ * or UNBOUND
+ * @param ch
+ * the char
to search for
+ * @return the lowest position of ch
in (bound
,
+ * position
] that resides in a Java partition, or
+ * NOT_FOUND
if none can be found
+ */
+ public int scanForward(int position, int bound, char ch) {
+ return scanForward(position, bound, new CharacterMatch(ch));
+ }
+
+ /**
+ * Finds the lowest position in fDocument
such that the
+ * position is >= position
and < bound
+ * and fDocument.getChar(position) == ch
evaluates to
+ * true
for at least one ch in chars
and the
+ * position is in the default partition.
+ *
+ * @param position
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
> position
,
+ * or UNBOUND
+ * @param chars
+ * an array of char
to search for
+ * @return the lowest position of a non-whitespace character in [position
,
+ * bound
) that resides in a Java partition, or
+ * NOT_FOUND
if none can be found
+ */
+ public int scanForward(int position, int bound, char[] chars) {
+ return scanForward(position, bound, new CharacterMatch(chars));
+ }
+
+ /**
+ * Finds the highest position p
in fDocument
+ * such that bound
< p
<=
+ * start
and
+ * condition.stop(fDocument.getChar(p), p)
evaluates to
+ * true
.
+ *
+ * @param start
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
< start
,
+ * or UNBOUND
+ * @param condition
+ * the StopCondition
to check
+ * @return the highest position in (bound
,
+ * start
for which condition
holds, or
+ * NOT_FOUND
if none can be found
+ */
+ public int scanBackward(int start, int bound, StopCondition condition) {
+ if (bound == UNBOUND)
+ bound = -1;
+
+ Assert.isTrue(bound >= -1);
+ Assert.isTrue(start < fDocument.getLength());
+
+ try {
+ fPos = start;
+ while (fPos > bound) {
+
+ fChar = fDocument.getChar(fPos);
+ // omit opening tag
+ if (fChar == 'p' || fChar == 'P') {
+ if (fPos >= 4) {
+ if (fDocument.get(fPos - 4, 5).equalsIgnoreCase("= 1) {
+ if (fDocument.get(fPos - 1, 2).equalsIgnoreCase("")) {
+ fPos--;
+ return NOT_FOUND;
+ }
+ }
+ }
+ if (condition.stop(fChar, fPos, false))
+ return fPos;
+
+ fPos--;
+ }
+ } catch (BadLocationException e) {
+ }
+ return NOT_FOUND;
+ }
+
+ /**
+ * Finds the highest position in fDocument
such that the
+ * position is <= position
and > bound
+ * and fDocument.getChar(position) == ch
evaluates to
+ * true
for at least one ch in chars
and the
+ * position is in the default partition.
+ *
+ * @param position
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
< position
,
+ * or UNBOUND
+ * @param ch
+ * the char
to search for
+ * @return the highest position of one element in chars
in (bound
,
+ * position
] that resides in a Java partition, or
+ * NOT_FOUND
if none can be found
+ */
+ public int scanBackward(int position, int bound, char ch) {
+ return scanBackward(position, bound, new CharacterMatch(ch));
+ }
+
+ /**
+ * Finds the highest position in fDocument
such that the
+ * position is <= position
and > bound
+ * and fDocument.getChar(position) == ch
evaluates to
+ * true
for at least one ch in chars
and the
+ * position is in the default partition.
+ *
+ * @param position
+ * the first character position in fDocument
to be
+ * considered
+ * @param bound
+ * the first position in fDocument
to not consider
+ * any more, with bound
< position
,
+ * or UNBOUND
+ * @param chars
+ * an array of char
to search for
+ * @return the highest position of one element in chars
in (bound
,
+ * position
] that resides in a Java partition, or
+ * NOT_FOUND
if none can be found
+ */
+ public int scanBackward(int position, int bound, char[] chars) {
+ return scanBackward(position, bound, new CharacterMatch(chars));
+ }
+
+ /**
+ * Checks whether position
resides in a default (Java)
+ * partition of fDocument
.
+ *
+ * @param position
+ * the position to be checked
+ * @return true
if position
is in the default
+ * partition of fDocument
, false
+ * otherwise
+ */
+ public boolean isDefaultPartition(int position) {
+ Assert.isTrue(position >= 0);
+ Assert.isTrue(position <= fDocument.getLength());
+
+ try {
+ ITypedRegion region = TextUtilities.getPartition(fDocument,
+ fPartitioning, position, false);
+ return region.getType().equals(fPartition);
+
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks if the line seems to be an open condition not followed by a block
+ * (i.e. an if, while, or for statement with just one following statement,
+ * see example below).
+ *
+ *
+ * if (condition)
+ * doStuff();
+ *
+ *
+ * true
if the code is a conditional statement or
+ * loop without a block, false
otherwise
+ */
+ public boolean isBracelessBlockStart(int position, int bound) {
+ if (position < 1)
+ return false;
+
+ switch (previousToken(position, bound)) {
+ case TokenDO:
+ case TokenELSE:
+ return true;
+ case TokenRPAREN:
+ position = findOpeningPeer(fPos, LPAREN, RPAREN);
+ if (position > 0) {
+ switch (previousToken(position - 1, bound)) {
+ case TokenIF:
+ case TokenFOR:
+ case TokenWHILE:
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaIndenter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaIndenter.java
new file mode 100644
index 0000000..ef0c4ae
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaIndenter.java
@@ -0,0 +1,1519 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.formatter.DefaultCodeFormatterConstants;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+
+/**
+ * Uses the {@link net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner}to
+ * get the indentation level for a certain position in a document.
+ *
+ * findPreviousIndenationUnit
. */
+ private int fIndent;
+
+ /**
+ * The absolute (character-counted) indentation offset for special cases
+ * (method defs, array initializers)
+ */
+ private int fAlign;
+
+ /** The stateful scanposition for the indentation methods. */
+ private int fPosition;
+
+ /** The previous position. */
+ private int fPreviousPos;
+
+ /** The most recent token. */
+ private int fToken;
+
+ /** The line of fPosition
. */
+ private int fLine;
+
+ /**
+ * The scanner we will use to scan the document. It has to be installed on
+ * the same document as the one we get.
+ */
+ private JavaHeuristicScanner fScanner;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param document
+ * the document to scan
+ * @param scanner
+ * the {@link JavaHeuristicScanner} to be used for scanning the
+ * document. It must be installed on the same
+ * IDocument
.
+ */
+ public JavaIndenter(IDocument document, JavaHeuristicScanner scanner) {
+ Assert.isNotNull(document);
+ Assert.isNotNull(scanner);
+ fDocument = document;
+ fScanner = scanner;
+ }
+
+ /**
+ * Computes the indentation at the reference point of position
.
+ *
+ * @param offset
+ * the offset in the document
+ * @return a String which reflects the indentation at the line in which the
+ * reference position to offset
resides, or
+ * null
if it cannot be determined
+ */
+ public StringBuffer getReferenceIndentation(int offset) {
+ return getReferenceIndentation(offset, false);
+ }
+
+ /**
+ * Computes the indentation at the reference point of position
.
+ *
+ * @param offset
+ * the offset in the document
+ * @param assumeOpeningBrace
+ * true
if an opening brace should be assumed
+ * @return a String which reflects the indentation at the line in which the
+ * reference position to offset
resides, or
+ * null
if it cannot be determined
+ */
+ private StringBuffer getReferenceIndentation(int offset,
+ boolean assumeOpeningBrace) {
+
+ int unit;
+ if (assumeOpeningBrace)
+ unit = findReferencePosition(offset, Symbols.TokenLBRACE);
+ else
+ unit = findReferencePosition(offset, peekChar(offset));
+
+ // if we were unable to find anything, return null
+ if (unit == JavaHeuristicScanner.NOT_FOUND)
+ return null;
+
+ return getLeadingWhitespace(unit);
+
+ }
+
+ /**
+ * Computes the indentation at offset
.
+ *
+ * @param offset
+ * the offset in the document
+ * @return a String which reflects the correct indentation for the line in
+ * which offset resides, or null
if it cannot be
+ * determined
+ */
+ public StringBuffer computeIndentation(int offset) {
+ return computeIndentation(offset, false);
+ }
+
+ /**
+ * Computes the indentation at offset
.
+ *
+ * @param offset
+ * the offset in the document
+ * @param assumeOpeningBrace
+ * true
if an opening brace should be assumed
+ * @return a String which reflects the correct indentation for the line in
+ * which offset resides, or null
if it cannot be
+ * determined
+ */
+ public StringBuffer computeIndentation(int offset,
+ boolean assumeOpeningBrace) {
+
+ StringBuffer indent = getReferenceIndentation(offset,
+ assumeOpeningBrace);
+
+ // handle special alignment
+ if (fAlign != JavaHeuristicScanner.NOT_FOUND) {
+ try {
+ // a special case has been detected.
+ IRegion line = fDocument.getLineInformationOfOffset(fAlign);
+ int lineOffset = line.getOffset();
+ return createIndent(lineOffset, fAlign);
+ } catch (BadLocationException e) {
+ return null;
+ }
+ }
+
+ if (indent == null)
+ return null;
+
+ // add additional indent
+ //indent.append(createIndent(fIndent));
+ indent.insert(0, createIndent(fIndent));
+ if (fIndent < 0)
+ unindent(indent);
+
+ return indent;
+ }
+
+ /**
+ * Returns the indentation of the line at offset
as a
+ * StringBuffer
. If the offset is not valid, the empty
+ * string is returned.
+ *
+ * @param offset
+ * the offset in the document
+ * @return the indentation (leading whitespace) of the line in which
+ * offset
is located
+ */
+ private StringBuffer getLeadingWhitespace(int offset) {
+ StringBuffer indent = new StringBuffer();
+ try {
+ IRegion line = fDocument.getLineInformationOfOffset(offset);
+ int lineOffset = line.getOffset();
+ int nonWS = fScanner.findNonWhitespaceForwardInAnyPartition(
+ lineOffset, lineOffset + line.getLength());
+ indent.append(fDocument.get(lineOffset, nonWS - lineOffset));
+ return indent;
+ } catch (BadLocationException e) {
+ return indent;
+ }
+ }
+
+ /**
+ * Reduces indentation in indent
by one indentation unit.
+ *
+ * @param indent
+ * the indentation to be modified
+ */
+ private void unindent(StringBuffer indent) {
+ CharSequence oneIndent = createIndent();
+ int i = indent.lastIndexOf(oneIndent.toString()); //$NON-NLS-1$
+ if (i != -1) {
+ indent.delete(i, i + oneIndent.length());
+ }
+ }
+
+ /**
+ * Creates an indentation string of the length indent - start + 1,
+ * consisting of the content in fDocument
in the range
+ * [start, indent), with every character replaced by a space except for
+ * tabs, which are kept as such.
+ *
+ * start
and indent
+ */
+ private StringBuffer createIndent(int start, int indent) {
+ final int tabLen = prefTabLength();
+ StringBuffer ret = new StringBuffer();
+ try {
+ int spaces = 0;
+ while (start < indent) {
+
+ char ch = fDocument.getChar(start);
+ if (ch == '\t') {
+ ret.append('\t');
+ spaces = 0;
+ } else if (tabLen == -1) {
+ ret.append(' ');
+ } else {
+ spaces++;
+ if (spaces == tabLen) {
+ ret.append('\t');
+ spaces = 0;
+ }
+ }
+
+ start++;
+ }
+ // remainder
+ if (spaces == tabLen)
+ ret.append('\t');
+ else
+ while (spaces-- > 0)
+ ret.append(' ');
+
+ } catch (BadLocationException e) {
+ }
+
+ return ret;
+ }
+
+ /**
+ * Creates a string that represents the given number of indents (can be
+ * spaces or tabs..)
+ *
+ * @param indent
+ * the requested indentation level.
+ *
+ * @return the indentation specified by indent
+ */
+ public StringBuffer createIndent(int indent) {
+ StringBuffer oneIndent = createIndent();
+
+ StringBuffer ret = new StringBuffer();
+ while (indent-- > 0)
+ ret.append(oneIndent);
+
+ return ret;
+ }
+
+ /**
+ * Creates a string that represents one indent (can be spaces or tabs..)
+ *
+ * @return one indentation
+ */
+ private StringBuffer createIndent() {
+ // get a sensible default when running without the infrastructure for
+ // testing
+ StringBuffer oneIndent = new StringBuffer();
+ // JavaCore plugin= JavaCore.getJavaCore();
+ WebUI plugin = WebUI.getDefault();
+ if (plugin == null) {
+ oneIndent.append('\t');
+ } else {
+ if (JavaCore.SPACE
+ .equals(JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR))) {
+ int tabLen = Integer
+ .parseInt(JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE));
+ for (int i = 0; i < tabLen; i++)
+ oneIndent.append(' ');
+ } else if (JavaCore.TAB
+ .equals(JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR)))
+ oneIndent.append('\t');
+ else
+ oneIndent.append('\t'); // default
+ }
+ return oneIndent;
+ }
+
+ /**
+ * Returns the reference position regarding to indentation for
+ * offset
, or NOT_FOUND
. This method calls
+ * {@link #findReferencePosition(int, int) findReferencePosition(offset, nextChar)}
+ * where nextChar
is the next character after
+ * offset
.
+ *
+ * @param offset
+ * the offset for which the reference is computed
+ * @return the reference statement relative to which offset
+ * should be indented, or {@link JavaHeuristicScanner#NOT_FOUND}
+ */
+ public int findReferencePosition(int offset) {
+ return findReferencePosition(offset, peekChar(offset));
+ }
+
+ /**
+ * Peeks the next char in the document that comes after offset
+ * on the same line as offset
.
+ *
+ * @param offset
+ * the offset into document
+ * @return the token symbol of the next element, or TokenEOF if there is
+ * none
+ */
+ private int peekChar(int offset) {
+ if (offset < fDocument.getLength()) {
+ try {
+ IRegion line = fDocument.getLineInformationOfOffset(offset);
+ int lineOffset = line.getOffset();
+ int next = fScanner.nextToken(offset, lineOffset
+ + line.getLength());
+ return next;
+ } catch (BadLocationException e) {
+ }
+ }
+ return Symbols.TokenEOF;
+ }
+
+ /**
+ * Returns the reference position regarding to indentation for
+ * position
, or NOT_FOUND
.
+ *
+ * peekNextChar
is true
, the next token
+ * after offset
is read and taken into account when computing
+ * the indentation. Currently, if the next token is the first token on the
+ * line (i.e. only preceded by whitespace), the following tokens are
+ * specially handled:
+ *
+ *
+ *
+ * @param offset
+ * the offset for which the reference is computed
+ * @param nextToken
+ * the next token to assume in the document
+ * @return the reference statement relative to which switch
labels are indented relative to the switch
+ * blockelse
keyword is aligned with its if
,
+ * anything else is aligned normally (i.e. with the base of any introducing
+ * statements).offset
,
+ * the indentation is the same as for an else
keywordoffset
+ * should be indented, or {@link JavaHeuristicScanner#NOT_FOUND}
+ */
+ public int findReferencePosition(int offset, int nextToken) {
+ boolean danglingElse = false;
+ boolean unindent = false;
+ boolean indent = false;
+ boolean matchBrace = false;
+ boolean matchParen = false;
+ boolean matchCase = false;
+
+ // account for unindenation characters already typed in, but after
+ // position
+ // if they are on a line by themselves, the indentation gets adjusted
+ // accordingly
+ //
+ // also account for a dangling else
+ if (offset < fDocument.getLength()) {
+ try {
+ IRegion line = fDocument.getLineInformationOfOffset(offset);
+ int lineOffset = line.getOffset();
+ int prevPos = Math.max(offset - 1, 0);
+ boolean isFirstTokenOnLine = fDocument.get(lineOffset,
+ prevPos + 1 - lineOffset).trim().length() == 0;
+ int prevToken = fScanner.previousToken(prevPos,
+ JavaHeuristicScanner.UNBOUND);
+ if (prevToken == Symbols.TokenEOF && nextToken == Symbols.TokenEOF) {
+ ITypedRegion partition = TextUtilities.getPartition(fDocument, IPHPPartitions.PHP_PARTITIONING, offset, true);
+ if (partition.getType().equals(IPHPPartitions.PHP_SINGLELINE_COMMENT)) {
+ fAlign = fScanner.getPosition();
+ } else {
+ fAlign = JavaHeuristicScanner.NOT_FOUND;
+ }
+ return JavaHeuristicScanner.NOT_FOUND;
+ }
+ boolean bracelessBlockStart = fScanner.isBracelessBlockStart(
+ prevPos, JavaHeuristicScanner.UNBOUND);
+
+ switch (nextToken) {
+ case Symbols.TokenEOF:
+ case Symbols.TokenELSE:
+ danglingElse = true;
+ break;
+ case Symbols.TokenCASE:
+ case Symbols.TokenDEFAULT:
+ if (isFirstTokenOnLine)
+ matchCase = true;
+ break;
+ case Symbols.TokenLBRACE: // for opening-brace-on-new-line
+ // style
+ // if (bracelessBlockStart && !prefIndentBracesForBlocks())
+ // unindent= true;
+ // else if ((prevToken == Symbols.TokenCOLON || prevToken ==
+ // Symbols.TokenEQUAL || prevToken == Symbols.TokenRBRACKET) &&
+ // !prefIndentBracesForArrays())
+ // unindent= true;
+ // else if (!bracelessBlockStart &&
+ // prefIndentBracesForMethods())
+ // indent= true;
+ // break;
+ if (bracelessBlockStart)
+ unindent = true;
+ else if ((prevToken == Symbols.TokenCOLON
+ || prevToken == Symbols.TokenEQUAL || prevToken == Symbols.TokenRBRACKET))
+ unindent = true;
+ else if (!bracelessBlockStart)
+ indent = true;
+ break;
+ case Symbols.TokenRBRACE: // closing braces get unindented
+ if (isFirstTokenOnLine)
+ matchBrace = true;
+ break;
+ case Symbols.TokenRPAREN:
+ if (isFirstTokenOnLine)
+ matchParen = true;
+ break;
+ }
+ } catch (BadLocationException e) {
+ }
+ } else {
+ // assume an else could come if we are at the end of file
+ danglingElse = true;
+ }
+
+ int ref = findReferencePosition(offset, danglingElse, matchBrace,
+ matchParen, matchCase);
+ if (unindent)
+ fIndent--;
+ if (indent)
+ fIndent++;
+ return ref;
+ }
+
+ /**
+ * Returns the reference position regarding to indentation for
+ * position
, or NOT_FOUND
.fIndent
+ * will contain the relative indentation (in indentation units, not
+ * characters) after the call. If there is a special alignment (e.g. for a
+ * method declaration where parameters should be aligned),
+ * fAlign
will contain the absolute position of the alignment
+ * reference in fDocument
, otherwise fAlign
+ * is set to JavaHeuristicScanner.NOT_FOUND
.
+ *
+ * @param offset
+ * the offset for which the reference is computed
+ * @param danglingElse
+ * whether a dangling else should be assumed at
+ * position
+ * @param matchBrace
+ * whether the position of the matching brace should be returned
+ * instead of doing code analysis
+ * @param matchParen
+ * whether the position of the matching parenthesis should be
+ * returned instead of doing code analysis
+ * @param matchCase
+ * whether the position of a switch statement reference should be
+ * returned (either an earlier case statement or the switch block
+ * brace)
+ * @return the reference statement relative to which position
+ * should be indented, or {@link JavaHeuristicScanner#NOT_FOUND}
+ */
+ public int findReferencePosition(int offset, boolean danglingElse,
+ boolean matchBrace, boolean matchParen, boolean matchCase) {
+ fIndent = 0; // the indentation modification
+ fAlign = JavaHeuristicScanner.NOT_FOUND;
+ fPosition = offset;
+
+ // forward cases
+ // an unindentation happens sometimes if the next token is special,
+ // namely on braces, parens and case labels
+ // align braces, but handle the case where we align with the method
+ // declaration start instead of
+ // the opening brace.
+ if (matchBrace) {
+ if (skipScope(Symbols.TokenLBRACE, Symbols.TokenRBRACE)) {
+ try {
+ // align with the opening brace that is on a line by its own
+ int lineOffset = fDocument.getLineOffset(fLine);
+ if (lineOffset <= fPosition
+ && fDocument
+ .get(lineOffset, fPosition - lineOffset)
+ .trim().length() == 0)
+ return fPosition;
+ } catch (BadLocationException e) {
+ // concurrent modification - walk default path
+ }
+ // if the opening brace is not on the start of the line, skip to
+ // the start
+ int pos = skipToStatementStart(true, true);
+ fIndent = 0; // indent is aligned with reference position
+ return pos;
+ } else {
+ // if we can't find the matching brace, the heuristic is to
+ // unindent
+ // by one against the normal position
+ int pos = findReferencePosition(offset, danglingElse, false,
+ matchParen, matchCase);
+ fIndent--;
+ return pos;
+ }
+ }
+
+ // align parenthesis'
+ if (matchParen) {
+ if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN))
+ return fPosition;
+ else {
+ // if we can't find the matching paren, the heuristic is to
+ // unindent
+ // by one against the normal position
+ int pos = findReferencePosition(offset, danglingElse,
+ matchBrace, false, matchCase);
+ fIndent--;
+ return pos;
+ }
+ }
+
+ // the only reliable way to get case labels aligned (due to many
+ // different styles of using braces in a block)
+ // is to go for another case statement, or the scope opening brace
+ if (matchCase) {
+ return matchCaseAlignment();
+ }
+
+ nextToken();
+ switch (fToken) {
+ case Symbols.TokenRBRACE:
+ // skip the block and fall through
+ // if we can't complete the scope, reset the scan position
+ int pos = fPosition;
+ if (!skipScope())
+ fPosition = pos;
+ case Symbols.TokenSEMICOLON:
+ // this is the 90% case: after a statement block
+ // the end of the previous statement / block previous.end
+ // search to the end of the statement / block before the previous;
+ // the token just after that is previous.start
+ return skipToStatementStart(danglingElse, false);
+
+ // scope introduction: special treat who special is
+ case Symbols.TokenLPAREN:
+ case Symbols.TokenLBRACE:
+ case Symbols.TokenLBRACKET:
+ return handleScopeIntroduction(offset + 1);
+
+ case Symbols.TokenEOF:
+ // trap when hitting start of document
+ return 0;
+
+ case Symbols.TokenEQUAL:
+ // indent assignments
+ fIndent = prefAssignmentIndent();
+ return fPosition;
+
+ case Symbols.TokenCOLON:
+ // TODO handle ternary deep indentation
+ fIndent = prefCaseBlockIndent();
+ return fPosition;
+
+ case Symbols.TokenQUESTIONMARK:
+ if (prefTernaryDeepAlign()) {
+ setFirstElementAlignment(fPosition, offset + 1);
+ return fPosition;
+ } else {
+ fIndent = prefTernaryIndent();
+ return fPosition;
+ }
+
+ // indentation for blockless introducers:
+ case Symbols.TokenDO:
+ case Symbols.TokenWHILE:
+ case Symbols.TokenELSE:
+ fIndent = prefSimpleIndent();
+ return fPosition;
+ case Symbols.TokenRPAREN:
+ int line = fLine;
+ if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN)) {
+ int scope = fPosition;
+ nextToken();
+ if (fToken == Symbols.TokenIF || fToken == Symbols.TokenWHILE
+ || fToken == Symbols.TokenFOR) {
+ fIndent = prefSimpleIndent();
+ return fPosition;
+ }
+ fPosition = scope;
+ if (looksLikeMethodDecl()) {
+ return skipToStatementStart(danglingElse, false);
+ }
+ }
+ // restore
+ fPosition = offset;
+ fLine = line;
+ // else: fall through to default
+
+ case Symbols.TokenCOMMA:
+ // inside a list of some type
+ // easy if there is already a list item before with its own
+ // indentation - we just align
+ // if not: take the start of the list ( LPAREN, LBRACE, LBRACKET )
+ // and either align or
+ // indent by list-indent
+ default:
+ // inside whatever we don't know about: similar to the list case:
+ // if we are inside a continued expression, then either align with a
+ // previous line that has indentation
+ // or indent from the expression start line (either a scope
+ // introducer or the start of the expr).
+ return skipToPreviousListItemOrListStart();
+
+ }
+ }
+
+ /**
+ * Skips to the start of a statement that ends at the current position.
+ *
+ * @param danglingElse
+ * whether to indent aligned with the last if
+ * @param isInBlock
+ * whether the current position is inside a block, which limits
+ * the search scope to the next scope introducer
+ * @return the reference offset of the start of the statement
+ */
+ private int skipToStatementStart(boolean danglingElse, boolean isInBlock) {
+ while (true) {
+ nextToken();
+
+ if (isInBlock) {
+ switch (fToken) {
+ // exit on all block introducers
+ case Symbols.TokenIF:
+ case Symbols.TokenELSE:
+ case Symbols.TokenSYNCHRONIZED:
+ case Symbols.TokenCOLON:
+ case Symbols.TokenSTATIC:
+ case Symbols.TokenCATCH:
+ case Symbols.TokenDO:
+ case Symbols.TokenWHILE:
+ case Symbols.TokenFINALLY:
+ case Symbols.TokenFOR:
+ case Symbols.TokenTRY:
+ return fPosition;
+
+ case Symbols.TokenSWITCH:
+ fIndent = prefCaseIndent();
+ return fPosition;
+ }
+ }
+
+ switch (fToken) {
+ // scope introduction through: LPAREN, LBRACE, LBRACKET
+ // search stop on SEMICOLON, RBRACE, COLON, EOF
+ // -> the next token is the start of the statement (i.e. previousPos
+ // when backward scanning)
+ case Symbols.TokenLPAREN:
+ case Symbols.TokenLBRACE:
+ case Symbols.TokenLBRACKET:
+ case Symbols.TokenSEMICOLON:
+ case Symbols.TokenEOF:
+ return fPreviousPos;
+
+ case Symbols.TokenCOLON:
+ int pos = fPreviousPos;
+ if (!isConditional())
+ return pos;
+ break;
+
+ case Symbols.TokenRBRACE:
+ // RBRACE is a little tricky: it can be the end of an array
+ // definition, but
+ // usually it is the end of a previous block
+ pos = fPreviousPos; // store state
+ if (skipScope() && looksLikeArrayInitializerIntro())
+ continue; // it's an array
+ else
+ return pos; // it's not - do as with all the above
+
+ // scopes: skip them
+ case Symbols.TokenRPAREN:
+ case Symbols.TokenRBRACKET:
+ pos = fPreviousPos;
+ if (skipScope())
+ break;
+ else
+ return pos;
+
+ // IF / ELSE: align the position after the conditional block
+ // with the if
+ // so we are ready for an else, except if danglingElse is false
+ // in order for this to work, we must skip an else to its if
+ case Symbols.TokenIF:
+ if (danglingElse)
+ return fPosition;
+ else
+ break;
+ case Symbols.TokenELSE:
+ // skip behind the next if, as we have that one covered
+ pos = fPosition;
+ if (skipNextIF())
+ break;
+ else
+ return pos;
+
+ case Symbols.TokenDO:
+ // align the WHILE position with its do
+ return fPosition;
+
+ case Symbols.TokenWHILE:
+ // this one is tricky: while can be the start of a while loop
+ // or the end of a do - while
+ pos = fPosition;
+ if (hasMatchingDo()) {
+ // continue searching from the DO on
+ break;
+ } else {
+ // continue searching from the WHILE on
+ fPosition = pos;
+ break;
+ }
+ default:
+ // keep searching
+
+ }
+
+ }
+ }
+
+ /**
+ * Returns true if the colon at the current position is part of a
+ * conditional (ternary) expression, false otherwise.
+ *
+ * @return true if the colon at the current position is part of a
+ * conditional
+ */
+ private boolean isConditional() {
+ while (true) {
+ nextToken();
+ switch (fToken) {
+
+ // search for case, otherwise return true
+ case Symbols.TokenIDENT:
+ continue;
+ case Symbols.TokenCASE:
+ return false;
+
+ default:
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns as a reference any previous switch
labels (case
+ * or default
) or the offset of the brace that scopes the
+ * switch statement. Sets fIndent
to
+ * prefCaseIndent
upon a match.
+ *
+ * @return the reference offset for a switch
label
+ */
+ private int matchCaseAlignment() {
+ while (true) {
+ nextToken();
+ switch (fToken) {
+ // invalid cases: another case label or an LBRACE must come before a
+ // case
+ // -> bail out with the current position
+ case Symbols.TokenLPAREN:
+ case Symbols.TokenLBRACKET:
+ case Symbols.TokenEOF:
+ return fPosition;
+ case Symbols.TokenLBRACE:
+ // opening brace of switch statement
+ fIndent = 1; //prefCaseIndent() is for Java
+ return fPosition;
+ case Symbols.TokenCASE:
+ case Symbols.TokenDEFAULT:
+ // align with previous label
+ fIndent = 0;
+ return fPosition;
+ // scopes: skip them
+ case Symbols.TokenRPAREN:
+ case Symbols.TokenRBRACKET:
+ case Symbols.TokenRBRACE:
+ skipScope();
+ break;
+ default:
+ // keep searching
+ continue;
+ }
+ }
+ }
+
+ /**
+ * Returns the reference position for a list element. The algorithm tries to
+ * match any previous indentation on the same list. If there is none, the
+ * reference position returned is determined depending on the type of list:
+ * The indentation will either match the list scope introducer (e.g. for
+ * method declarations), so called deep indents, or simply increase the
+ * indentation by a number of standard indents. See also
+ * {@link #handleScopeIntroduction(int)}.
+ *
+ * @return the reference position for a list item: either a previous list
+ * item that has its own indentation, or the list introduction
+ * start.
+ */
+ private int skipToPreviousListItemOrListStart() {
+ int startLine = fLine;
+ int startPosition = fPosition;
+ while (true) {
+ nextToken();
+
+ // if any line item comes with its own indentation, adapt to it
+ if (fLine < startLine) {
+ try {
+ int lineOffset = fDocument.getLineOffset(startLine);
+ int bound = Math.min(fDocument.getLength(),
+ startPosition + 1);
+ fAlign = fScanner.findNonWhitespaceForwardInAnyPartition(
+ lineOffset, bound);
+ } catch (BadLocationException e) {
+ // ignore and return just the position
+ }
+ return startPosition;
+ }
+
+ switch (fToken) {
+ // scopes: skip them
+ case Symbols.TokenRPAREN:
+ case Symbols.TokenRBRACKET:
+ case Symbols.TokenRBRACE:
+ skipScope();
+ break;
+
+ // scope introduction: special treat who special is
+ case Symbols.TokenLPAREN:
+ case Symbols.TokenLBRACE:
+ case Symbols.TokenLBRACKET:
+ return handleScopeIntroduction(startPosition + 1);
+
+ case Symbols.TokenSEMICOLON:
+ return fPosition;
+ case Symbols.TokenQUESTIONMARK:
+ if (prefTernaryDeepAlign()) {
+ setFirstElementAlignment(fPosition - 1, fPosition + 1);
+ } else {
+ fIndent = prefTernaryIndent();
+ }
+ return fPosition;
+ case Symbols.TokenEOF:
+ return 0;
+
+ case Symbols.TokenEQUAL:
+ // indent assignments
+ fIndent= prefAssignmentIndent();
+ return fPosition;
+ }
+ }
+ }
+
+ /**
+ * Skips a scope and positions the cursor (fPosition
) on
+ * the token that opens the scope. Returns true
if a matching
+ * peer could be found, false
otherwise. The current token
+ * when calling must be one out of Symbols.TokenRPAREN
,
+ * Symbols.TokenRBRACE
, and
+ * Symbols.TokenRBRACKET
.
+ *
+ * @return true
if a matching peer was found,
+ * false
otherwise
+ */
+ private boolean skipScope() {
+ switch (fToken) {
+ case Symbols.TokenRPAREN:
+ return skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN);
+ case Symbols.TokenRBRACKET:
+ return skipScope(Symbols.TokenLBRACKET, Symbols.TokenRBRACKET);
+ case Symbols.TokenRBRACE:
+ return skipScope(Symbols.TokenLBRACE, Symbols.TokenRBRACE);
+ default:
+ Assert.isTrue(false);
+ return false;
+ }
+ }
+
+ /**
+ * Handles the introduction of a new scope. The current token must be one
+ * out of Symbols.TokenLPAREN
,
+ * Symbols.TokenLBRACE
, and
+ * Symbols.TokenLBRACKET
. Returns as the reference position
+ * either the token introducing the scope or - if available - the first java
+ * token after that.
+ *
+ * fAlign
will
+ * be set to the reference position) or fIndent
will be set
+ * to the number of indentation units.
+ * fAlign
) to either the
+ * offset right after scopeIntroducerOffset
or - if available -
+ * the first Java token after scopeIntroducerOffset
, but
+ * before bound
.
+ *
+ * @param scopeIntroducerOffset
+ * the offset of the scope introducer
+ * @param bound
+ * the bound for the search for another element
+ * @return the reference position
+ */
+ private int setFirstElementAlignment(int scopeIntroducerOffset, int bound) {
+ int firstPossible = scopeIntroducerOffset + 1; // align with the first
+ // position after the
+ // scope intro
+ fAlign = fScanner.findNonWhitespaceForwardInAnyPartition(firstPossible,
+ bound);
+ if (fAlign == JavaHeuristicScanner.NOT_FOUND)
+ fAlign = firstPossible;
+ return fAlign;
+ }
+
+ /**
+ * Returns true
if the next token received after calling
+ * nextToken
is either an equal sign or an array designator
+ * ('[]').
+ *
+ * @return true
if the next elements look like the start of
+ * an array definition
+ */
+ private boolean looksLikeArrayInitializerIntro() {
+ nextToken();
+ if (fToken == Symbols.TokenEQUAL || skipBrackets()) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Skips over the next if
keyword. The current token when
+ * calling this method must be an else
keyword. Returns
+ * true
if a matching if
could be found,
+ * false
otherwise. The cursor (fPosition
)
+ * is set to the offset of the if
token.
+ *
+ * @return true
if a matching if
token was
+ * found, false
otherwise
+ */
+ private boolean skipNextIF() {
+ Assert.isTrue(fToken == Symbols.TokenELSE);
+
+ while (true) {
+ nextToken();
+ switch (fToken) {
+ // scopes: skip them
+ case Symbols.TokenRPAREN:
+ case Symbols.TokenRBRACKET:
+ case Symbols.TokenRBRACE:
+ skipScope();
+ break;
+
+ case Symbols.TokenIF:
+ // found it, return
+ return true;
+ case Symbols.TokenELSE:
+ // recursively skip else-if blocks
+ skipNextIF();
+ break;
+
+ // shortcut scope starts
+ case Symbols.TokenLPAREN:
+ case Symbols.TokenLBRACE:
+ case Symbols.TokenLBRACKET:
+ case Symbols.TokenEOF:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * while(condition); is ambiguous when parsed backwardly, as it is a valid
+ * statement by its own, so we have to check whether there is a matching do.
+ * A do
can either be separated from the while by a block, or
+ * by a single statement, which limits our search distance.
+ *
+ * @return true
if the while
currently in
+ * fToken
has a matching do
.
+ */
+ private boolean hasMatchingDo() {
+ Assert.isTrue(fToken == Symbols.TokenWHILE);
+ nextToken();
+ switch (fToken) {
+ case Symbols.TokenRBRACE:
+ skipScope(); // and fall thru
+ case Symbols.TokenSEMICOLON:
+ skipToStatementStart(false, false);
+ return fToken == Symbols.TokenDO;
+ }
+ return false;
+ }
+
+ /**
+ * Skips brackets if the current token is a RBRACKET. There can be nothing
+ * but whitespace in between, this is only to be used for []
+ * elements.
+ *
+ * @return true
if a []
could be scanned, the
+ * current token is left at the LBRACKET.
+ */
+ private boolean skipBrackets() {
+ if (fToken == Symbols.TokenRBRACKET) {
+ nextToken();
+ if (fToken == Symbols.TokenLBRACKET) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Reads the next token in backward direction from the heuristic scanner and
+ * sets the fields fToken, fPreviousPosition
and
+ * fPosition
accordingly.
+ */
+ private void nextToken() {
+ nextToken(fPosition);
+ }
+
+ /**
+ * Reads the next token in backward direction of start
from
+ * the heuristic scanner and sets the fields
+ * fToken, fPreviousPosition
and fPosition
+ * accordingly.
+ */
+ private void nextToken(int start) {
+ fToken = fScanner
+ .previousToken(start - 1, JavaHeuristicScanner.UNBOUND);
+ fPreviousPos = start;
+ fPosition = fScanner.getPosition() + 1;
+ try {
+ fLine = fDocument.getLineOfOffset(fPosition);
+ } catch (BadLocationException e) {
+ fLine = -1;
+ }
+ }
+
+ /**
+ * Returns true
if the current tokens look like a method
+ * declaration header (i.e. only the return type and method name). The
+ * heuristic calls nextToken
and expects an identifier
+ * (method name) and a type declaration (an identifier with optional
+ * brackets) which also covers the visibility modifier of constructors; it
+ * does not recognize package visible constructors.
+ *
+ * @return true
if the current position looks like a method
+ * declaration header.
+ */
+ private boolean looksLikeMethodDecl() {
+ /*
+ * TODO This heuristic does not recognize package private constructors
+ * since those do have neither type nor visibility keywords. One option
+ * would be to go over the parameter list, but that might be empty as
+ * well - hard to do without an AST...
+ */
+
+ nextToken();
+ if (fToken == Symbols.TokenIDENT) { // method name
+ do
+ nextToken();
+ while (skipBrackets()); // optional brackets for array valued return
+ // types
+ return fToken == Symbols.TokenIDENT; // type name
+
+ }
+ return false;
+ }
+
+ /**
+ * Returns true
if the current tokens look like a method call
+ * header (i.e. an identifier as opposed to a keyword taking parenthesized
+ * parameters such as if
).
+ * nextToken
and expects an identifier
+ * (method name).
+ *
+ * @return true
if the current position looks like a method
+ * call header.
+ */
+ private boolean looksLikeMethodCall() {
+ nextToken();
+ return fToken == Symbols.TokenIDENT; // method name
+ }
+
+ /**
+ * Scans tokens for the matching opening peer. The internal cursor (fPosition
)
+ * is set to the offset of the opening peer if found.
+ *
+ * @return true
if a matching token was found,
+ * false
otherwise
+ */
+ private boolean skipScope(int openToken, int closeToken) {
+
+ int depth = 1;
+
+ while (true) {
+ nextToken();
+
+ if (fToken == closeToken) {
+ depth++;
+ } else if (fToken == openToken) {
+ depth--;
+ if (depth == 0)
+ return true;
+ } else if (fToken == Symbols.TokenEOF) {
+ return false;
+ }
+ }
+ }
+
+ // TODO adjust once there are per-project settings
+
+ private int prefTabLength() {
+ int tabLen;
+ // JavaCore core= JavaCore.getJavaCore();
+ WebUI plugin = WebUI.getDefault();
+ // if (core != null && plugin != null)
+ if (plugin != null)
+ if (JavaCore.SPACE
+ .equals(JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR)))
+ // if the formatter uses chars to mark indentation, then don't
+ // substitute any chars
+ tabLen = -1; // results in no tabs being substituted for
+ // space runs
+ else
+ // if the formatter uses tabs to mark indentations, use the
+ // visual setting from the editor
+ // to get nicely aligned indentations
+ tabLen = plugin
+ .getPreferenceStore()
+ .getInt(
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
+ else
+ tabLen = 4; // sensible default for testing
+
+ return tabLen;
+ }
+
+ private boolean prefArrayDimensionsDeepIndent() {
+ return true; // sensible default
+ }
+
+ private int prefArrayIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER);
+ try {
+ if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
+ return 1;
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+
+ return prefContinuationIndent(); // default
+ }
+
+ private boolean prefArrayDeepIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER);
+ try {
+ return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+
+ return true;
+ }
+
+ private boolean prefTernaryDeepAlign() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
+ try {
+ return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+ return false;
+ }
+
+ private int prefTernaryIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
+ try {
+ if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
+ return 1;
+ else
+ return prefContinuationIndent();
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+
+ return prefContinuationIndent();
+ }
+
+ private int prefCaseIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ if (DefaultCodeFormatterConstants.TRUE
+ .equals(JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH)))
+ return prefBlockIndent();
+ else
+ return 0;
+ }
+
+ return 0; // sun standard
+ }
+
+ private int prefAssignmentIndent() {
+ return prefBlockIndent();
+ }
+
+ private int prefCaseBlockIndent() {
+ if (true)
+ return prefBlockIndent();
+
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ if (DefaultCodeFormatterConstants.TRUE
+ .equals(JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES)))
+ return prefBlockIndent();
+ else
+ return 0;
+ }
+ return prefBlockIndent(); // sun standard
+ }
+
+ private int prefSimpleIndent() {
+ return prefBlockIndent();
+ }
+
+ private int prefBracketIndent() {
+ return prefBlockIndent();
+ }
+
+ private boolean prefMethodDeclDeepIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION);
+ try {
+ return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+
+ return true;
+ }
+
+ private int prefMethodDeclIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION);
+ try {
+ if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
+ return 1;
+ else
+ return prefContinuationIndent();
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+ return 1;
+ }
+
+ private boolean prefMethodCallDeepIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION);
+ try {
+ return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+ return false; // sensible default
+ }
+
+ private int prefMethodCallIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION);
+ try {
+ if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
+ return 1;
+ else
+ return prefContinuationIndent();
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+
+ return 1; // sensible default
+ }
+
+ private boolean prefParenthesisDeepIndent() {
+
+ if (true) // don't do parenthesis deep indentation
+ return false;
+
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION);
+ try {
+ return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
+ } catch (IllegalArgumentException e) {
+ // ignore and return default
+ }
+ }
+
+ return false; // sensible default
+ }
+
+ private int prefParenthesisIndent() {
+ return prefContinuationIndent();
+ }
+
+ private int prefBlockIndent() {
+ return 1; // sensible default
+ }
+
+ private boolean prefIndentBracesForBlocks() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK);
+ return option
+ .equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED);
+ }
+
+ return false; // sensible default
+ }
+
+ private boolean prefIndentBracesForArrays() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER);
+ return option
+ .equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED);
+ }
+
+ return false; // sensible default
+ }
+
+ private boolean prefIndentBracesForMethods() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION);
+ return option
+ .equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED);
+ }
+
+ return false; // sensible default
+ }
+
+ private int prefContinuationIndent() {
+ Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+ String option = JavaCore
+ .getOption(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION);
+ try {
+ return Integer.parseInt(option);
+ } catch (NumberFormatException e) {
+ // ignore and return default
+ }
+ }
+
+ return 2; // sensible default
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java
new file mode 100644
index 0000000..badd6d4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java
@@ -0,0 +1,640 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.actions.OpenActionUtil;
+import net.sourceforge.phpdt.internal.ui.util.StringMatcher;
+import net.sourceforge.phpdt.internal.ui.viewsupport.AppearanceAwareLabelProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.DecoratingJavaLabelProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels;
+import net.sourceforge.phpdt.ui.JavaElementSorter;
+import net.sourceforge.phpdt.ui.StandardJavaElementContentProvider;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlExtension;
+import org.eclipse.jface.text.IInformationControlExtension2;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+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.Color;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+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.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+
+/**
+ * @author dmegert
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates. To enable and disable the creation of type
+ * comments go to Window>Preferences>Java>Code Generation.
+ */
+public class JavaOutlineInformationControl implements IInformationControl,
+ IInformationControlExtension, IInformationControlExtension2 {
+
+ /**
+ * The NamePatternFilter selects the elements which match the given string
+ * patterns.
+ * true
iff the Java Model has changed
+ * @since 3.0
+ */
+ private synchronized boolean hasJavaModelChanged() {
+ return fHasJavaModelChanged;
+ }
+
+ /**
+ * Sets whether the Java Model has changed or not.
+ *
+ * @param state
+ * true
iff the java model has changed
+ * @since 3.0
+ */
+ private synchronized void setJavaModelChanged(boolean state) {
+ fHasJavaModelChanged = state;
+ }
+}
+// /**
+// * A reconciler that is also activated on editor activation.
+// */
+// public class JavaReconciler extends MonoReconciler {
+//
+// /**
+// * Internal part listener for activating the reconciler.
+// */
+// class PartListener implements IPartListener {
+//
+// /*
+// * @see IPartListener#partActivated(IWorkbenchPart)
+// */
+// public void partActivated(IWorkbenchPart part) {
+// if (part == fTextEditor)
+// JavaReconciler.this.forceReconciling();
+// }
+//
+// /*
+// * @see IPartListener#partBroughtToTop(IWorkbenchPart)
+// */
+// public void partBroughtToTop(IWorkbenchPart part) {
+// }
+//
+// /*
+// * @see IPartListener#partClosed(IWorkbenchPart)
+// */
+// public void partClosed(IWorkbenchPart part) {
+// }
+//
+// /*
+// * @see IPartListener#partDeactivated(IWorkbenchPart)
+// */
+// public void partDeactivated(IWorkbenchPart part) {
+// }
+//
+// /*
+// * @see IPartListener#partOpened(IWorkbenchPart)
+// */
+// public void partOpened(IWorkbenchPart part) {
+// }
+// };
+//
+//
+// /** The reconciler's editor */
+// private ITextEditor fTextEditor;
+// /** The part listener */
+// private IPartListener fPartListener;
+//
+//
+// /**
+// * Creates a new reconciler.
+// */
+// public JavaReconciler(ITextEditor editor, IReconcilingStrategy strategy,
+// boolean isIncremental) {
+// super(strategy, isIncremental);
+// fTextEditor= editor;
+// }
+//
+// /*
+// * @see IReconciler#install(ITextViewer)
+// */
+// public void install(ITextViewer textViewer) {
+// super.install(textViewer);
+//
+// fPartListener= new PartListener();
+// IWorkbenchPartSite site= fTextEditor.getSite();
+// IWorkbenchWindow window= site.getWorkbenchWindow();
+// window.getPartService().addPartListener(fPartListener);
+// }
+//
+// /*
+// * @see IReconciler#uninstall()
+// */
+// public void uninstall() {
+//
+// IWorkbenchPartSite site= fTextEditor.getSite();
+// IWorkbenchWindow window= site.getWorkbenchWindow();
+// window.getPartService().removePartListener(fPartListener);
+// fPartListener= null;
+//
+// super.uninstall();
+// }
+//
+// /*
+// * @see AbstractReconciler#forceReconciling()
+// */
+// protected void forceReconciling() {
+// super.forceReconciling();
+// IReconcilingStrategy strategy=
+// getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
+// if (strategy instanceof JavaReconcilingStrategy) {
+// JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
+// java.notifyParticipants(false);
+// }
+// }
+//
+// /*
+// * @see AbstractReconciler#reconcilerReset()
+// */
+// protected void reconcilerReset() {
+// super.reconcilerReset();
+// IReconcilingStrategy strategy=
+// getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
+// if (strategy instanceof JavaReconcilingStrategy) {
+// JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
+// java.notifyParticipants(true);
+// }
+// }
+// }
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaWordFinder.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaWordFinder.java
new file mode 100644
index 0000000..37944fb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaWordFinder.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+
+public class JavaWordFinder {
+
+ public static IRegion findWord(IDocument document, int offset) {
+
+ int start = -1;
+ int end = -1;
+
+ try {
+
+ int pos = offset;
+ char c = ' ';
+
+ while (pos >= 0) {
+ c = document.getChar(pos);
+ if (c == '$') {
+ --pos;
+ break;
+ }
+ if (!Scanner.isPHPIdentifierPart(c))
+ break;
+
+ --pos;
+ }
+
+ start = pos;
+
+ pos = offset;
+ int length = document.getLength();
+
+ while (pos < length) {
+ c = document.getChar(pos);
+ if (!Scanner.isPHPIdentifierPart(c))
+ break;
+ ++pos;
+ }
+
+ end = pos;
+
+ } catch (BadLocationException x) {
+ }
+
+ if (start > -1 && end > -1) {
+ if (start == offset && end == offset)
+ return new Region(offset, 0);
+ else if (start == offset)
+ return new Region(start, end - start);
+ else
+ return new Region(start + 1, end - start - 1);
+ }
+
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaWordIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaWordIterator.java
new file mode 100644
index 0000000..1c55ba9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaWordIterator.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+
+import org.eclipse.jface.text.Assert;
+
+/**
+ * Breaks java text into word starts, also stops at line start and end. No
+ * direction dependency.
+ *
+ * @since 3.0
+ */
+public class JavaWordIterator extends BreakIterator {
+
+ /**
+ * The underlying java break iterator. It returns all breaks, including
+ * before and after every whitespace.
+ */
+ private JavaBreakIterator fIterator;
+
+ /** The current index for the stateful operations. */
+ private int fIndex;
+
+ /**
+ * Creates a new word iterator.
+ */
+ public JavaWordIterator() {
+ fIterator = new JavaBreakIterator();
+ first();
+ }
+
+ /*
+ * @see java.text.BreakIterator#first()
+ */
+ public int first() {
+ fIndex = fIterator.first();
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#last()
+ */
+ public int last() {
+ fIndex = fIterator.last();
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#next(int)
+ */
+ public int next(int n) {
+ int next = 0;
+ while (--n > 0 && next != DONE) {
+ next = next();
+ }
+ return next;
+ }
+
+ /*
+ * @see java.text.BreakIterator#next()
+ */
+ public int next() {
+ fIndex = following(fIndex);
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#previous()
+ */
+ public int previous() {
+ fIndex = preceding(fIndex);
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#preceding(int)
+ */
+ public int preceding(int offset) {
+ int first = fIterator.preceding(offset);
+ if (isWhitespace(first, offset)) {
+ int second = fIterator.preceding(first);
+ if (second != DONE && !isDelimiter(second, first))
+ return second;
+ }
+ return first;
+ }
+
+ /*
+ * @see java.text.BreakIterator#following(int)
+ */
+ public int following(int offset) {
+ int first = fIterator.following(offset);
+ if (eatFollowingWhitespace(offset, first)) {
+ int second = fIterator.following(first);
+ if (isWhitespace(first, second))
+ return second;
+ }
+ return first;
+ }
+
+ private boolean eatFollowingWhitespace(int offset, int exclusiveEnd) {
+ if (exclusiveEnd == DONE || offset == DONE)
+ return false;
+
+ if (isWhitespace(offset, exclusiveEnd))
+ return false;
+ if (isDelimiter(offset, exclusiveEnd))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns true
if the given sequence into the underlying
+ * text represents a delimiter, false
otherwise.
+ *
+ * @param offset
+ * the offset
+ * @param exclusiveEnd
+ * the end offset
+ * @return true
if the given range is a delimiter
+ */
+ private boolean isDelimiter(int offset, int exclusiveEnd) {
+ if (exclusiveEnd == DONE || offset == DONE)
+ return false;
+
+ Assert.isTrue(offset >= 0);
+ Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
+ Assert.isTrue(exclusiveEnd > offset);
+
+ CharSequence seq = fIterator.fText;
+
+ while (offset < exclusiveEnd) {
+ char ch = seq.charAt(offset);
+ if (ch != '\n' && ch != '\r')
+ return false;
+ offset++;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true
if the given sequence into the underlying
+ * text represents whitespace, but not a delimiter, false
+ * otherwise.
+ *
+ * @param offset
+ * the offset
+ * @param exclusiveEnd
+ * the end offset
+ * @return true
if the given range is whitespace
+ */
+ private boolean isWhitespace(int offset, int exclusiveEnd) {
+ if (exclusiveEnd == DONE || offset == DONE)
+ return false;
+
+ Assert.isTrue(offset >= 0);
+ Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
+ Assert.isTrue(exclusiveEnd > offset);
+
+ CharSequence seq = fIterator.fText;
+
+ while (offset < exclusiveEnd) {
+ char ch = seq.charAt(offset);
+ if (!Character.isWhitespace(ch))
+ return false;
+ if (ch == '\n' || ch == '\r')
+ return false;
+ offset++;
+ }
+
+ return true;
+ }
+
+ /*
+ * @see java.text.BreakIterator#current()
+ */
+ public int current() {
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.BreakIterator#getText()
+ */
+ public CharacterIterator getText() {
+ return fIterator.getText();
+ }
+
+ /**
+ * Sets the text as CharSequence
.
+ *
+ * @param newText
+ * the new text
+ */
+ public void setText(CharSequence newText) {
+ fIterator.setText(newText);
+ first();
+ }
+
+ /*
+ * @see java.text.BreakIterator#setText(java.text.CharacterIterator)
+ */
+ public void setText(CharacterIterator newText) {
+ fIterator.setText(newText);
+ first();
+ }
+
+ /*
+ * @see java.text.BreakIterator#setText(java.lang.String)
+ */
+ public void setText(String newText) {
+ setText((CharSequence) newText);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/LineBreakingReader.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/LineBreakingReader.java
new file mode 100644
index 0000000..c69c0c8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/LineBreakingReader.java
@@ -0,0 +1,116 @@
+package net.sourceforge.phpdt.internal.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.text.BreakIterator;
+
+import org.eclipse.swt.graphics.GC;
+
+/*
+ * Not a real reader. Could change if requested
+ */
+public class LineBreakingReader {
+
+ private BufferedReader fReader;
+
+ private GC fGC;
+
+ private int fMaxWidth;
+
+ private String fLine;
+
+ private int fOffset;
+
+ private BreakIterator fLineBreakIterator;
+
+ /**
+ * Creates a reader that breaks an input text to fit in a given width.
+ *
+ * @param reader
+ * Reader of the input text
+ * @param gc
+ * The graphic context that defines the currently used font sizes
+ * @param maxLineWidth
+ * The max width (pixes) where the text has to fit in
+ */
+ public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) {
+ fReader = new BufferedReader(reader);
+ fGC = gc;
+ fMaxWidth = maxLineWidth;
+ fOffset = 0;
+ fLine = null;
+ fLineBreakIterator = BreakIterator.getLineInstance();
+ }
+
+ public boolean isFormattedLine() {
+ return fLine != null;
+ }
+
+ /**
+ * Reads the next line. The lengths of the line will not exceed the gived
+ * maximum width.
+ */
+ public String readLine() throws IOException {
+ if (fLine == null) {
+ String line = fReader.readLine();
+ if (line == null)
+ return null;
+
+ int lineLen = fGC.textExtent(line).x;
+ if (lineLen < fMaxWidth) {
+ return line;
+ }
+ fLine = line;
+ fLineBreakIterator.setText(line);
+ fOffset = 0;
+ }
+ int breakOffset = findNextBreakOffset(fOffset);
+ String res;
+ if (breakOffset != BreakIterator.DONE) {
+ res = fLine.substring(fOffset, breakOffset);
+ fOffset = findWordBegin(breakOffset);
+ if (fOffset == fLine.length()) {
+ fLine = null;
+ }
+ } else {
+ res = fLine.substring(fOffset);
+ fLine = null;
+ }
+ return res;
+ }
+
+ private int findNextBreakOffset(int currOffset) {
+ int currWidth = 0;
+ int nextOffset = fLineBreakIterator.following(currOffset);
+ while (nextOffset != BreakIterator.DONE) {
+ String word = fLine.substring(currOffset, nextOffset);
+ int wordWidth = fGC.textExtent(word).x;
+ int nextWidth = wordWidth + currWidth;
+ if (nextWidth > fMaxWidth) {
+ if (currWidth > 0) {
+ return currOffset;
+ } else {
+ return nextOffset;
+ }
+ }
+ currWidth = nextWidth;
+ currOffset = nextOffset;
+ nextOffset = fLineBreakIterator.next();
+ }
+ return nextOffset;
+ }
+
+ private int findWordBegin(int idx) {
+ while (idx < fLine.length()
+ && Character.isWhitespace(fLine.charAt(idx))) {
+ idx++;
+ }
+ return idx;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPCodeReader.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPCodeReader.java
new file mode 100644
index 0000000..fffffda
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPCodeReader.java
@@ -0,0 +1,256 @@
+package net.sourceforge.phpdt.internal.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.io.IOException;
+
+import net.sourceforge.phpdt.internal.corext.phpdoc.SingleCharReader;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Reads from a document either forwards or backwards. May be configured to skip
+ * comments and strings.
+ */
+public class PHPCodeReader extends SingleCharReader {
+
+ /** The EOF character */
+ public static final int EOF = -1;
+
+ private boolean fSkipComments = false;
+
+ private boolean fSkipStrings = false;
+
+ private boolean fForward = false;
+
+ private IDocument fDocument;
+
+ private int fOffset;
+
+ private int fEnd = -1;
+
+ private int fCachedLineNumber = -1;
+
+ private int fCachedLineOffset = -1;
+
+ public PHPCodeReader() {
+ }
+
+ /**
+ * Returns the offset of the last read character. Should only be called
+ * after read has been called.
+ */
+ public int getOffset() {
+ return fForward ? fOffset - 1 : fOffset;
+ }
+
+ public void configureForwardReader(IDocument document, int offset,
+ int length, boolean skipComments, boolean skipStrings)
+ throws IOException {
+ fDocument = document;
+ fOffset = offset;
+ fSkipComments = skipComments;
+ fSkipStrings = skipStrings;
+
+ fForward = true;
+ fEnd = Math.min(fDocument.getLength(), fOffset + length);
+ }
+
+ public void configureBackwardReader(IDocument document, int offset,
+ boolean skipComments, boolean skipStrings) throws IOException {
+ fDocument = document;
+ fOffset = offset;
+ fSkipComments = skipComments;
+ fSkipStrings = skipStrings;
+
+ fForward = false;
+ try {
+ fCachedLineNumber = fDocument.getLineOfOffset(fOffset);
+ } catch (BadLocationException x) {
+ throw new IOException(x.getMessage());
+ }
+ }
+
+ /*
+ * @see Reader#close()
+ */
+ public void close() throws IOException {
+ fDocument = null;
+ }
+
+ /*
+ * @see SingleCharReader#read()
+ */
+ public int read() throws IOException {
+ try {
+ return fForward ? readForwards() : readBackwards();
+ } catch (BadLocationException x) {
+ throw new IOException(x.getMessage());
+ }
+ }
+
+ private void gotoCommentEnd() throws BadLocationException {
+ while (fOffset < fEnd) {
+ char current = fDocument.getChar(fOffset++);
+ if (current == '*') {
+ if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') {
+ ++fOffset;
+ return;
+ }
+ }
+ }
+ }
+
+ private void gotoStringEnd(char delimiter) throws BadLocationException {
+ while (fOffset < fEnd) {
+ char current = fDocument.getChar(fOffset++);
+ if (current == '\\') {
+ // ignore escaped characters
+ ++fOffset;
+ } else if (current == delimiter) {
+ return;
+ }
+ }
+ }
+
+ private void gotoLineEnd() throws BadLocationException {
+ int line = fDocument.getLineOfOffset(fOffset);
+ fOffset = fDocument.getLineOffset(line + 1);
+ }
+
+ private int readForwards() throws BadLocationException {
+ while (fOffset < fEnd) {
+ char current = fDocument.getChar(fOffset++);
+
+ switch (current) {
+ case '"':
+ case '\'':
+
+ if (fSkipStrings) {
+ gotoStringEnd(current);
+ continue;
+ }
+
+ return current;
+ case '#':
+
+ if (fSkipComments && fOffset < fEnd) {
+ gotoLineEnd();
+ continue;
+ }
+
+ return current;
+
+ case '/':
+
+ if (fSkipComments && fOffset < fEnd) {
+ char next = fDocument.getChar(fOffset);
+ if (next == '*') {
+ // a comment starts, advance to the comment end
+ ++fOffset;
+ gotoCommentEnd();
+ continue;
+ } else if (next == '/') {
+ // '//'-comment starts, advance to the line end
+ gotoLineEnd();
+ continue;
+ }
+ }
+
+ return current;
+
+ }
+
+ return current;
+ }
+
+ return EOF;
+ }
+
+ private void handleSingleLineComment() throws BadLocationException {
+ int line = fDocument.getLineOfOffset(fOffset);
+ if (line < fCachedLineNumber) {
+ fCachedLineNumber = line;
+ fCachedLineOffset = fDocument.getLineOffset(line);
+ int offset = fOffset;
+ while (fCachedLineOffset < offset) {
+ char current = fDocument.getChar(offset--);
+
+ if (current == '/' && fCachedLineOffset <= offset
+ && fDocument.getChar(offset) == '/') {
+ fOffset = offset;
+ return;
+ }
+
+ if (current == '#' && fCachedLineOffset <= offset) {
+ fOffset = offset;
+ return;
+ }
+ }
+ }
+ }
+
+ private void gotoCommentStart() throws BadLocationException {
+ while (0 < fOffset) {
+ char current = fDocument.getChar(fOffset--);
+ if (current == '*' && 0 <= fOffset
+ && fDocument.getChar(fOffset) == '/')
+ return;
+ }
+ }
+
+ private void gotoStringStart(char delimiter) throws BadLocationException {
+ while (0 < fOffset) {
+ char current = fDocument.getChar(fOffset);
+ if (current == delimiter) {
+ if (!(0 <= fOffset && fDocument.getChar(fOffset - 1) == '\\'))
+ return;
+ }
+ --fOffset;
+ }
+ }
+
+ private int readBackwards() throws BadLocationException {
+
+ while (0 < fOffset) {
+ --fOffset;
+
+ handleSingleLineComment();
+
+ char current = fDocument.getChar(fOffset);
+ switch (current) {
+ case '/':
+
+ if (fSkipComments && fOffset > 1) {
+ char next = fDocument.getChar(fOffset - 1);
+ if (next == '*') {
+ // a comment ends, advance to the comment start
+ fOffset -= 2;
+ gotoCommentStart();
+ continue;
+ }
+ }
+
+ return current;
+ case '"':
+ case '\'':
+
+ if (fSkipStrings) {
+ --fOffset;
+ gotoStringStart(current);
+ continue;
+ }
+
+ return current;
+ }
+
+ return current;
+ }
+
+ return EOF;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPPairMatcher.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPPairMatcher.java
new file mode 100644
index 0000000..ab9abd5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPPairMatcher.java
@@ -0,0 +1,188 @@
+package net.sourceforge.phpdt.internal.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.io.IOException;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.source.ICharacterPairMatcher;
+
+/**
+ * Helper class for match pairs of characters.
+ */
+public class PHPPairMatcher implements ICharacterPairMatcher {
+ protected char[] fPairs;
+
+ protected IDocument fDocument;
+
+ protected int fOffset;
+
+ protected int fStartPos;
+
+ protected int fEndPos;
+
+ protected int fAnchor;
+
+ protected PHPCodeReader fReader = new PHPCodeReader();
+
+ public PHPPairMatcher(char[] pairs) {
+ fPairs = pairs;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
+ */
+ public void clear() {
+ if (fReader != null) {
+ try {
+ fReader.close();
+ } catch (IOException x) {
+ // ignore
+ }
+ }
+ }
+
+ public IRegion match(IDocument document, int offset) {
+
+ fOffset = offset;
+
+ if (fOffset < 0)
+ return null;
+
+ fDocument = document;
+
+ if (matchPairsAt() && fStartPos != fEndPos)
+ return new Region(fStartPos, fEndPos - fStartPos + 1);
+
+ return null;
+ }
+
+ public int getAnchor() {
+ return fAnchor;
+ }
+
+ public void dispose() {
+ fDocument = null;
+ if (fReader != null) {
+ try {
+ fReader.close();
+ } catch (IOException x) {
+ // ignore
+ }
+ fReader = null;
+ }
+ }
+
+ protected boolean matchPairsAt() {
+
+ int i;
+ int pairIndex1 = fPairs.length;
+ int pairIndex2 = fPairs.length;
+
+ fStartPos = -1;
+ fEndPos = -1;
+
+ // get the chars preceding and following the start position
+ try {
+
+ char prevChar = fDocument.getChar(Math.max(fOffset - 1, 0));
+ char nextChar = fDocument.getChar(fOffset);
+
+ // search for opening peer character next to the activation point
+ for (i = 0; i < fPairs.length; i = i + 2) {
+ if (nextChar == fPairs[i]) {
+ fStartPos = fOffset;
+ pairIndex1 = i;
+ } else if (prevChar == fPairs[i]) {
+ fStartPos = fOffset - 1;
+ pairIndex1 = i;
+ }
+ }
+
+ // search for closing peer character next to the activation point
+ for (i = 1; i < fPairs.length; i = i + 2) {
+ if (prevChar == fPairs[i]) {
+ fEndPos = fOffset - 1;
+ pairIndex2 = i;
+ } else if (nextChar == fPairs[i]) {
+ fEndPos = fOffset;
+ pairIndex2 = i;
+ }
+ }
+
+ if (fEndPos > -1) {
+ fAnchor = RIGHT;
+ fStartPos = searchForOpeningPeer(fEndPos,
+ fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument);
+ if (fStartPos > -1)
+ return true;
+ else
+ fEndPos = -1;
+ } else if (fStartPos > -1) {
+ fAnchor = LEFT;
+ fEndPos = searchForClosingPeer(fStartPos, fPairs[pairIndex1],
+ fPairs[pairIndex1 + 1], fDocument);
+ if (fEndPos > -1)
+ return true;
+ else
+ fStartPos = -1;
+ }
+
+ } catch (BadLocationException x) {
+ } catch (IOException x) {
+ }
+
+ return false;
+ }
+
+ protected int searchForClosingPeer(int offset, int openingPeer,
+ int closingPeer, IDocument document) throws IOException {
+
+ fReader.configureForwardReader(document, offset + 1, document
+ .getLength(), true, true);
+
+ int stack = 1;
+ int c = fReader.read();
+ while (c != PHPCodeReader.EOF) {
+ if (c == openingPeer && c != closingPeer)
+ stack++;
+ else if (c == closingPeer)
+ stack--;
+
+ if (stack == 0)
+ return fReader.getOffset();
+
+ c = fReader.read();
+ }
+
+ return -1;
+ }
+
+ protected int searchForOpeningPeer(int offset, int openingPeer,
+ int closingPeer, IDocument document) throws IOException {
+
+ fReader.configureBackwardReader(document, offset, true, true);
+
+ int stack = 1;
+ int c = fReader.read();
+ while (c != PHPCodeReader.EOF) {
+ if (c == closingPeer && c != openingPeer)
+ stack++;
+ else if (c == openingPeer)
+ stack--;
+
+ if (stack == 0)
+ return fReader.getOffset();
+
+ c = fReader.read();
+ }
+
+ return -1;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java
new file mode 100644
index 0000000..acc8643
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * Adapts {@link org.eclipse.core.runtime.Preferences} to
+ * {@link org.eclipse.jface.preference.IPreferenceStore}
+ *
+ * @since 3.0
+ */
+public class PreferencesAdapter implements IPreferenceStore {
+
+ /**
+ * Property change listener. Listens for events of type
+ * {@link org.eclipse.core.runtime.Preferences.PropertyChangeEvent} and
+ * fires a {@link org.eclipse.jface.util.PropertyChangeEvent} on the adapter
+ * with arguments from the received event.
+ */
+ private class PropertyChangeListener implements
+ Preferences.IPropertyChangeListener {
+
+ /*
+ * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
+ */
+ public void propertyChange(Preferences.PropertyChangeEvent event) {
+ firePropertyChangeEvent(event.getProperty(), event.getOldValue(),
+ event.getNewValue());
+ }
+ }
+
+ /** Listeners on the adapter */
+ private ListenerList fListeners = new ListenerList();
+
+ /** Listener on the adapted Preferences */
+ private PropertyChangeListener fListener = new PropertyChangeListener();
+
+ /** Adapted Preferences */
+ private Preferences fPreferences;
+
+ /** True iff no events should be forwarded */
+ private boolean fSilent;
+
+ /**
+ * Initialize with empty Preferences.
+ */
+ public PreferencesAdapter() {
+ this(new Preferences());
+ }
+
+ /**
+ * Initialize with the given Preferences.
+ *
+ * @param preferences
+ * The preferences to wrap.
+ */
+ public PreferencesAdapter(Preferences preferences) {
+ fPreferences = preferences;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addPropertyChangeListener(IPropertyChangeListener listener) {
+ if (fListeners.size() == 0)
+ fPreferences.addPropertyChangeListener(fListener);
+ fListeners.add(listener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removePropertyChangeListener(IPropertyChangeListener listener) {
+ fListeners.remove(listener);
+ if (fListeners.size() == 0)
+ fPreferences.removePropertyChangeListener(fListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean contains(String name) {
+ return fPreferences.contains(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void firePropertyChangeEvent(String name, Object oldValue,
+ Object newValue) {
+ if (!fSilent) {
+ PropertyChangeEvent event = new PropertyChangeEvent(this, name,
+ oldValue, newValue);
+ Object[] listeners = fListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++)
+ ((IPropertyChangeListener) listeners[i]).propertyChange(event);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean getBoolean(String name) {
+ return fPreferences.getBoolean(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean getDefaultBoolean(String name) {
+ return fPreferences.getDefaultBoolean(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getDefaultDouble(String name) {
+ return fPreferences.getDefaultDouble(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public float getDefaultFloat(String name) {
+ return fPreferences.getDefaultFloat(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDefaultInt(String name) {
+ return fPreferences.getDefaultInt(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getDefaultLong(String name) {
+ return fPreferences.getDefaultLong(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDefaultString(String name) {
+ return fPreferences.getDefaultString(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getDouble(String name) {
+ return fPreferences.getDouble(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public float getFloat(String name) {
+ return fPreferences.getFloat(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getInt(String name) {
+ return fPreferences.getInt(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLong(String name) {
+ return fPreferences.getLong(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getString(String name) {
+ return fPreferences.getString(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDefault(String name) {
+ return fPreferences.isDefault(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean needsSaving() {
+ return fPreferences.needsSaving();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void putValue(String name, String value) {
+ try {
+ fSilent = true;
+ fPreferences.setValue(name, value);
+ } finally {
+ fSilent = false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, double value) {
+ fPreferences.setDefault(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, float value) {
+ fPreferences.setDefault(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, int value) {
+ fPreferences.setDefault(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, long value) {
+ fPreferences.setDefault(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, String defaultObject) {
+ fPreferences.setDefault(name, defaultObject);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, boolean value) {
+ fPreferences.setDefault(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setToDefault(String name) {
+ fPreferences.setToDefault(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, double value) {
+ fPreferences.setValue(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, float value) {
+ fPreferences.setValue(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, int value) {
+ fPreferences.setValue(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, long value) {
+ fPreferences.setValue(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, String value) {
+ fPreferences.setValue(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, boolean value) {
+ fPreferences.setValue(name, value);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SequenceCharacterIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SequenceCharacterIterator.java
new file mode 100644
index 0000000..33a9906
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SequenceCharacterIterator.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.text.CharacterIterator;
+
+import org.eclipse.jface.text.Assert;
+
+/**
+ * A CharSequence
based implementation of
+ * CharacterIterator
.
+ *
+ * @since 3.0
+ */
+public class SequenceCharacterIterator implements CharacterIterator {
+
+ private int fIndex = -1;
+
+ private final CharSequence fSequence;
+
+ private final int fFirst;
+
+ private final int fLast;
+
+ private void invariant() {
+ Assert.isTrue(fIndex >= fFirst);
+ Assert.isTrue(fIndex <= fLast);
+ }
+
+ /**
+ * Creates an iterator for the entire sequence.
+ *
+ * @param sequence
+ * the sequence backing this iterator
+ */
+ public SequenceCharacterIterator(CharSequence sequence) {
+ this(sequence, 0);
+ }
+
+ /**
+ * Creates an iterator.
+ *
+ * @param sequence
+ * the sequence backing this iterator
+ * @param first
+ * the first character to consider
+ * @throws IllegalArgumentException
+ * if the indices are out of bounds
+ */
+ public SequenceCharacterIterator(CharSequence sequence, int first)
+ throws IllegalArgumentException {
+ this(sequence, first, sequence.length());
+ }
+
+ /**
+ * Creates an iterator.
+ *
+ * @param sequence
+ * the sequence backing this iterator
+ * @param first
+ * the first character to consider
+ * @param last
+ * the last character index to consider
+ * @throws IllegalArgumentException
+ * if the indices are out of bounds
+ */
+ public SequenceCharacterIterator(CharSequence sequence, int first, int last)
+ throws IllegalArgumentException {
+ if (sequence == null)
+ throw new NullPointerException();
+ if (first < 0 || first > last)
+ throw new IllegalArgumentException();
+ if (last > sequence.length())
+ throw new IllegalArgumentException();
+ fSequence = sequence;
+ fFirst = first;
+ fLast = last;
+ fIndex = first;
+ invariant();
+ }
+
+ /*
+ * @see java.text.CharacterIterator#first()
+ */
+ public char first() {
+ return setIndex(getBeginIndex());
+ }
+
+ /*
+ * @see java.text.CharacterIterator#last()
+ */
+ public char last() {
+ if (fFirst == fLast)
+ return setIndex(getEndIndex());
+ else
+ return setIndex(getEndIndex() - 1);
+ }
+
+ /*
+ * @see java.text.CharacterIterator#current()
+ */
+ public char current() {
+ if (fIndex >= fFirst && fIndex < fLast)
+ return fSequence.charAt(fIndex);
+ else
+ return DONE;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#next()
+ */
+ public char next() {
+ return setIndex(Math.min(fIndex + 1, getEndIndex()));
+ }
+
+ /*
+ * @see java.text.CharacterIterator#previous()
+ */
+ public char previous() {
+ if (fIndex > getBeginIndex()) {
+ return setIndex(fIndex - 1);
+ } else {
+ return DONE;
+ }
+ }
+
+ /*
+ * @see java.text.CharacterIterator#setIndex(int)
+ */
+ public char setIndex(int position) {
+ if (position >= getBeginIndex() && position <= getEndIndex())
+ fIndex = position;
+ else
+ throw new IllegalArgumentException();
+
+ invariant();
+ return current();
+ }
+
+ /*
+ * @see java.text.CharacterIterator#getBeginIndex()
+ */
+ public int getBeginIndex() {
+ return fFirst;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#getEndIndex()
+ */
+ public int getEndIndex() {
+ return fLast;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#getIndex()
+ */
+ public int getIndex() {
+ return fIndex;
+ }
+
+ /*
+ * @see java.text.CharacterIterator#clone()
+ */
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new InternalError();
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java
new file mode 100644
index 0000000..9f74ae9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.VerifyKeyListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * Installs as a verify key listener on a viewer and overwrites the behaviour of
+ * the backspace key. Clients may register undo specifications for certain
+ * offsets in a document. The SmartBackspaceManager
will manage
+ * the specfications and execute the contained TextEdit
s when
+ * backspace is pressed at the given offset and the specification is still
+ * valid.
+ * TextEdit
s that will be executed when backspace is
+ * pressed at triggerOffset
. The spec will be removed
+ * when it is executed, or if more than lives
+ * TypingRun
s
+ * have ended after registering the spec.
+ * UndoSpec
s that will be
+ * executed upon repeated pressing of backspace.
+ * TextEdit
s to perform when executing
+ * the spec
+ * @param lives
+ * the number of TypingRun
s before removing
+ * the spec
+ * @param child
+ * a child specification that will be registered after
+ * executing this spec, or null
+ */
+ public UndoSpec(int triggerOffset, IRegion selection, TextEdit[] edits,
+ int lives, UndoSpec child) {
+ Assert.isLegal(triggerOffset >= 0);
+ Assert.isLegal(selection != null);
+ Assert.isLegal(lives >= 0);
+ Assert.isLegal(edits != null);
+ Assert.isLegal(edits.length > 0);
+ for (int i = 0; i < edits.length; i++) {
+ Assert.isLegal(edits[i] != null);
+ }
+
+ this.triggerOffset = triggerOffset;
+ this.selection = selection;
+ this.undoEdits = edits;
+ this.lives = lives;
+ this.child = child;
+ }
+ }
+
+ private class BackspaceListener implements VerifyKeyListener {
+
+ /*
+ * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
+ */
+ public void verifyKey(VerifyEvent event) {
+ if (fViewer != null && isBackspace(event)) {
+ int offset = getCaretOffset();
+ UndoSpec spec = removeEdit(offset);
+ if (spec != null) {
+ try {
+ beginChange();
+ for (int i = 0; i < spec.undoEdits.length; i++) {
+ spec.undoEdits[i].apply(getDocument(),
+ TextEdit.UPDATE_REGIONS);
+ }
+ fViewer.setSelectedRange(spec.selection.getOffset(),
+ spec.selection.getLength());
+ if (spec.child != null)
+ register(spec.child);
+ } catch (MalformedTreeException e) {
+ // fall back to standard bs
+ return;
+ } catch (BadLocationException e) {
+ // fall back to standard bs
+ return;
+ } finally {
+ endChange();
+ }
+ event.doit = false;
+ }
+
+ }
+ }
+
+ private void beginChange() {
+ ITextViewer viewer = fViewer;
+ if (viewer instanceof TextViewer) {
+ TextViewer v = (TextViewer) viewer;
+ v.getRewriteTarget().beginCompoundChange();
+ v.setRedraw(false);
+ }
+ }
+
+ private void endChange() {
+ ITextViewer viewer = fViewer;
+ if (viewer instanceof TextViewer) {
+ TextViewer v = (TextViewer) viewer;
+ v.getRewriteTarget().endCompoundChange();
+ v.setRedraw(true);
+ }
+ }
+
+ private boolean isBackspace(VerifyEvent event) {
+ return event.doit == true && event.character == SWT.BS
+ && event.stateMask == 0;
+ }
+
+ private int getCaretOffset() {
+ ITextViewer viewer = fViewer;
+ Point point = viewer.getSelectedRange();
+ return point.x;
+ }
+
+ }
+
+ private ITextViewer fViewer;
+
+ private BackspaceListener fBackspaceListener;
+
+ private Map fSpecs;
+
+ private TypingRunDetector fRunDetector;
+
+ private ITypingRunListener fRunListener;
+
+ /**
+ * Registers an undo specification with this manager.
+ *
+ * @param spec
+ * the specification to register
+ * @throws IllegalStateException
+ * if the manager is not installed
+ */
+ public void register(UndoSpec spec) {
+ if (fViewer == null)
+ throw new IllegalStateException();
+
+ ensureListenerInstalled();
+ addEdit(spec);
+ }
+
+ private void addEdit(UndoSpec spec) {
+ Integer i = new Integer(spec.triggerOffset);
+ fSpecs.put(i, spec);
+ }
+
+ private UndoSpec removeEdit(int offset) {
+ Integer i = new Integer(offset);
+ UndoSpec spec = (UndoSpec) fSpecs.remove(i);
+ return spec;
+ }
+
+ private void ensureListenerInstalled() {
+ if (fBackspaceListener == null) {
+ fBackspaceListener = new BackspaceListener();
+ ITextViewer viewer = fViewer;
+ if (viewer instanceof ITextViewerExtension)
+ ((ITextViewerExtension) viewer)
+ .prependVerifyKeyListener(fBackspaceListener);
+ else
+ viewer.getTextWidget().addVerifyKeyListener(fBackspaceListener);
+ }
+ }
+
+ private void ensureListenerRemoved() {
+ if (fBackspaceListener != null) {
+ ITextViewer viewer = fViewer;
+ if (viewer instanceof ITextViewerExtension)
+ ((ITextViewerExtension) viewer)
+ .removeVerifyKeyListener(fBackspaceListener);
+ else
+ viewer.getTextWidget().removeVerifyKeyListener(
+ fBackspaceListener);
+ fBackspaceListener = null;
+ }
+ }
+
+ private IDocument getDocument() {
+ return fViewer.getDocument();
+ }
+
+ /**
+ * Installs the receiver on a text viewer.
+ *
+ * @param viewer
+ */
+ public void install(ITextViewer viewer) {
+ Assert.isLegal(viewer != null);
+
+ fViewer = viewer;
+ fSpecs = new HashMap();
+ fRunDetector = new TypingRunDetector();
+ fRunDetector.install(viewer);
+ fRunListener = new ITypingRunListener() {
+
+ /*
+ * @see org.eclipse.jface.text.TypingRunDetector.ITypingRunListener#typingRunStarted(org.eclipse.jface.text.TypingRunDetector.TypingRun)
+ */
+ public void typingRunStarted(TypingRun run) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.TypingRunDetector.ITypingRunListener#typingRunEnded(org.eclipse.jface.text.TypingRunDetector.TypingRun)
+ */
+ public void typingRunEnded(TypingRun run, ChangeType reason) {
+ if (reason == TypingRun.SELECTION)
+ fSpecs.clear();
+ else
+ prune();
+ }
+ };
+ fRunDetector.addTypingRunListener(fRunListener);
+ }
+
+ private void prune() {
+ for (Iterator it = fSpecs.values().iterator(); it.hasNext();) {
+ UndoSpec spec = (UndoSpec) it.next();
+ if (--spec.lives < 0)
+ it.remove();
+ }
+ }
+
+ /**
+ * Uninstalls the receiver. No undo specifications may be registered on an
+ * uninstalled manager.
+ */
+ public void uninstall() {
+ if (fViewer != null) {
+ fRunDetector.removeTypingRunListener(fRunListener);
+ fRunDetector.uninstall();
+ fRunDetector = null;
+ ensureListenerRemoved();
+ fViewer = null;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java
new file mode 100644
index 0000000..00e57c1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java
@@ -0,0 +1,1299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.Arrays;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.core.Assert;
+import net.sourceforge.phpdt.internal.ui.text.SmartBackspaceManager.UndoSpec;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.texteditor.ITextEditorExtension2;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+
+/**
+ * Modifies DocumentCommand
s inserting semicolons and opening
+ * braces to place them smartly, i.e. moving them to the end of a line if that
+ * is what the user expects.
+ *
+ * for
statements definition. If the line contains a semicolon or
+ * brace after the current caret position, the cursor is moved after it.
+ * doit
is false (so it works in code
+ // completion situations)
+ // if (!command.doit)
+ // return;
+
+ if (command.text == null)
+ return;
+
+ if (command.text.equals(SEMICOLON))
+ fCharacter = SEMICHAR;
+ else if (command.text.equals(BRACE))
+ fCharacter = BRACECHAR;
+ else
+ return;
+
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ if (fCharacter == SEMICHAR
+ && !store
+ .getBoolean(PreferenceConstants.EDITOR_SMART_SEMICOLON))
+ return;
+ if (fCharacter == BRACECHAR
+ && !store
+ .getBoolean(PreferenceConstants.EDITOR_SMART_OPENING_BRACE))
+ return;
+
+ IWorkbenchPage page = WebUI.getActivePage();
+ if (page == null)
+ return;
+ IEditorPart part = page.getActiveEditor();
+ if (!(part instanceof PHPUnitEditor))
+ return;
+ PHPUnitEditor editor = (PHPUnitEditor) part;
+ if (editor.getInsertMode() != ITextEditorExtension3.SMART_INSERT
+ || !editor.isEditable())
+ return;
+ ITextEditorExtension2 extension = (ITextEditorExtension2) editor
+ .getAdapter(ITextEditorExtension2.class);
+ if (extension != null && !extension.validateEditorInputState())
+ return;
+ if (isMultilineSelection(document, command))
+ return;
+
+ // 1: find concerned line / position in java code, location in statement
+ int pos = command.offset;
+ ITextSelection line;
+ try {
+ IRegion l = document.getLineInformationOfOffset(pos);
+ line = new TextSelection(document, l.getOffset(), l.getLength());
+ } catch (BadLocationException e) {
+ return;
+ }
+
+ // 2: choose action based on findings (is for-Statement?)
+ // for now: compute the best position to insert the new character
+ int positionInLine = computeCharacterPosition(document, line, pos
+ - line.getOffset(), fCharacter, fPartitioning);
+ int position = positionInLine + line.getOffset();
+
+ // never position before the current position!
+ if (position < pos)
+ return;
+
+ // never double already existing content
+ if (alreadyPresent(document, fCharacter, position))
+ return;
+
+ // don't do special processing if what we do is actually the normal
+ // behaviour
+ String insertion = adjustSpacing(document, position, fCharacter);
+ if (command.offset == position && insertion.equals(command.text))
+ return;
+
+ try {
+
+ final SmartBackspaceManager manager = (SmartBackspaceManager) editor
+ .getAdapter(SmartBackspaceManager.class);
+ if (manager != null
+ && WebUI.getDefault().getPreferenceStore()
+ .getBoolean(
+ PreferenceConstants.EDITOR_SMART_BACKSPACE)) {
+ TextEdit e1 = new ReplaceEdit(command.offset, command.text
+ .length(), document.get(command.offset, command.length));
+ UndoSpec s1 = new UndoSpec(command.offset
+ + command.text.length(), new Region(command.offset, 0),
+ new TextEdit[] { e1 }, 0, null);
+
+ DeleteEdit smart = new DeleteEdit(position, insertion.length());
+ ReplaceEdit raw = new ReplaceEdit(command.offset,
+ command.length, command.text);
+ UndoSpec s2 = new UndoSpec(position + insertion.length(),
+ new Region(command.offset + command.text.length(), 0),
+ new TextEdit[] { smart, raw }, 2, s1);
+ manager.register(s2);
+ }
+
+ // 3: modify command
+ command.offset = position;
+ command.length = 0;
+ command.caretOffset = position;
+ command.text = insertion;
+ command.doit = true;
+ command.owner = null;
+ } catch (MalformedTreeException e) {
+ WebUI.log(e);
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ }
+
+ }
+
+ /**
+ * Returns true
if the document command is applied on a multi
+ * line selection, false
otherwise.
+ *
+ * @param document
+ * the document
+ * @param command
+ * the command
+ * @return true
if command
is a multiline
+ * command
+ */
+ private boolean isMultilineSelection(IDocument document,
+ DocumentCommand command) {
+ try {
+ return document.getNumberOfLines(command.offset, command.length) > 1;
+ } catch (BadLocationException e) {
+ // ignore
+ return false;
+ }
+ }
+
+ /**
+ * Adds a space before a brace if it is inserted after a parenthesis, equal
+ * sign, or one of the keywords try, else, do
.
+ *
+ * @param document
+ * the document we are working on
+ * @param position
+ * the insert position of character
+ * @param character
+ * the character to be inserted
+ * @return a String
consisting of character
+ * plus any additional spacing
+ */
+ private String adjustSpacing(IDocument doc, int position, char character) {
+ if (character == BRACECHAR) {
+ if (position > 0 && position <= doc.getLength()) {
+ int pos = position - 1;
+ if (looksLike(doc, pos, ")") //$NON-NLS-1$
+ || looksLike(doc, pos, "=") //$NON-NLS-1$
+ || looksLike(doc, pos, "]") //$NON-NLS-1$
+ || looksLike(doc, pos, "try") //$NON-NLS-1$
+ || looksLike(doc, pos, "else") //$NON-NLS-1$
+ || looksLike(doc, pos, "synchronized") //$NON-NLS-1$
+ || looksLike(doc, pos, "static") //$NON-NLS-1$
+ || looksLike(doc, pos, "finally") //$NON-NLS-1$
+ || looksLike(doc, pos, "do")) //$NON-NLS-1$
+ return new String(new char[] { ' ', character });
+ }
+ }
+
+ return new String(new char[] { character });
+ }
+
+ /**
+ * Checks whether a character to be inserted is already present at the
+ * insert location (perhaps separated by some whitespace from
+ * position
.
+ *
+ * @param document
+ * the document we are working on
+ * @param position
+ * the insert position of ch
+ * @param character
+ * the character to be inserted
+ * @return true
if ch
is already present at
+ * location
, false
otherwise
+ */
+ private boolean alreadyPresent(IDocument document, char ch, int position) {
+ int pos = firstNonWhitespaceForward(document, position, fPartitioning,
+ document.getLength());
+ try {
+ if (pos != -1 && document.getChar(pos) == ch)
+ return true;
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Computes the next insert position of the given character in the current
+ * line.
+ *
+ * @param document
+ * the document we are working on
+ * @param line
+ * the line where the change is being made
+ * @param offset
+ * the position of the caret in the line when
+ * character
was typed
+ * @param character
+ * the character to look for
+ * @param partitioning
+ * the document partitioning
+ * @return the position where character
should be inserted /
+ * replaced
+ */
+ protected static int computeCharacterPosition(IDocument document,
+ ITextSelection line, int offset, char character, String partitioning) {
+ String text = line.getText();
+ if (text == null)
+ return 0;
+
+ int insertPos;
+ if (character == BRACECHAR) {
+
+ insertPos = computeArrayInitializationPos(document, line, offset,
+ partitioning);
+
+ if (insertPos == -1) {
+ insertPos = computeAfterTryDoElse(document, line, offset);
+ }
+
+ if (insertPos == -1) {
+ insertPos = computeAfterParenthesis(document, line, offset,
+ partitioning);
+ }
+
+ } else if (character == SEMICHAR) {
+
+ if (isForStatement(text, offset)) {
+ insertPos = -1; // don't do anything in for statements, as semis
+ // are vital part of these
+ } else {
+ int nextPartitionPos = nextPartitionOrLineEnd(document, line,
+ offset, partitioning);
+ insertPos = startOfWhitespaceBeforeOffset(text,
+ nextPartitionPos);
+ // if there is a semi present, return its location as
+ // alreadyPresent() will take it out this way.
+ if (insertPos > 0 && text.charAt(insertPos - 1) == character)
+ insertPos = insertPos - 1;
+ }
+
+ } else {
+ Assert.isTrue(false);
+ return -1;
+ }
+
+ return insertPos;
+ }
+
+ /**
+ * Computes an insert position for an opening brace if offset
+ * maps to a position in document
that looks like being the
+ * RHS of an assignment or like an array definition.
+ *
+ * @param document
+ * the document being modified
+ * @param line
+ * the current line under investigation
+ * @param offset
+ * the offset of the caret position, relative to the line start.
+ * @param partitioning
+ * the document partitioning
+ * @return an insert position relative to the line start if
+ * line
looks like being an array initialization at
+ * offset
, -1 otherwise
+ */
+ private static int computeArrayInitializationPos(IDocument document,
+ ITextSelection line, int offset, String partitioning) {
+ // search backward while WS, find = (not != <= >= ==) in default
+ // partition
+ int pos = offset + line.getOffset();
+
+ if (pos == 0)
+ return -1;
+
+ int p = firstNonWhitespaceBackward(document, pos - 1, partitioning, -1);
+
+ if (p == -1)
+ return -1;
+
+ try {
+
+ char ch = document.getChar(p);
+ if (ch != '=' && ch != ']')
+ return -1;
+
+ if (p == 0)
+ return offset;
+
+ p = firstNonWhitespaceBackward(document, p - 1, partitioning, -1);
+ if (p == -1)
+ return -1;
+
+ ch = document.getChar(p);
+ if (Scanner.isPHPIdentifierPart(ch) || ch == ']' || ch == '[')
+ return offset;
+
+ } catch (BadLocationException e) {
+ }
+ return -1;
+ }
+
+ /**
+ * Computes an insert position for an opening brace if offset
+ * maps to a position in document
involving a keyword taking
+ * a block after it. These are: try
, do
,
+ * synchronized
, static
,
+ * finally
, or else
.
+ *
+ * @param document
+ * the document being modified
+ * @param line
+ * the current line under investigation
+ * @param offset
+ * the offset of the caret position, relative to the line start.
+ * @return an insert position relative to the line start if
+ * line
contains one of the above keywords at or
+ * before offset
, -1 otherwise
+ */
+ private static int computeAfterTryDoElse(IDocument doc,
+ ITextSelection line, int offset) {
+ // search backward while WS, find 'try', 'do', 'else' in default
+ // partition
+ int p = offset + line.getOffset();
+ p = firstWhitespaceToRight(doc, p);
+ if (p == -1)
+ return -1;
+ p--;
+
+ if (looksLike(doc, p, "try") //$NON-NLS-1$
+ || looksLike(doc, p, "do") //$NON-NLS-1$
+ || looksLike(doc, p, "synchronized") //$NON-NLS-1$
+ || looksLike(doc, p, "static") //$NON-NLS-1$
+ || looksLike(doc, p, "finally") //$NON-NLS-1$
+ || looksLike(doc, p, "else")) //$NON-NLS-1$
+ return p + 1 - line.getOffset();
+
+ return -1;
+ }
+
+ /**
+ * Computes an insert position for an opening brace if offset
+ * maps to a position in document
with a expression in
+ * parenthesis that will take a block after the closing parenthesis.
+ *
+ * @param document
+ * the document being modified
+ * @param line
+ * the current line under investigation
+ * @param offset
+ * the offset of the caret position, relative to the line start.
+ * @param partitioning
+ * the document partitioning
+ * @return an insert position relative to the line start if
+ * line
contains a parenthesized expression that can
+ * be followed by a block, -1 otherwise
+ */
+ private static int computeAfterParenthesis(IDocument document,
+ ITextSelection line, int offset, String partitioning) {
+ // find the opening parenthesis for every closing parenthesis on the
+ // current line after offset
+ // return the position behind the closing parenthesis if it looks like a
+ // method declaration
+ // or an expression for an if, while, for, catch statement
+ int pos = offset + line.getOffset();
+ int length = line.getOffset() + line.getLength();
+ int scanTo = scanForward(document, pos, partitioning, length, '}');
+ if (scanTo == -1)
+ scanTo = length;
+
+ int closingParen = findClosingParenToLeft(document, pos, partitioning) - 1;
+
+ while (true) {
+ int startScan = closingParen + 1;
+ closingParen = scanForward(document, startScan, partitioning,
+ scanTo, ')');
+ if (closingParen == -1)
+ break;
+
+ int openingParen = findOpeningParenMatch(document, closingParen,
+ partitioning);
+
+ // no way an expression at the beginning of the document can mean
+ // anything
+ if (openingParen < 1)
+ break;
+
+ // only select insert positions for parenthesis currently embracing
+ // the caret
+ if (openingParen > pos)
+ continue;
+
+ if (looksLikeAnonymousClassDef(document, openingParen - 1,
+ partitioning))
+ return closingParen + 1 - line.getOffset();
+
+ if (looksLikeIfWhileForCatch(document, openingParen - 1,
+ partitioning))
+ return closingParen + 1 - line.getOffset();
+
+ if (looksLikeMethodDecl(document, openingParen - 1, partitioning))
+ return closingParen + 1 - line.getOffset();
+
+ }
+
+ return -1;
+ }
+
+ /**
+ * Finds a closing parenthesis to the left of position
in
+ * document, where that parenthesis is only separated by whitespace from
+ * position
. If no such parenthesis can be found,
+ * position
is returned.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @return the position of a closing parenthesis left to
+ * position
separated only by whitespace, or
+ * position
if no parenthesis can be found
+ */
+ private static int findClosingParenToLeft(IDocument document, int position,
+ String partitioning) {
+ final char CLOSING_PAREN = ')';
+ try {
+ if (position < 1)
+ return position;
+
+ int nonWS = firstNonWhitespaceBackward(document, position - 1,
+ partitioning, -1);
+ if (nonWS != -1 && document.getChar(nonWS) == CLOSING_PAREN)
+ return nonWS;
+ } catch (BadLocationException e1) {
+ }
+ return position;
+ }
+
+ /**
+ * Finds the first whitespace character position to the right of (and
+ * including) position
.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @return the position of a whitespace character greater or equal than
+ * position
separated only by whitespace, or -1 if
+ * none found
+ */
+ private static int firstWhitespaceToRight(IDocument document, int position) {
+ int length = document.getLength();
+ Assert.isTrue(position >= 0);
+ Assert.isTrue(position <= length);
+
+ try {
+ while (position < length) {
+ char ch = document.getChar(position);
+ if (Character.isWhitespace(ch))
+ return position;
+ position++;
+ }
+ return position;
+ } catch (BadLocationException e) {
+ }
+ return -1;
+ }
+
+ /**
+ * Finds the highest position in document
such that the
+ * position is <= position
and > bound
+ * and Character.isWhitespace(document.getChar(pos))
+ * evaluates to false
and the position is in the default
+ * partition.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @param bound
+ * the first position in document
to not consider
+ * any more, with bound
> position
+ * @return the highest position of one element in chars
in [position
,
+ * scanTo
) that resides in a Java partition, or
+ * -1
if none can be found
+ */
+ private static int firstNonWhitespaceBackward(IDocument document,
+ int position, String partitioning, int bound) {
+ Assert.isTrue(position < document.getLength());
+ Assert.isTrue(bound >= -1);
+
+ try {
+ while (position > bound) {
+ char ch = document.getChar(position);
+ if (!Character.isWhitespace(ch)
+ && isDefaultPartition(document, position, partitioning))
+ return position;
+ position--;
+ }
+ } catch (BadLocationException e) {
+ }
+ return -1;
+ }
+
+ /**
+ * Finds the smallest position in document
such that the
+ * position is >= position
and < bound
+ * and Character.isWhitespace(document.getChar(pos))
+ * evaluates to false
and the position is in the default
+ * partition.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @param bound
+ * the first position in document
to not consider
+ * any more, with bound
> position
+ * @return the smallest position of one element in chars
in [position
,
+ * scanTo
) that resides in a Java partition, or
+ * -1
if none can be found
+ */
+ private static int firstNonWhitespaceForward(IDocument document,
+ int position, String partitioning, int bound) {
+ Assert.isTrue(position >= 0);
+ Assert.isTrue(bound <= document.getLength());
+
+ try {
+ while (position < bound) {
+ char ch = document.getChar(position);
+ if (!Character.isWhitespace(ch)
+ && isDefaultPartition(document, position, partitioning))
+ return position;
+ position++;
+ }
+ } catch (BadLocationException e) {
+ }
+ return -1;
+ }
+
+ /**
+ * Finds the highest position in document
such that the
+ * position is <= position
and > bound
+ * and document.getChar(position) == ch
evaluates to
+ * true
for at least one ch in chars
and the
+ * position is in the default partition.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @param bound
+ * the first position in document
to not consider
+ * any more, with scanTo
>
+ * position
+ * @param chars
+ * an array of char
to search for
+ * @return the highest position of one element in chars
in (bound
,
+ * position
] that resides in a Java partition, or
+ * -1
if none can be found
+ */
+ private static int scanBackward(IDocument document, int position,
+ String partitioning, int bound, char[] chars) {
+ Assert.isTrue(bound >= -1);
+ Assert.isTrue(position < document.getLength());
+
+ Arrays.sort(chars);
+
+ try {
+ while (position > bound) {
+
+ if (Arrays.binarySearch(chars, document.getChar(position)) >= 0
+ && isDefaultPartition(document, position, partitioning))
+ return position;
+
+ position--;
+ }
+ } catch (BadLocationException e) {
+ }
+ return -1;
+ }
+
+ // /**
+ // * Finds the highest position in document
such that the
+ // position is <= position
+ // * and > bound
and document.getChar(position) ==
+ // ch
evaluates to true
+ // * and the position is in the default partition.
+ // *
+ // * @param document the document being modified
+ // * @param position the first character position in document
+ // to be considered
+ // * @param bound the first position in document
to not
+ // consider any more, with scanTo
> position
+ // * @param chars an array of char
to search for
+ // * @return the highest position of one element in chars
in
+ // [position
, scanTo
) that resides in a Java
+ // partition, or -1
if none can be found
+ // */
+ // private static int scanBackward(IDocument document, int position, int
+ // bound, char ch) {
+ // return scanBackward(document, position, bound, new char[] {ch});
+ // }
+ //
+ /**
+ * Finds the lowest position in document
such that the
+ * position is >= position
and < bound
+ * and document.getChar(position) == ch
evaluates to
+ * true
for at least one ch in chars
and the
+ * position is in the default partition.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @param bound
+ * the first position in document
to not consider
+ * any more, with scanTo
>
+ * position
+ * @param chars
+ * an array of char
to search for
+ * @return the lowest position of one element in chars
in [position
,
+ * bound
) that resides in a Java partition, or
+ * -1
if none can be found
+ */
+ private static int scanForward(IDocument document, int position,
+ String partitioning, int bound, char[] chars) {
+ Assert.isTrue(position >= 0);
+ Assert.isTrue(bound <= document.getLength());
+
+ Arrays.sort(chars);
+
+ try {
+ while (position < bound) {
+
+ if (Arrays.binarySearch(chars, document.getChar(position)) >= 0
+ && isDefaultPartition(document, position, partitioning))
+ return position;
+
+ position++;
+ }
+ } catch (BadLocationException e) {
+ }
+ return -1;
+ }
+
+ /**
+ * Finds the lowest position in document
such that the
+ * position is >= position
and < bound
+ * and document.getChar(position) == ch
evaluates to
+ * true
and the position is in the default partition.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @param bound
+ * the first position in document
to not consider
+ * any more, with scanTo
>
+ * position
+ * @param chars
+ * an array of char
to search for
+ * @return the lowest position of one element in chars
in [position
,
+ * bound
) that resides in a Java partition, or
+ * -1
if none can be found
+ */
+ private static int scanForward(IDocument document, int position,
+ String partitioning, int bound, char ch) {
+ return scanForward(document, position, partitioning, bound,
+ new char[] { ch });
+ }
+
+ /**
+ * Checks whether the content of document
in the range (offset
,
+ * length
) contains the new
keyword.
+ *
+ * @param document
+ * the document being modified
+ * @param offset
+ * the first character position in document
to be
+ * considered
+ * @param length
+ * the length of the character range to be considered
+ * @param partitioning
+ * the document partitioning
+ * @return true
if the specified character range contains a
+ * new
keyword, false
otherwise.
+ */
+ private static boolean isNewMatch(IDocument document, int offset,
+ int length, String partitioning) {
+ Assert.isTrue(length >= 0);
+ Assert.isTrue(offset >= 0);
+ Assert.isTrue(offset + length < document.getLength() + 1);
+
+ try {
+ String text = document.get(offset, length);
+ int pos = text.indexOf("new"); //$NON-NLS-1$
+
+ while (pos != -1
+ && !isDefaultPartition(document, pos + offset, partitioning))
+ pos = text.indexOf("new", pos + 2); //$NON-NLS-1$
+
+ if (pos < 0)
+ return false;
+
+ if (pos != 0 && Scanner.isPHPIdentifierPart(text.charAt(pos - 1)))
+ return false;
+
+ if (pos + 3 < length
+ && Scanner.isPHPIdentifierPart(text.charAt(pos + 3)))
+ return false;
+
+ return true;
+
+ } catch (BadLocationException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether the content of document
at
+ * position
looks like an anonymous class definition.
+ * position
must be to the left of the opening parenthesis of
+ * the definition's parameter list.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @return true
if the content of document
+ * looks like an anonymous class definition, false
+ * otherwise
+ */
+ private static boolean looksLikeAnonymousClassDef(IDocument document,
+ int position, String partitioning) {
+ int previousCommaOrParen = scanBackward(document, position - 1,
+ partitioning, -1, new char[] { ',', '(' });
+ if (previousCommaOrParen == -1 || position < previousCommaOrParen + 5) // 2
+ // for
+ // borders,
+ // 3
+ // for
+ // "new"
+ return false;
+
+ if (isNewMatch(document, previousCommaOrParen + 1, position
+ - previousCommaOrParen - 2, partitioning))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Checks whether position
resides in a default (Java)
+ * partition of document
.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the position to be checked
+ * @param partitioning
+ * the document partitioning
+ * @return true
if position
is in the default
+ * partition of document
, false
+ * otherwise
+ */
+ private static boolean isDefaultPartition(IDocument document, int position,
+ String partitioning) {
+ Assert.isTrue(position >= 0);
+ Assert.isTrue(position <= document.getLength());
+
+ try {
+ // don't use getPartition2 since we're interested in the scanned
+ // character's partition
+ ITypedRegion region = TextUtilities.getPartition(document,
+ partitioning, position, false);
+ return region.getType().equals(IDocument.DEFAULT_CONTENT_TYPE);
+
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Finds the position of the parenthesis matching the closing parenthesis at
+ * position
.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the position in document
of a closing
+ * parenthesis
+ * @param partitioning
+ * the document partitioning
+ * @return the position in document
of the matching
+ * parenthesis, or -1 if none can be found
+ */
+ private static int findOpeningParenMatch(IDocument document, int position,
+ String partitioning) {
+ final char CLOSING_PAREN = ')';
+ final char OPENING_PAREN = '(';
+
+ Assert.isTrue(position < document.getLength());
+ Assert.isTrue(position >= 0);
+ Assert.isTrue(isDefaultPartition(document, position, partitioning));
+
+ try {
+
+ Assert.isTrue(document.getChar(position) == CLOSING_PAREN);
+
+ int depth = 1;
+ while (true) {
+ position = scanBackward(document, position - 1, partitioning,
+ -1, new char[] { CLOSING_PAREN, OPENING_PAREN });
+ if (position == -1)
+ return -1;
+
+ if (document.getChar(position) == CLOSING_PAREN)
+ depth++;
+ else
+ depth--;
+
+ if (depth == 0)
+ return position;
+ }
+
+ } catch (BadLocationException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * Checks whether, to the left of position
and separated only
+ * by whitespace, document
contains a keyword taking a
+ * parameter list and a block after it. These are: if
,
+ * while
, catch
, for
,
+ * synchronized
, switch
.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @return true
if document
contains any of
+ * the above keywords to the left of position
,
+ * false
otherwise
+ */
+ private static boolean looksLikeIfWhileForCatch(IDocument document,
+ int position, String partitioning) {
+ position = firstNonWhitespaceBackward(document, position, partitioning,
+ -1);
+ if (position == -1)
+ return false;
+
+ return looksLike(document, position, "if") //$NON-NLS-1$
+ || looksLike(document, position, "while") //$NON-NLS-1$
+ || looksLike(document, position, "catch") //$NON-NLS-1$
+ || looksLike(document, position, "synchronized") //$NON-NLS-1$
+ || looksLike(document, position, "switch") //$NON-NLS-1$
+ || looksLike(document, position, "for"); //$NON-NLS-1$
+ }
+
+ /**
+ * Checks whether code>document contains the String
like
+ * such that its last character is at position
. If like
+ * starts with a identifier part (as determined by
+ * {@link Scanner#isPHPIdentifierPart(char)}), it is also made sure that
+ * like
is preceded by some non-identifier character or
+ * stands at the document start.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param like
+ * the String
to look for.
+ * @return true
if document
contains like
+ * such that it ends at position
, false
+ * otherwise
+ */
+ private static boolean looksLike(IDocument document, int position,
+ String like) {
+ int length = like.length();
+ if (position < length - 1)
+ return false;
+
+ try {
+ if (!like.equals(document.get(position - length + 1, length)))
+ return false;
+
+ if (position >= length
+ && Scanner.isPHPIdentifierPart(like.charAt(0))
+ && Scanner.isPHPIdentifierPart(document.getChar(position
+ - length)))
+ return false;
+
+ } catch (BadLocationException e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks whether the content of document
at
+ * position
looks like a method declaration header (i.e. only
+ * the return type and method name). position
must be just
+ * left of the opening parenthesis of the parameter list.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @return true
if the content of document
+ * looks like a method definition, false
otherwise
+ */
+ private static boolean looksLikeMethodDecl(IDocument document,
+ int position, String partitioning) {
+
+ // method name
+ position = eatIdentToLeft(document, position, partitioning);
+ if (position < 1)
+ return false;
+
+ position = eatBrackets(document, position - 1, partitioning);
+ if (position < 1)
+ return false;
+
+ position = eatIdentToLeft(document, position - 1, partitioning);
+
+ return position != -1;
+ }
+
+ /**
+ * From position
to the left, eats any whitespace and then a
+ * pair of brackets as used to declare an array return type like
+ *
+ *
+ * String [ ]
+ *
. The return value is either the position of the opening bracket
+ * or position
if no pair of brackets can be parsed.
+ *
+ * @param document
+ * the document being modified
+ * @param position
+ * the first character position in document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @return the smallest character position of bracket pair or
+ * position
+ */
+ private static int eatBrackets(IDocument document, int position,
+ String partitioning) {
+ // accept array return type
+ int pos = firstNonWhitespaceBackward(document, position, partitioning,
+ -1);
+ try {
+ if (pos > 1 && document.getChar(pos) == ']') {
+ pos = firstNonWhitespaceBackward(document, pos - 1,
+ partitioning, -1);
+ if (pos > 0 && document.getChar(pos) == '[')
+ return pos;
+ }
+ } catch (BadLocationException e) {
+ // won't happen
+ }
+ return position;
+ }
+
+ /**
+ * From position
to the left, eats any whitespace and the
+ * first identifier, returning the position of the first identifier
+ * character (in normal read order).
+ * " some string "
and
+ * positionition 13, the return value will be 6 (the first letter in
+ * string
).
+ * document
to be
+ * considered
+ * @param partitioning
+ * the document partitioning
+ * @return the smallest character position of an identifier or -1 if none
+ * can be found; always <= position
+ */
+ private static int eatIdentToLeft(IDocument document, int position,
+ String partitioning) {
+ if (position < 0)
+ return -1;
+ Assert.isTrue(position < document.getLength());
+
+ int p = firstNonWhitespaceBackward(document, position, partitioning, -1);
+ if (p == -1)
+ return -1;
+
+ try {
+ while (p >= 0) {
+
+ char ch = document.getChar(p);
+ if (Scanner.isPHPIdentifierPart(ch)) {
+ p--;
+ continue;
+ }
+
+ // length must be > 0
+ if (Character.isWhitespace(ch) && p != position)
+ return p + 1;
+ else
+ return -1;
+
+ }
+
+ // start of document reached
+ return 0;
+
+ } catch (BadLocationException e) {
+ }
+ return -1;
+ }
+
+ /**
+ * Returns a position in the first java partition after the last non-empty
+ * and non-comment partition. There is no non-whitespace from the returned
+ * position to the end of the partition it is contained in.
+ *
+ * @param document
+ * the document being modified
+ * @param line
+ * the line under investigation
+ * @param offset
+ * the caret offset into line
+ * @param partitioning
+ * the document partitioning
+ * @return the position of the next Java partition, or the end of
+ * line
+ */
+ private static int nextPartitionOrLineEnd(IDocument document,
+ ITextSelection line, int offset, String partitioning) {
+ // run relative to document
+ final int docOffset = offset + line.getOffset();
+ final int eol = line.getOffset() + line.getLength();
+ int nextPartitionPos = eol; // init with line end
+ int validPosition = docOffset;
+
+ try {
+ ITypedRegion partition = TextUtilities.getPartition(document,
+ partitioning, nextPartitionPos, true);
+ validPosition = getValidPositionForPartition(document, partition,
+ eol);
+ while (validPosition == -1) {
+ nextPartitionPos = partition.getOffset() - 1;
+ if (nextPartitionPos < docOffset) {
+ validPosition = docOffset;
+ break;
+ }
+ partition = TextUtilities.getPartition(document, partitioning,
+ nextPartitionPos, false);
+ validPosition = getValidPositionForPartition(document,
+ partition, eol);
+ }
+ } catch (BadLocationException e) {
+ }
+
+ validPosition = Math.max(validPosition, docOffset);
+ // make relative to line
+ validPosition -= line.getOffset();
+ return validPosition;
+ }
+
+ /**
+ * Returns a valid insert location (except for whitespace) in
+ * partition
or -1 if there is no valid insert location. An
+ * valid insert location is right after any java string or character
+ * partition, or at the end of a java default partition, but never behind
+ * maxOffset
. Comment partitions or empty java partitions do
+ * never yield valid insert positions.
+ *
+ * @param doc
+ * the document being modified
+ * @param partition
+ * the current partition
+ * @param maxOffset
+ * the maximum offset to consider
+ * @return a valid insert location in partition
, or -1 if
+ * there is no valid insert location
+ */
+ private static int getValidPositionForPartition(IDocument doc,
+ ITypedRegion partition, int maxOffset) {
+ final int INVALID = -1;
+
+ if (IPHPPartitions.PHP_PHPDOC_COMMENT.equals(partition.getType()))
+ return INVALID;
+ if (IPHPPartitions.PHP_MULTILINE_COMMENT.equals(partition.getType()))
+ return INVALID;
+ if (IPHPPartitions.PHP_SINGLELINE_COMMENT.equals(partition.getType()))
+ return INVALID;
+
+ int endOffset = Math.min(maxOffset, partition.getOffset()
+ + partition.getLength());
+
+ // if (IPHPPartitions.JAVA_CHARACTER.equals(partition.getType()))
+ // return endOffset;
+ if (IPHPPartitions.PHP_STRING_DQ.equals(partition.getType()))
+ return endOffset;
+ if (IPHPPartitions.PHP_STRING_SQ.equals(partition.getType()))
+ return endOffset;
+ if (IPHPPartitions.PHP_STRING_HEREDOC.equals(partition.getType()))
+ return endOffset;
+ if (IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())) {
+ try {
+ if (doc.get(partition.getOffset(),
+ endOffset - partition.getOffset()).trim().length() == 0)
+ return INVALID;
+ else
+ return endOffset;
+ } catch (BadLocationException e) {
+ return INVALID;
+ }
+ }
+ // default: we don't know anything about the partition - assume valid
+ return endOffset;
+ }
+
+ /**
+ * Determines whether the current line contains a for statement. Algorithm:
+ * any "for" word in the line is a positive, "for" contained in a string
+ * literal will produce a false positive.
+ *
+ * @param line
+ * the line where the change is being made
+ * @param offset
+ * the position of the caret
+ * @return true
if line
contains
+ * for
, false
otherwise
+ */
+ private static boolean isForStatement(String line, int offset) {
+ /* searching for (^|\s)for(\s|$) */
+ int forPos = line.indexOf("for"); //$NON-NLS-1$
+ if (forPos != -1) {
+ if ((forPos == 0 || !Scanner.isPHPIdentifierPart(line
+ .charAt(forPos - 1)))
+ && (line.length() == forPos + 3 || !Scanner
+ .isPHPIdentifierPart(line.charAt(forPos + 3))))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the position in text
after which there comes only
+ * whitespace, up to offset
.
+ *
+ * @param text
+ * the text being searched
+ * @param offset
+ * the maximum offset to search for
+ * @return the smallest value v
such that
+ * text.substring(v, offset).trim() == 0
+ */
+ private static int startOfWhitespaceBeforeOffset(String text, int offset) {
+ int i = Math.min(offset, text.length());
+ for (; i >= 1; i--) {
+ if (!Character.isWhitespace(text.charAt(i - 1)))
+ break;
+ }
+ return i;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SubstitutionTextReader.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SubstitutionTextReader.java
new file mode 100644
index 0000000..cc89ebe
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SubstitutionTextReader.java
@@ -0,0 +1,155 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import net.sourceforge.phpdt.internal.corext.phpdoc.SingleCharReader;
+
+/**
+ * Reads the text contents from a reader and computes for each character a
+ * potential substitution. The substitution may eat more characters than only
+ * the one passed into the computation routine.
+ */
+public abstract class SubstitutionTextReader extends SingleCharReader {
+
+ protected static final String LINE_DELIM = System.getProperty(
+ "line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ private Reader fReader;
+
+ private boolean fWasWhiteSpace;
+
+ private int fCharAfterWhiteSpace;
+
+ /**
+ * Tells whether white space characters are skipped.
+ */
+ private boolean fSkipWhiteSpace = true;
+
+ private boolean fReadFromBuffer;
+
+ private StringBuffer fBuffer;
+
+ private int fIndex;
+
+ protected SubstitutionTextReader(Reader reader) {
+ fReader = reader;
+ fBuffer = new StringBuffer();
+ fIndex = 0;
+ fReadFromBuffer = false;
+ fCharAfterWhiteSpace = -1;
+ fWasWhiteSpace = true;
+ }
+
+ /**
+ * Implement to compute the substitution for the given character and if
+ * necessary subsequent characters. Use nextChar
to read
+ * subsequent characters.
+ */
+ protected abstract String computeSubstitution(int c) throws IOException;
+
+ /**
+ * Returns the internal reader.
+ */
+ protected Reader getReader() {
+ return fReader;
+ }
+
+ /**
+ * Returns the next character.
+ */
+ protected int nextChar() throws IOException {
+ fReadFromBuffer = (fBuffer.length() > 0);
+ if (fReadFromBuffer) {
+ char ch = fBuffer.charAt(fIndex++);
+ if (fIndex >= fBuffer.length()) {
+ fBuffer.setLength(0);
+ fIndex = 0;
+ }
+ return ch;
+ } else {
+ int ch = fCharAfterWhiteSpace;
+ if (ch == -1) {
+ ch = fReader.read();
+ }
+ if (fSkipWhiteSpace && Character.isWhitespace((char) ch)) {
+ do {
+ ch = fReader.read();
+ } while (Character.isWhitespace((char) ch));
+ if (ch != -1) {
+ fCharAfterWhiteSpace = ch;
+ return ' ';
+ }
+ } else {
+ fCharAfterWhiteSpace = -1;
+ }
+ return ch;
+ }
+ }
+
+ /**
+ * @see Reader#read()
+ */
+ public int read() throws IOException {
+ int c;
+ do {
+
+ c = nextChar();
+ while (!fReadFromBuffer) {
+ String s = computeSubstitution(c);
+ if (s == null)
+ break;
+ if (s.length() > 0)
+ fBuffer.insert(0, s);
+ c = nextChar();
+ }
+
+ } while (fSkipWhiteSpace && fWasWhiteSpace && (c == ' '));
+ fWasWhiteSpace = (c == ' ' || c == '\r' || c == '\n');
+ return c;
+ }
+
+ /**
+ * @see Reader#ready()
+ */
+ public boolean ready() throws IOException {
+ return fReader.ready();
+ }
+
+ /**
+ * @see Reader#close()
+ */
+ public void close() throws IOException {
+ fReader.close();
+ }
+
+ /**
+ * @see Reader#reset()
+ */
+ public void reset() throws IOException {
+ fReader.reset();
+ fWasWhiteSpace = true;
+ fCharAfterWhiteSpace = -1;
+ fBuffer.setLength(0);
+ fIndex = 0;
+ }
+
+ protected final void setSkipWhitespace(boolean state) {
+ fSkipWhiteSpace = state;
+ }
+
+ protected final boolean isSkippingWhitespace() {
+ return fSkipWhiteSpace;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/Symbols.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/Symbols.java
new file mode 100644
index 0000000..eeba337
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/Symbols.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+/**
+ * Symbols for the heuristic java scanner.
+ *
+ * @since 3.0
+ */
+public interface Symbols {
+ int TokenEOF = -1;
+
+ int TokenLBRACE = 1;
+
+ int TokenRBRACE = 2;
+
+ int TokenLBRACKET = 3;
+
+ int TokenRBRACKET = 4;
+
+ int TokenLPAREN = 5;
+
+ int TokenRPAREN = 6;
+
+ int TokenSEMICOLON = 7;
+
+ int TokenOTHER = 8;
+
+ int TokenCOLON = 9;
+
+ int TokenQUESTIONMARK = 10;
+
+ int TokenCOMMA = 11;
+
+ int TokenEQUAL = 12;
+
+ int TokenIF = 109;
+
+ int TokenDO = 1010;
+
+ int TokenFOR = 1011;
+
+ int TokenTRY = 1012;
+
+ int TokenCASE = 1013;
+
+ int TokenELSE = 1014;
+
+ int TokenBREAK = 1015;
+
+ int TokenCATCH = 1016;
+
+ int TokenWHILE = 1017;
+
+ int TokenRETURN = 1018;
+
+ int TokenSTATIC = 1019;
+
+ int TokenSWITCH = 1020;
+
+ int TokenFINALLY = 1021;
+
+ int TokenSYNCHRONIZED = 1022;
+
+ int TokenGOTO = 1023;
+
+ int TokenDEFAULT = 1024;
+
+ int TokenNEW = 1025;
+
+ int TokenIDENT = 2000;
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java
new file mode 100644
index 0000000..6a2cd02
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+/**
+ * Describes a run of similar typing changes.
+ * DELETE
deletes one single character
+ * (through delete or backspace or empty paste).
+ */
+ public static final ChangeType DELETE = new ChangeType(true, "DELETE"); //$NON-NLS-1$
+
+ /**
+ * A change of type INSERT
inserts one single character
+ * (normal typing).
+ */
+ public static final ChangeType INSERT = new ChangeType(true, "INSERT"); //$NON-NLS-1$
+
+ /**
+ * A change of type NO_CHANGE
does not change anything.
+ */
+ public static final ChangeType NO_CHANGE = new ChangeType(false,
+ "NO_CHANGE"); //$NON-NLS-1$
+
+ /**
+ * A change of type OVERTYPE
replaces one single character
+ * (overwrite mode, pasting a single character).
+ */
+ public static final ChangeType OVERTYPE = new ChangeType(true, "OVERTYPE"); //$NON-NLS-1$
+
+ /**
+ * A change of type SELECTION
does not change text, but
+ * changes the focus, or selection. Such a change ends all typing runs.
+ */
+ public static final ChangeType SELECTION = new ChangeType(false,
+ "SELECTION"); //$NON-NLS-1$
+
+ /**
+ * A change of type UNKNOWN
modifies text in an unspecified
+ * way. An example is pasting more than one character, or deleting an entire
+ * selection, or reverting a file. Such a change ends all typing runs and
+ * cannot form a typing run with any other change, including a change of
+ * type UNKNOWN
.
+ */
+ public static final ChangeType UNKNOWN = new ChangeType(true, "UNKNOWN"); //$NON-NLS-1$
+
+ /**
+ * Enumeration of change types.
+ *
+ * @since 3.0
+ */
+ public static final class ChangeType {
+ private final boolean fIsModification;
+
+ private final String fName;
+
+ /** Private ctor for type safe enumeration. */
+ private ChangeType(boolean isRunPart, String name) {
+ fIsModification = isRunPart;
+ fName = name;
+ }
+
+ /**
+ * Returns true
if changes of this type modify text.
+ *
+ * @return true
if changes of this type modify text,
+ * false
otherwise
+ */
+ boolean isModification() {
+ return fIsModification;
+ }
+
+ /*
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return fName;
+ }
+ }
+
+ /**
+ * Creates a new run.
+ *
+ * @param type
+ * the type of the run
+ */
+ TypingRun(ChangeType type) {
+ this.type = type;
+ }
+
+ /** The change type of this run. */
+ public final ChangeType type;
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java
new file mode 100644
index 0000000..d74a9c3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java
@@ -0,0 +1,491 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.TextEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+
+/**
+ * When connected to a text viewer, a TypingRunDetector
observes
+ * TypingRun
events. A typing run is a sequence of similar text
+ * modifications, such as inserting or deleting single characters.
+ * TypingRun
.
+ * type
.
+ *
+ * @param type
+ * the ChangeType
of the new change
+ * @param nextOffset
+ * the offset of the next change in a typing run
+ */
+ public Change(ChangeType type, int nextOffset) {
+ fType = type;
+ fNextOffset = nextOffset;
+ }
+
+ /**
+ * Returns true
if the receiver can extend the typing
+ * range the last change of which is described by change
.
+ *
+ * @param change
+ * the last change in a typing run
+ * @return true
if the receiver is a valid extension to
+ * change
,false
otherwise
+ */
+ public boolean canFollow(Change change) {
+ if (fType == TypingRun.NO_CHANGE)
+ return true;
+ else if (fType.equals(TypingRun.UNKNOWN))
+ return false;
+ if (fType.equals(change.fType)) {
+ if (fType == TypingRun.DELETE)
+ return fNextOffset == change.fNextOffset - 1;
+ else if (fType == TypingRun.INSERT)
+ return fNextOffset == change.fNextOffset + 1;
+ else if (fType == TypingRun.OVERTYPE)
+ return fNextOffset == change.fNextOffset + 1;
+ else if (fType == TypingRun.SELECTION)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true
if the receiver describes a text
+ * modification, false
if it describes a focus /
+ * selection change.
+ *
+ * @return true
if the receiver is a text modification
+ */
+ public boolean isModification() {
+ return fType.isModification();
+ }
+
+ /*
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return fType.toString() + "@" + fNextOffset; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the change type of this change.
+ *
+ * @return the change type of this change
+ */
+ public ChangeType getType() {
+ return fType;
+ }
+ }
+
+ /**
+ * Observes any events that modify the content of the document displayed in
+ * the editor. Since text events may start a new run, this listener is
+ * always registered if the detector is connected.
+ */
+ private class TextListener implements ITextListener {
+
+ /*
+ * @see org.eclipse.jface.text.ITextListener#textChanged(org.eclipse.jface.text.TextEvent)
+ */
+ public void textChanged(TextEvent event) {
+ handleTextChanged(event);
+ }
+ }
+
+ /**
+ * Observes non-modifying events that will end a run, such as clicking into
+ * the editor, moving the caret, and the editor losing focus. These events
+ * can never start a run, therefore this listener is only registered if
+ * there is an ongoing run.
+ */
+ private class SelectionListener implements MouseListener, KeyListener,
+ FocusListener {
+
+ /*
+ * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
+ */
+ public void focusGained(FocusEvent e) {
+ handleSelectionChanged();
+ }
+
+ /*
+ * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+ */
+ public void focusLost(FocusEvent e) {
+ }
+
+ /*
+ * @see MouseListener#mouseDoubleClick
+ */
+ public void mouseDoubleClick(MouseEvent e) {
+ }
+
+ /*
+ * If the right mouse button is pressed, the current editing command is
+ * closed
+ *
+ * @see MouseListener#mouseDown
+ */
+ public void mouseDown(MouseEvent e) {
+ if (e.button == 1)
+ handleSelectionChanged();
+ }
+
+ /*
+ * @see MouseListener#mouseUp
+ */
+ public void mouseUp(MouseEvent e) {
+ }
+
+ /*
+ * @see KeyListener#keyPressed
+ */
+ public void keyReleased(KeyEvent e) {
+ }
+
+ /*
+ * On cursor keys, the current editing command is closed
+ *
+ * @see KeyListener#keyPressed
+ */
+ public void keyPressed(KeyEvent e) {
+ switch (e.keyCode) {
+ case SWT.ARROW_UP:
+ case SWT.ARROW_DOWN:
+ case SWT.ARROW_LEFT:
+ case SWT.ARROW_RIGHT:
+ case SWT.END:
+ case SWT.HOME:
+ case SWT.PAGE_DOWN:
+ case SWT.PAGE_UP:
+ handleSelectionChanged();
+ break;
+ }
+ }
+ }
+
+ /** The listeners. */
+ private final Set fListeners = new HashSet();
+
+ /**
+ * The viewer we work upon. Set to null
in
+ * uninstall
.
+ */
+ private ITextViewer fViewer;
+
+ /** The text event listener. */
+ private final TextListener fTextListener = new TextListener();
+
+ /**
+ * The selection listener. Set to null
when no run is active.
+ */
+ private SelectionListener fSelectionListener;
+
+ /* state variables */
+
+ /** The most recently observed change. Never null
. */
+ private Change fLastChange;
+
+ /** The current run, or null
if there is none. */
+ private TypingRun fRun;
+
+ /**
+ * Installs the receiver with a text viewer.
+ *
+ * @param viewer
+ * the viewer to install on
+ */
+ public void install(ITextViewer viewer) {
+ Assert.isLegal(viewer != null);
+ fViewer = viewer;
+ connect();
+ }
+
+ /**
+ * Initializes the state variables and registers any permanent listeners.
+ */
+ private void connect() {
+ if (fViewer != null) {
+ fLastChange = new Change(TypingRun.UNKNOWN, -1);
+ fRun = null;
+ fSelectionListener = null;
+ fViewer.addTextListener(fTextListener);
+ }
+ }
+
+ /**
+ * Uninstalls the receiver and removes all listeners. install()
+ * must be called for events to be generated.
+ */
+ public void uninstall() {
+ if (fViewer != null) {
+ fListeners.clear();
+ disconnect();
+ fViewer = null;
+ }
+ }
+
+ /**
+ * Disconnects any registered listeners.
+ */
+ private void disconnect() {
+ fViewer.removeTextListener(fTextListener);
+ ensureSelectionListenerRemoved();
+ }
+
+ /**
+ * Adds a listener for TypingRun
events. Repeatedly adding
+ * the same listener instance has no effect. Listeners may be added even if
+ * the receiver is neither connected nor installed.
+ *
+ * @param listener
+ * the listener add
+ */
+ public void addTypingRunListener(ITypingRunListener listener) {
+ Assert.isLegal(listener != null);
+ fListeners.add(listener);
+ if (fListeners.size() == 1)
+ connect();
+ }
+
+ /**
+ * Removes the listener from this manager. If listener
is not
+ * registered with the receiver, nothing happens.
+ *
+ * @param listener
+ * the listener to remove, or null
+ */
+ public void removeTypingRunListener(ITypingRunListener listener) {
+ fListeners.remove(listener);
+ if (fListeners.size() == 0)
+ disconnect();
+ }
+
+ /**
+ * Handles an incoming text event.
+ *
+ * @param event
+ * the text event that describes the text modification
+ */
+ void handleTextChanged(TextEvent event) {
+ Change type = computeChange(event);
+ handleChange(type);
+ }
+
+ /**
+ * Computes the change abstraction given a text event.
+ *
+ * @param event
+ * the text event to analyze
+ * @return a change object describing the event
+ */
+ private Change computeChange(TextEvent event) {
+ DocumentEvent e = event.getDocumentEvent();
+ if (e == null)
+ return new Change(TypingRun.NO_CHANGE, -1);
+
+ int start = e.getOffset();
+ int end = e.getOffset() + e.getLength();
+ String newText = e.getText();
+ if (newText == null)
+ newText = new String();
+
+ if (start == end) {
+ // no replace / delete / overwrite
+ if (newText.length() == 1)
+ return new Change(TypingRun.INSERT, end + 1);
+ } else if (start == end - 1) {
+ if (newText.length() == 1)
+ return new Change(TypingRun.OVERTYPE, end);
+ if (newText.length() == 0)
+ return new Change(TypingRun.DELETE, start);
+ }
+
+ return new Change(TypingRun.UNKNOWN, -1);
+ }
+
+ /**
+ * Handles an incoming selection event.
+ */
+ void handleSelectionChanged() {
+ handleChange(new Change(TypingRun.SELECTION, -1));
+ }
+
+ /**
+ * State machine. Changes state given the current state and the incoming
+ * change.
+ *
+ * @param change
+ * the incoming change
+ */
+ private void handleChange(Change change) {
+ if (change.getType() == TypingRun.NO_CHANGE)
+ return;
+
+ if (DEBUG)
+ System.err.println("Last change: " + fLastChange); //$NON-NLS-1$
+
+ if (!change.canFollow(fLastChange))
+ endIfStarted(change);
+ fLastChange = change;
+ if (change.isModification())
+ startOrContinue();
+
+ if (DEBUG)
+ System.err.println("New change: " + change); //$NON-NLS-1$
+ }
+
+ /**
+ * Starts a new run if there is none and informs all listeners. If there
+ * already is a run, nothing happens.
+ */
+ private void startOrContinue() {
+ if (!hasRun()) {
+ if (DEBUG)
+ System.err.println("+Start run"); //$NON-NLS-1$
+ fRun = new TypingRun(fLastChange.getType());
+ ensureSelectionListenerAdded();
+ fireRunBegun(fRun);
+ }
+ }
+
+ /**
+ * Returns true
if there is an active run, false
+ * otherwise.
+ *
+ * @return true
if there is an active run, false
+ * otherwise
+ */
+ private boolean hasRun() {
+ return fRun != null;
+ }
+
+ /**
+ * Ends any active run and informs all listeners. If there is none, nothing
+ * happens.
+ *
+ * @param change
+ * the change that triggered ending the active run
+ */
+ private void endIfStarted(Change change) {
+ if (hasRun()) {
+ ensureSelectionListenerRemoved();
+ if (DEBUG)
+ System.err.println("-End run"); //$NON-NLS-1$
+ fireRunEnded(fRun, change.getType());
+ fRun = null;
+ }
+ }
+
+ /**
+ * Adds the selection listener to the text widget underlying the viewer, if
+ * not already done.
+ */
+ private void ensureSelectionListenerAdded() {
+ if (fSelectionListener == null) {
+ fSelectionListener = new SelectionListener();
+ StyledText textWidget = fViewer.getTextWidget();
+ textWidget.addFocusListener(fSelectionListener);
+ textWidget.addKeyListener(fSelectionListener);
+ textWidget.addMouseListener(fSelectionListener);
+ }
+ }
+
+ /**
+ * If there is a selection listener, it is removed from the text widget
+ * underlying the viewer.
+ */
+ private void ensureSelectionListenerRemoved() {
+ if (fSelectionListener != null) {
+ StyledText textWidget = fViewer.getTextWidget();
+ textWidget.removeFocusListener(fSelectionListener);
+ textWidget.removeKeyListener(fSelectionListener);
+ textWidget.removeMouseListener(fSelectionListener);
+ fSelectionListener = null;
+ }
+ }
+
+ /**
+ * Informs all listeners about a newly started TypingRun
.
+ *
+ * @param run
+ * the new run
+ */
+ private void fireRunBegun(TypingRun run) {
+ List listeners = new ArrayList(fListeners);
+ for (Iterator it = listeners.iterator(); it.hasNext();) {
+ ITypingRunListener listener = (ITypingRunListener) it.next();
+ listener.typingRunStarted(fRun);
+ }
+ }
+
+ /**
+ * Informs all listeners about an ended TypingRun
.
+ *
+ * @param run
+ * the previously active run
+ * @param reason
+ * the type of change that caused the run to be ended
+ */
+ private void fireRunEnded(TypingRun run, ChangeType reason) {
+ List listeners = new ArrayList(fListeners);
+ for (Iterator it = listeners.iterator(); it.hasNext();) {
+ ITypingRunListener listener = (ITypingRunListener) it.next();
+ listener.typingRunEnded(fRun, reason);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/comment/CommentFormattingContext.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/comment/CommentFormattingContext.java
new file mode 100644
index 0000000..127f285
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/comment/CommentFormattingContext.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.comment;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.text.formatter.FormattingContext;
+
+/**
+ * Formatting context for the comment formatter.
+ *
+ * @since 3.0
+ */
+public class CommentFormattingContext extends FormattingContext {
+
+ /*
+ * @see org.eclipse.jface.text.formatter.IFormattingContext#getPreferenceKeys()
+ */
+ public String[] getPreferenceKeys() {
+ return new String[] {
+ PreferenceConstants.FORMATTER_COMMENT_FORMAT,
+ PreferenceConstants.FORMATTER_COMMENT_FORMATHEADER,
+ PreferenceConstants.FORMATTER_COMMENT_FORMATSOURCE,
+ PreferenceConstants.FORMATTER_COMMENT_INDENTPARAMETERDESCRIPTION,
+ PreferenceConstants.FORMATTER_COMMENT_INDENTROOTTAGS,
+ PreferenceConstants.FORMATTER_COMMENT_NEWLINEFORPARAMETER,
+ PreferenceConstants.FORMATTER_COMMENT_SEPARATEROOTTAGS,
+ PreferenceConstants.FORMATTER_COMMENT_LINELENGTH,
+ PreferenceConstants.FORMATTER_COMMENT_CLEARBLANKLINES,
+ PreferenceConstants.FORMATTER_COMMENT_FORMATHTML };
+ }
+
+ /*
+ * @see org.eclipse.jface.text.formatter.IFormattingContext#isBooleanPreference(java.lang.String)
+ */
+ public boolean isBooleanPreference(String key) {
+ return !key.equals(PreferenceConstants.FORMATTER_COMMENT_LINELENGTH);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.formatter.IFormattingContext#isIntegerPreference(java.lang.String)
+ */
+ public boolean isIntegerPreference(String key) {
+ return key.equals(PreferenceConstants.FORMATTER_COMMENT_LINELENGTH);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingPreferenceBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingPreferenceBlock.java
new file mode 100644
index 0000000..42d14eb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingPreferenceBlock.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.folding;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.preferences.OverlayPreferenceStore;
+import net.sourceforge.phpdt.internal.ui.preferences.OverlayPreferenceStore.OverlayKey;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingPreferenceBlock;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+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.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Java default folding preferences.
+ *
+ * @since 3.0
+ */
+public class DefaultJavaFoldingPreferenceBlock implements
+ IJavaFoldingPreferenceBlock {
+
+ private IPreferenceStore fStore;
+
+ private OverlayPreferenceStore fOverlayStore;
+
+ private OverlayKey[] fKeys;
+
+ private Map fCheckBoxes = new HashMap();
+
+ private SelectionListener fCheckBoxListener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ Button button = (Button) e.widget;
+ fOverlayStore.setValue((String) fCheckBoxes.get(button), button
+ .getSelection());
+ }
+ };
+
+ public DefaultJavaFoldingPreferenceBlock() {
+ fStore = WebUI.getDefault().getPreferenceStore();
+ fKeys = createKeys();
+ fOverlayStore = new OverlayPreferenceStore(fStore, fKeys);
+ }
+
+ private OverlayKey[] createKeys() {
+ ArrayList overlayKeys = new ArrayList();
+
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_FOLDING_JAVADOC));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_FOLDING_HEADERS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_FOLDING_INNERTYPES));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(
+ OverlayPreferenceStore.BOOLEAN,
+ PreferenceConstants.EDITOR_FOLDING_METHODS));
+ // overlayKeys.add(new
+ // OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
+ // PreferenceConstants.EDITOR_FOLDING_IMPORTS));
+
+ return (OverlayKey[]) overlayKeys.toArray(new OverlayKey[overlayKeys
+ .size()]);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.IJavaFoldingPreferences#createControl(org.eclipse.swt.widgets.Group)
+ */
+ public Control createControl(Composite composite) {
+ fOverlayStore.load();
+ fOverlayStore.start();
+
+ Composite inner = new Composite(composite, SWT.NONE);
+ GridLayout layout = new GridLayout(1, true);
+ layout.verticalSpacing = 3;
+ layout.marginWidth = 0;
+ inner.setLayout(layout);
+
+ Label label = new Label(inner, SWT.LEFT);
+ label.setText(FoldingMessages
+ .getString("DefaultJavaFoldingPreferenceBlock.title")); //$NON-NLS-1$
+
+ addCheckBox(
+ inner,
+ FoldingMessages
+ .getString("DefaultJavaFoldingPreferenceBlock.comments"), PreferenceConstants.EDITOR_FOLDING_JAVADOC, 0); //$NON-NLS-1$
+ addCheckBox(
+ inner,
+ FoldingMessages
+ .getString("DefaultJavaFoldingPreferenceBlock.headers"), PreferenceConstants.EDITOR_FOLDING_HEADERS, 0);//$NON-NLS-1$
+ addCheckBox(inner, FoldingMessages
+ .getString("DefaultJavaFoldingPreferenceBlock.innerTypes"),
+ PreferenceConstants.EDITOR_FOLDING_INNERTYPES, 0); //$NON-NLS-1$
+ addCheckBox(
+ inner,
+ FoldingMessages
+ .getString("DefaultJavaFoldingPreferenceBlock.methods"), PreferenceConstants.EDITOR_FOLDING_METHODS, 0); //$NON-NLS-1$
+ // addCheckBox(inner,
+ // FoldingMessages.getString("DefaultJavaFoldingPreferenceBlock.imports"),
+ // PreferenceConstants.EDITOR_FOLDING_IMPORTS, 0); //$NON-NLS-1$
+
+ return inner;
+ }
+
+ private Button addCheckBox(Composite parent, String label, String key,
+ int indentation) {
+ Button checkBox = new Button(parent, SWT.CHECK);
+ checkBox.setText(label);
+
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ gd.horizontalSpan = 1;
+ gd.grabExcessVerticalSpace = false;
+ checkBox.setLayoutData(gd);
+ checkBox.addSelectionListener(fCheckBoxListener);
+
+ fCheckBoxes.put(checkBox, key);
+
+ return checkBox;
+ }
+
+ private void initializeFields() {
+ Iterator it = fCheckBoxes.keySet().iterator();
+ while (it.hasNext()) {
+ Button b = (Button) it.next();
+ String key = (String) fCheckBoxes.get(b);
+ b.setSelection(fOverlayStore.getBoolean(key));
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.AbstractJavaFoldingPreferences#performOk()
+ */
+ public void performOk() {
+ fOverlayStore.propagate();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.AbstractJavaFoldingPreferences#initialize()
+ */
+ public void initialize() {
+ initializeFields();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.AbstractJavaFoldingPreferences#performDefaults()
+ */
+ public void performDefaults() {
+ fOverlayStore.loadDefaults();
+ initializeFields();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.AbstractJavaFoldingPreferences#dispose()
+ */
+ public void dispose() {
+ fOverlayStore.stop();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java
new file mode 100644
index 0000000..30efcd2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java
@@ -0,0 +1,1062 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.folding;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.ElementChangedEvent;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IElementChangedListener;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaElementDelta;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.ToolFactory;
+import net.sourceforge.phpdt.core.compiler.IScanner;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.projection.IProjectionListener;
+import org.eclipse.jface.text.source.projection.IProjectionPosition;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Updates the projection model of a class file or compilation unit.
+ *
+ * @since 3.0
+ */
+public class DefaultJavaFoldingStructureProvider implements
+ IProjectionListener, IJavaFoldingStructureProvider {
+
+ private static class JavaProjectionAnnotation extends ProjectionAnnotation {
+
+ private IJavaElement fJavaElement;
+
+ private boolean fIsComment;
+
+ public JavaProjectionAnnotation(IJavaElement element,
+ boolean isCollapsed, boolean isComment) {
+ super(isCollapsed);
+ fJavaElement = element;
+ fIsComment = isComment;
+ }
+
+ public IJavaElement getElement() {
+ return fJavaElement;
+ }
+
+ public void setElement(IJavaElement element) {
+ fJavaElement = element;
+ }
+
+ public boolean isComment() {
+ return fIsComment;
+ }
+
+ public void setIsComment(boolean isComment) {
+ fIsComment = isComment;
+ }
+
+ /*
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "JavaProjectionAnnotation:\n" + //$NON-NLS-1$
+ "\telement: \t" + fJavaElement.toString() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
+ "\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
+ "\tcomment: \t" + fIsComment + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ private static final class Tuple {
+ JavaProjectionAnnotation annotation;
+
+ Position position;
+
+ Tuple(JavaProjectionAnnotation annotation, Position position) {
+ this.annotation = annotation;
+ this.position = position;
+ }
+ }
+
+ private class ElementChangedListener implements IElementChangedListener {
+
+ /*
+ * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
+ */
+ public void elementChanged(ElementChangedEvent e) {
+ IJavaElementDelta delta = findElement(fInput, e.getDelta());
+ if (delta != null)
+ processDelta(delta);
+ }
+
+ private IJavaElementDelta findElement(IJavaElement target,
+ IJavaElementDelta delta) {
+
+ if (delta == null || target == null)
+ return null;
+
+ IJavaElement element = delta.getElement();
+
+ if (element.getElementType() > IJavaElement.CLASS_FILE)
+ return null;
+
+ if (target.equals(element))
+ return delta;
+
+ IJavaElementDelta[] children = delta.getAffectedChildren();
+
+ for (int i = 0; i < children.length; i++) {
+ IJavaElementDelta d = findElement(target, children[i]);
+ if (d != null)
+ return d;
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Projection position that will return two foldable regions: one folding
+ * away the region from after the '/**' to the beginning of the content, the
+ * other from after the first content line until after the comment.
+ *
+ * @since 3.1
+ */
+ private static final class CommentPosition extends Position implements
+ IProjectionPosition {
+ CommentPosition(int offset, int length) {
+ super(offset, length);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
+ */
+ public IRegion[] computeProjectionRegions(IDocument document)
+ throws BadLocationException {
+ DocumentCharacterIterator sequence = new DocumentCharacterIterator(
+ document, offset, offset + length);
+ int prefixEnd = 0;
+ int contentStart = findFirstContent(sequence, prefixEnd);
+
+ int firstLine = document.getLineOfOffset(offset + prefixEnd);
+ int captionLine = document.getLineOfOffset(offset + contentStart);
+ int lastLine = document.getLineOfOffset(offset + length);
+
+ Assert.isTrue(firstLine <= captionLine,
+ "first folded line is greater than the caption line"); //$NON-NLS-1$
+ Assert.isTrue(captionLine <= lastLine,
+ "caption line is greater than the last folded line"); //$NON-NLS-1$
+
+ IRegion preRegion;
+ if (firstLine < captionLine) {
+ // preRegion= new Region(offset + prefixEnd, contentStart -
+ // prefixEnd);
+ int preOffset = document.getLineOffset(firstLine);
+ IRegion preEndLineInfo = document
+ .getLineInformation(captionLine);
+ int preEnd = preEndLineInfo.getOffset();
+ preRegion = new Region(preOffset, preEnd - preOffset);
+ } else {
+ preRegion = null;
+ }
+
+ if (captionLine < lastLine) {
+ int postOffset = document.getLineOffset(captionLine + 1);
+ IRegion postRegion = new Region(postOffset, offset + length
+ - postOffset);
+
+ if (preRegion == null)
+ return new IRegion[] { postRegion };
+
+ return new IRegion[] { preRegion, postRegion };
+ }
+
+ if (preRegion != null)
+ return new IRegion[] { preRegion };
+
+ return null;
+ }
+
+ /**
+ * Finds the offset of the first identifier part within
+ * content
. Returns 0 if none is found.
+ *
+ * @param content
+ * the content to search
+ * @return the first index of a unicode identifier part, or zero if none
+ * can be found
+ */
+ private int findFirstContent(final CharSequence content, int prefixEnd) {
+ int lenght = content.length();
+ for (int i = prefixEnd; i < lenght; i++) {
+ if (Character.isUnicodeIdentifierPart(content.charAt(i)))
+ return i;
+ }
+ return 0;
+ }
+
+ // /**
+ // * Finds the offset of the first identifier part within
+ // content
.
+ // * Returns 0 if none is found.
+ // *
+ // * @param content the content to search
+ // * @return the first index of a unicode identifier part, or zero if
+ // none
+ // can
+ // * be found
+ // */
+ // private int findPrefixEnd(final CharSequence content) {
+ // // return the index after the leading '/*' or '/**'
+ // int len= content.length();
+ // int i= 0;
+ // while (i < len && isWhiteSpace(content.charAt(i)))
+ // i++;
+ // if (len >= i + 2 && content.charAt(i) == '/' && content.charAt(i + 1)
+ // ==
+ // '*')
+ // if (len >= i + 3 && content.charAt(i + 2) == '*')
+ // return i + 3;
+ // else
+ // return i + 2;
+ // else
+ // return i;
+ // }
+ //
+ // private boolean isWhiteSpace(char c) {
+ // return c == ' ' || c == '\t';
+ // }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
+ */
+ public int computeCaptionOffset(IDocument document) {
+ // return 0;
+ DocumentCharacterIterator sequence = new DocumentCharacterIterator(
+ document, offset, offset + length);
+ return findFirstContent(sequence, 0);
+ }
+ }
+
+ /**
+ * Projection position that will return two foldable regions: one folding
+ * away the lines before the one containing the simple name of the java
+ * element, one folding away any lines after the caption.
+ *
+ * @since 3.1
+ */
+ private static final class JavaElementPosition extends Position implements
+ IProjectionPosition {
+
+ private IMember fMember;
+
+ public JavaElementPosition(int offset, int length, IMember member) {
+ super(offset, length);
+ Assert.isNotNull(member);
+ fMember = member;
+ }
+
+ public void setMember(IMember member) {
+ Assert.isNotNull(member);
+ fMember = member;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
+ */
+ public IRegion[] computeProjectionRegions(IDocument document)
+ throws BadLocationException {
+ int nameStart = offset;
+ try {
+ /*
+ * The member's name range may not be correct. However,
+ * reconciling would trigger another element delta which would
+ * lead to reentrant situations. Therefore, we optimistically
+ * assume that the name range is correct, but double check the
+ * received lines below.
+ */
+ ISourceRange nameRange = fMember.getNameRange();
+ if (nameRange != null)
+ nameStart = nameRange.getOffset();
+
+ } catch (JavaModelException e) {
+ // ignore and use default
+ }
+
+ int firstLine = document.getLineOfOffset(offset);
+ int captionLine = document.getLineOfOffset(nameStart);
+ int lastLine = document.getLineOfOffset(offset + length);
+
+ /*
+ * see comment above - adjust the caption line to be inside the
+ * entire folded region, and rely on later element deltas to correct
+ * the name range.
+ */
+ if (captionLine < firstLine)
+ captionLine = firstLine;
+ if (captionLine > lastLine)
+ captionLine = lastLine;
+
+ IRegion preRegion;
+ if (firstLine < captionLine) {
+ int preOffset = document.getLineOffset(firstLine);
+ IRegion preEndLineInfo = document
+ .getLineInformation(captionLine);
+ int preEnd = preEndLineInfo.getOffset();
+ preRegion = new Region(preOffset, preEnd - preOffset);
+ } else {
+ preRegion = null;
+ }
+
+ if (captionLine < lastLine) {
+ int postOffset = document.getLineOffset(captionLine + 1);
+ IRegion postRegion = new Region(postOffset, offset + length
+ - postOffset);
+
+ if (preRegion == null)
+ return new IRegion[] { postRegion };
+
+ return new IRegion[] { preRegion, postRegion };
+ }
+
+ if (preRegion != null)
+ return new IRegion[] { preRegion };
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
+ */
+ public int computeCaptionOffset(IDocument document)
+ throws BadLocationException {
+ int nameStart = offset;
+ try {
+ // need a reconcile here?
+ ISourceRange nameRange = fMember.getNameRange();
+ if (nameRange != null)
+ nameStart = nameRange.getOffset();
+ } catch (JavaModelException e) {
+ // ignore and use default
+ }
+
+ return nameStart - offset;
+ }
+
+ }
+
+ private IDocument fCachedDocument;
+
+ private ProjectionAnnotationModel fCachedModel;
+
+ private ITextEditor fEditor;
+
+ private ProjectionViewer fViewer;
+
+ private IJavaElement fInput;
+
+ private IElementChangedListener fElementListener;
+
+ private boolean fAllowCollapsing = false;
+
+ private boolean fCollapseJavadoc = false;
+
+ // private boolean fCollapseImportContainer = true;
+
+ private boolean fCollapseInnerTypes = true;
+
+ private boolean fCollapseMethods = false;
+
+ private boolean fCollapseHeaderComments = true;
+
+ /* caches for header comment extraction. */
+ private IType fFirstType;
+
+ private boolean fHasHeaderComment;
+
+ public DefaultJavaFoldingStructureProvider() {
+ }
+
+ public void install(ITextEditor editor, ProjectionViewer viewer) {
+ if (editor instanceof PHPEditor) {
+ fEditor = editor;
+ fViewer = viewer;
+ fViewer.addProjectionListener(this);
+ }
+ }
+
+ public void uninstall() {
+ if (isInstalled()) {
+ projectionDisabled();
+ fViewer.removeProjectionListener(this);
+ fViewer = null;
+ fEditor = null;
+ }
+ }
+
+ protected boolean isInstalled() {
+ return fEditor != null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled()
+ */
+ public void projectionEnabled() {
+ // http://home.ott.oti.com/teams/wswb/anon/out/vms/index.html
+ // projectionEnabled messages are not always paired with
+ // projectionDisabled
+ // i.e. multiple enabled messages may be sent out.
+ // we have to make sure that we disable first when getting an enable
+ // message.
+ projectionDisabled();
+
+ if (fEditor instanceof PHPEditor) {
+ initialize();
+ fElementListener = new ElementChangedListener();
+ JavaCore.addElementChangedListener(fElementListener);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionDisabled()
+ */
+ public void projectionDisabled() {
+ fCachedDocument = null;
+ if (fElementListener != null) {
+ JavaCore.removeElementChangedListener(fElementListener);
+ fElementListener = null;
+ }
+ }
+
+ public void initialize() {
+
+ if (!isInstalled())
+ return;
+
+ initializePreferences();
+
+ try {
+
+ IDocumentProvider provider = fEditor.getDocumentProvider();
+ fCachedDocument = provider.getDocument(fEditor.getEditorInput());
+ fAllowCollapsing = true;
+
+ fFirstType = null;
+ fHasHeaderComment = false;
+
+ if (fEditor instanceof PHPUnitEditor) {
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ fInput = manager.getWorkingCopy(fEditor.getEditorInput());
+ }
+ // else if (fEditor instanceof ClassFileEditor) {
+ // IClassFileEditorInput editorInput= (IClassFileEditorInput)
+ // fEditor.getEditorInput();
+ // fInput= editorInput.getClassFile();
+ // }
+
+ if (fInput != null) {
+ ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor
+ .getAdapter(ProjectionAnnotationModel.class);
+ if (model != null) {
+ fCachedModel = model;
+ if (fInput instanceof ICompilationUnit) {
+ ICompilationUnit unit = (ICompilationUnit) fInput;
+ synchronized (unit) {
+ try {
+ // unit.reconcile(ICompilationUnit.NO_AST,
+ // false, null, null);
+ unit.reconcile();
+ } catch (JavaModelException x) {
+ }
+ }
+ }
+
+ Map additions = computeAdditions((IParent) fInput);
+ /*
+ * Minimize the events being sent out - as this happens in
+ * the UI thread merge everything into one call.
+ */
+ List removals = new LinkedList();
+ Iterator existing = model.getAnnotationIterator();
+ while (existing.hasNext())
+ removals.add(existing.next());
+ model.replaceAnnotations((Annotation[]) removals
+ .toArray(new Annotation[removals.size()]),
+ additions);
+ }
+ }
+
+ } finally {
+ fCachedDocument = null;
+ fCachedModel = null;
+ fAllowCollapsing = false;
+
+ fFirstType = null;
+ fHasHeaderComment = false;
+ }
+ }
+
+ private void initializePreferences() {
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ fCollapseInnerTypes = store
+ .getBoolean(PreferenceConstants.EDITOR_FOLDING_INNERTYPES);
+ // fCollapseImportContainer =
+ // store.getBoolean(PreferenceConstants.EDITOR_FOLDING_IMPORTS);
+ fCollapseJavadoc = store
+ .getBoolean(PreferenceConstants.EDITOR_FOLDING_JAVADOC);
+ fCollapseMethods = store
+ .getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS);
+ fCollapseHeaderComments = store
+ .getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS);
+ }
+
+ private Map computeAdditions(IParent parent) {
+ Map map = new LinkedHashMap(); // use a linked map to maintain ordering
+ // of
+ // comments
+ try {
+ computeAdditions(parent.getChildren(), map);
+ } catch (JavaModelException x) {
+ }
+ return map;
+ }
+
+ private void computeAdditions(IJavaElement[] elements, Map map)
+ throws JavaModelException {
+ for (int i = 0; i < elements.length; i++) {
+ IJavaElement element = elements[i];
+
+ computeAdditions(element, map);
+
+ if (element instanceof IParent) {
+ IParent parent = (IParent) element;
+ computeAdditions(parent.getChildren(), map);
+ }
+ }
+ }
+
+ private void computeAdditions(IJavaElement element, Map map) {
+
+ boolean createProjection = false;
+
+ boolean collapse = false;
+ switch (element.getElementType()) {
+
+ // case IJavaElement.IMPORT_CONTAINER:
+ // collapse = fAllowCollapsing && fCollapseImportContainer;
+ // createProjection = true;
+ // break;
+ case IJavaElement.TYPE:
+ collapse = fAllowCollapsing;
+ if (isInnerType((IType) element)) {
+ collapse = collapse && fCollapseInnerTypes;
+ } else {
+ collapse = false; // don't allow the most outer type to be
+ // folded, may be changed in future versions
+ }
+ createProjection = true;
+ break;
+ case IJavaElement.METHOD:
+ collapse = fAllowCollapsing && fCollapseMethods;
+ createProjection = true;
+ break;
+ }
+
+ if (createProjection) {
+ IRegion[] regions = computeProjectionRanges(element);
+ if (regions != null) {
+ // comments
+ for (int i = 0; i < regions.length - 1; i++) {
+ Position position = createProjectionPosition(regions[i],
+ null);
+ boolean commentCollapse;
+ if (position != null) {
+ if (i == 0 && (regions.length > 2 || fHasHeaderComment)
+ && element == fFirstType) {
+ commentCollapse = fAllowCollapsing
+ && fCollapseHeaderComments;
+ } else {
+ commentCollapse = fAllowCollapsing
+ && fCollapseJavadoc;
+ }
+ map.put(new JavaProjectionAnnotation(element,
+ commentCollapse, true), position);
+ }
+ }
+ // code
+ Position position = createProjectionPosition(
+ regions[regions.length - 1], element);
+ if (position != null)
+ map.put(new JavaProjectionAnnotation(element, collapse,
+ false), position);
+ }
+ }
+ }
+
+ private boolean isInnerType(IType type) {
+
+ try {
+ return type.isMember();
+ } catch (JavaModelException x) {
+ IJavaElement parent = type.getParent();
+ if (parent != null) {
+ int parentType = parent.getElementType();
+ return (parentType != IJavaElement.COMPILATION_UNIT && parentType != IJavaElement.CLASS_FILE);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Computes the projection ranges for a given IJavaElement
.
+ * More than one range may be returned if the element has a leading comment
+ * which gets folded separately. If there are no foldable regions,
+ * null
is returned.
+ *
+ * @param element
+ * the java element that can be folded
+ * @return the regions to be folded, or null
if there are
+ * none
+ */
+ private IRegion[] computeProjectionRanges(IJavaElement element) {
+
+ try {
+ if (element instanceof ISourceReference) {
+ ISourceReference reference = (ISourceReference) element;
+ ISourceRange range = reference.getSourceRange();
+
+ String contents = reference.getSource();
+ if (contents == null)
+ return null;
+
+ List regions = new ArrayList();
+ // now add all comments first to the regions list
+ if (fFirstType == null && element instanceof IType) {
+ fFirstType = (IType) element;
+ IRegion headerComment = computeHeaderComment(fFirstType);
+ if (headerComment != null) {
+ regions.add(headerComment);
+ fHasHeaderComment = true;
+ }
+ }
+
+ final int shift = range.getOffset();
+ int start = shift;
+ if (element instanceof IType) {
+ Scanner scanner = ToolFactory.createScanner(true, false,
+ false, false);
+ scanner.setSource(contents.toCharArray());
+ scanner.setPHPMode(true);
+
+ int token = scanner.getNextToken();
+ while (token != ITerminalSymbols.TokenNameEOF) {
+
+ token = scanner.getNextToken();
+ start = shift + scanner.getCurrentTokenStartPosition();
+
+ switch (token) {
+ case ITerminalSymbols.TokenNameCOMMENT_PHPDOC:
+ case ITerminalSymbols.TokenNameCOMMENT_BLOCK: {
+ int end = shift
+ + scanner.getCurrentTokenEndPosition() + 1;
+ regions.add(new Region(start, end - start));
+ }
+ case ITerminalSymbols.TokenNameCOMMENT_LINE:
+ continue;
+ }
+ }
+ }
+ // at the end add the element region
+ regions.add(new Region(range.getOffset(), range.getLength()));
+
+ if (regions.size() > 0) {
+ IRegion[] result = new IRegion[regions.size()];
+ regions.toArray(result);
+ return result;
+ }
+
+ }
+ } catch (JavaModelException e) {
+ } catch (InvalidInputException e) {
+ }
+
+ return null;
+ }
+
+ private IRegion computeHeaderComment(IType type) throws JavaModelException {
+ if (fCachedDocument == null)
+ return null;
+
+ // search at most up to the first type
+ ISourceRange range = type.getSourceRange();
+ if (range == null)
+ return null;
+ int start = 0;
+ int end = range.getOffset();
+
+ if (fInput instanceof ISourceReference) {
+ String content;
+ try {
+ content = fCachedDocument.get(start, end - start);
+ } catch (BadLocationException e) {
+ return null; // ignore header comment in that case
+ }
+
+ /*
+ * code adapted from CommentFormattingStrategy: scan the header
+ * content up to the first type. Once a comment is found, accumulate
+ * any additional comments up to the stop condition. The stop
+ * condition is reaching a package declaration, import container, or
+ * the end of the input.
+ */
+ IScanner scanner = ToolFactory.createScanner(true, false, false,
+ false);
+ scanner.setSource(content.toCharArray());
+
+ int headerStart = -1;
+ int headerEnd = -1;
+ try {
+ boolean foundComment = false;
+ int terminal = scanner.getNextToken();
+ while (terminal != ITerminalSymbols.TokenNameEOF
+ && !(terminal == ITerminalSymbols.TokenNameclass
+ || terminal == ITerminalSymbols.TokenNameinterface || foundComment)) {
+
+ if (terminal == ITerminalSymbols.TokenNameCOMMENT_PHPDOC
+ || terminal == ITerminalSymbols.TokenNameCOMMENT_BLOCK
+ || terminal == ITerminalSymbols.TokenNameCOMMENT_LINE) {
+ if (!foundComment)
+ headerStart = scanner
+ .getCurrentTokenStartPosition();
+ headerEnd = scanner.getCurrentTokenEndPosition();
+ foundComment = true;
+ }
+ terminal = scanner.getNextToken();
+ }
+
+ } catch (InvalidInputException ex) {
+ return null;
+ }
+
+ if (headerEnd != -1) {
+ return new Region(headerStart, headerEnd - headerStart);
+ }
+ }
+ return null;
+ }
+
+ private Position createProjectionPosition(IRegion region,
+ IJavaElement element) {
+
+ if (fCachedDocument == null)
+ return null;
+
+ try {
+
+ int start = fCachedDocument.getLineOfOffset(region.getOffset());
+ int end = fCachedDocument.getLineOfOffset(region.getOffset()
+ + region.getLength());
+ if (start != end) {
+ int offset = fCachedDocument.getLineOffset(start);
+ int endOffset;
+ if (fCachedDocument.getNumberOfLines() > end + 1)
+ endOffset = fCachedDocument.getLineOffset(end + 1);
+ else if (end > start)
+ endOffset = fCachedDocument.getLineOffset(end)
+ + fCachedDocument.getLineLength(end);
+ else
+ return null;
+ if (element instanceof IMember)
+ return new JavaElementPosition(offset, endOffset - offset,
+ (IMember) element);
+ else
+ return new CommentPosition(offset, endOffset - offset);
+ }
+
+ } catch (BadLocationException x) {
+ }
+
+ return null;
+ }
+
+ protected void processDelta(IJavaElementDelta delta) {
+
+ if (!isInstalled())
+ return;
+
+ if ((delta.getFlags() & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_CHILDREN)) == 0)
+ return;
+
+ ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor
+ .getAdapter(ProjectionAnnotationModel.class);
+ if (model == null)
+ return;
+
+ try {
+
+ IDocumentProvider provider = fEditor.getDocumentProvider();
+ fCachedDocument = provider.getDocument(fEditor.getEditorInput());
+ fCachedModel = model;
+ fAllowCollapsing = false;
+
+ fFirstType = null;
+ fHasHeaderComment = false;
+
+ Map additions = new HashMap();
+ List deletions = new ArrayList();
+ List updates = new ArrayList();
+
+ Map updated = computeAdditions((IParent) fInput);
+ Map previous = createAnnotationMap(model);
+
+ Iterator e = updated.keySet().iterator();
+ while (e.hasNext()) {
+ JavaProjectionAnnotation newAnnotation = (JavaProjectionAnnotation) e
+ .next();
+//+
+ Position newPosition = (Position) updated.get(newAnnotation);
+ additions.put(newAnnotation, newPosition);
+//-
+// IJavaElement element = newAnnotation.getElement();
+// Position newPosition = (Position) updated.get(newAnnotation);
+//
+// List annotations = (List) previous.get(element);
+// if (annotations == null) {
+//
+// additions.put(newAnnotation, newPosition);
+//
+// } else {
+// Iterator x = annotations.iterator();
+// boolean matched = false;
+// while (x.hasNext()) {
+// Tuple tuple = (Tuple) x.next();
+// JavaProjectionAnnotation existingAnnotation = tuple.annotation;
+// Position existingPosition = tuple.position;
+// if (newAnnotation.isComment() == existingAnnotation
+// .isComment()) {
+// if (existingPosition != null
+// && (!newPosition.equals(existingPosition))) {
+// existingPosition.setOffset(newPosition
+// .getOffset());
+// existingPosition.setLength(newPosition
+// .getLength());
+// updates.add(existingAnnotation);
+// }
+// matched = true;
+// x.remove();
+// break;
+// }
+// }
+// if (!matched)
+// additions.put(newAnnotation, newPosition);
+//
+// if (annotations.isEmpty())
+// previous.remove(element);
+// }
+//-
+ }
+
+ e = previous.values().iterator();
+ while (e.hasNext()) {
+ List list = (List) e.next();
+ int size = list.size();
+ for (int i = 0; i < size; i++)
+ deletions.add(((Tuple) list.get(i)).annotation);
+ }
+
+ match(deletions, additions, updates);
+
+ Annotation[] removals = new Annotation[deletions.size()];
+ deletions.toArray(removals);
+ Annotation[] changes = new Annotation[updates.size()];
+ updates.toArray(changes);
+ model.modifyAnnotations(removals, additions, changes);
+
+ } finally {
+ fCachedDocument = null;
+ fAllowCollapsing = true;
+ fCachedModel = null;
+
+ fFirstType = null;
+ fHasHeaderComment = false;
+ }
+ }
+
+ /**
+ * Matches deleted annotations to changed or added ones. A deleted
+ * annotation/position tuple that has a matching addition / change is
+ * updated and marked as changed. The matching tuple is not added (for
+ * additions) or marked as deletion instead (for changes). The result is
+ * that more annotations are changed and fewer get deleted/re-added.
+ */
+ private void match(List deletions, Map additions, List changes) {
+ if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty()))
+ return;
+
+ List newDeletions = new ArrayList();
+ List newChanges = new ArrayList();
+
+ Iterator deletionIterator = deletions.iterator();
+ while (deletionIterator.hasNext()) {
+ JavaProjectionAnnotation deleted = (JavaProjectionAnnotation) deletionIterator
+ .next();
+ Position deletedPosition = fCachedModel.getPosition(deleted);
+ if (deletedPosition == null)
+ continue;
+
+ Tuple deletedTuple = new Tuple(deleted, deletedPosition);
+
+ Tuple match = findMatch(deletedTuple, changes, null);
+ boolean addToDeletions = true;
+ if (match == null) {
+ match = findMatch(deletedTuple, additions.keySet(), additions);
+ addToDeletions = false;
+ }
+
+ if (match != null) {
+ IJavaElement element = match.annotation.getElement();
+ deleted.setElement(element);
+ deletedPosition.setLength(match.position.getLength());
+ if (deletedPosition instanceof JavaElementPosition
+ && element instanceof IMember) {
+ JavaElementPosition jep = (JavaElementPosition) deletedPosition;
+ jep.setMember((IMember) element);
+ }
+
+ deletionIterator.remove();
+ newChanges.add(deleted);
+
+ if (addToDeletions)
+ newDeletions.add(match.annotation);
+ }
+ }
+
+ deletions.addAll(newDeletions);
+ changes.addAll(newChanges);
+ }
+
+ /**
+ * Finds a match for tuple
in a collection of annotations.
+ * The positions for the JavaProjectionAnnotation
instances
+ * in annotations
can be found in the passed
+ * positionMap
or fCachedModel
if
+ * positionMap
is null
.
+ * annotations
.
+ * JavaProjectionAnnotation
+ * @param positionMap
+ * a Map<Annotation, Position>
or
+ * null
+ * @return a matching tuple or null
for no match
+ */
+ private Tuple findMatch(Tuple tuple, Collection annotations, Map positionMap) {
+ Iterator it = annotations.iterator();
+ while (it.hasNext()) {
+ JavaProjectionAnnotation annotation = (JavaProjectionAnnotation) it
+ .next();
+ if (tuple.annotation.isComment() == annotation.isComment()) {
+ Position position = positionMap == null ? fCachedModel
+ .getPosition(annotation) : (Position) positionMap
+ .get(annotation);
+ if (position == null)
+ continue;
+
+ if (tuple.position.getOffset() == position.getOffset()) {
+ it.remove();
+ return new Tuple(annotation, position);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private Map createAnnotationMap(IAnnotationModel model) {
+ Map map = new HashMap();
+ Iterator e = model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Object annotation = e.next();
+ if (annotation instanceof JavaProjectionAnnotation) {
+ JavaProjectionAnnotation java = (JavaProjectionAnnotation) annotation;
+ Position position = model.getPosition(java);
+ Assert.isNotNull(position);
+ List list = (List) map.get(java.getElement());
+ if (list == null) {
+ list = new ArrayList(2);
+ map.put(java.getElement(), list);
+ }
+ list.add(new Tuple(java, position));
+ }
+ }
+
+ Comparator comparator = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((Tuple) o1).position.getOffset()
+ - ((Tuple) o2).position.getOffset();
+ }
+ };
+ for (Iterator it = map.values().iterator(); it.hasNext();) {
+ List list = (List) it.next();
+ Collections.sort(list, comparator);
+ }
+ return map;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/EmptyJavaFoldingPreferenceBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/EmptyJavaFoldingPreferenceBlock.java
new file mode 100644
index 0000000..5ccaeaa
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/EmptyJavaFoldingPreferenceBlock.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.folding;
+
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingPreferenceBlock;
+
+import org.eclipse.swt.SWT;
+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;
+
+/**
+ * Empty preference block for extensions to the
+ * net.sourceforge.phpdt.ui.javaFoldingStructureProvider
+ * extension point that do not specify their own.
+ *
+ * @since 3.0
+ */
+class EmptyJavaFoldingPreferenceBlock implements IJavaFoldingPreferenceBlock {
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.IJavaFoldingPreferences#createControl(org.eclipse.swt.widgets.Group)
+ */
+ public Control createControl(Composite composite) {
+ Composite inner = new Composite(composite, SWT.NONE);
+ inner.setLayout(new GridLayout(3, false));
+
+ Label label = new Label(inner, SWT.CENTER);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = 30;
+ label.setLayoutData(gd);
+
+ label = new Label(inner, SWT.CENTER);
+ label.setText(FoldingMessages
+ .getString("EmptyJavaFoldingPreferenceBlock.emptyCaption")); //$NON-NLS-1$
+ gd = new GridData(GridData.CENTER);
+ label.setLayoutData(gd);
+
+ label = new Label(inner, SWT.CENTER);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = 30;
+ label.setLayoutData(gd);
+
+ return inner;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.IJavaFoldingPreferenceBlock#initialize()
+ */
+ public void initialize() {
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.IJavaFoldingPreferenceBlock#performOk()
+ */
+ public void performOk() {
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.IJavaFoldingPreferenceBlock#performDefaults()
+ */
+ public void performDefaults() {
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.folding.IJavaFoldingPreferenceBlock#dispose()
+ */
+ public void dispose() {
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/FoldingMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/FoldingMessages.java
new file mode 100644
index 0000000..2f641d3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/FoldingMessages.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.folding;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @since 3.0
+ */
+class FoldingMessages {
+
+ private static final String BUNDLE_NAME = FoldingMessages.class.getName();
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private FoldingMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/FoldingMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/FoldingMessages.properties
new file mode 100644
index 0000000..b89b15e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/FoldingMessages.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2000, 2004 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+
+DefaultJavaFoldingPreferenceBlock.title= Initially fold these region types:
+DefaultJavaFoldingPreferenceBlock.comments= &Comments
+DefaultJavaFoldingPreferenceBlock.headers= &Header Comments
+DefaultJavaFoldingPreferenceBlock.innerTypes= Inner &types
+DefaultJavaFoldingPreferenceBlock.methods= &Methods
+DefaultJavaFoldingPreferenceBlock.imports= &Imports
+
+EmptyJavaFoldingPreferenceBlock.emptyCaption=
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/JavaFoldingStructureProviderDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/JavaFoldingStructureProviderDescriptor.java
new file mode 100644
index 0000000..a810ba8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/JavaFoldingStructureProviderDescriptor.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.folding;
+
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingPreferenceBlock;
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jface.text.Assert;
+
+/**
+ * Describes a contribution to the folding provider extension point.
+ *
+ * @since 3.0
+ */
+public final class JavaFoldingStructureProviderDescriptor {
+
+ /* extension point attribute names */
+
+ private static final String PREFERENCES_CLASS = "preferencesClass"; //$NON-NLS-1$
+
+ private static final String CLASS = "class"; //$NON-NLS-1$
+
+ private static final String NAME = "name"; //$NON-NLS-1$
+
+ private static final String ID = "id"; //$NON-NLS-1$
+
+ /** The identifier of the extension. */
+ private String fId;
+
+ /** The name of the extension. */
+ private String fName;
+
+ /** The class name of the provided IJavaFoldingStructureProvider
. */
+ private String fClass;
+
+ /**
+ * true
if the extension specifies a custom
+ * IJavaFoldingPreferenceBlock
.
+ */
+ private boolean fHasPreferences;
+
+ /** The configuration element of this extension. */
+ private IConfigurationElement fElement;
+
+ /**
+ * Creates a new descriptor.
+ *
+ * @param element
+ * the configuration element to read
+ */
+ JavaFoldingStructureProviderDescriptor(IConfigurationElement element) {
+ fElement = element;
+ fId = element.getAttributeAsIs(ID);
+ Assert.isLegal(fId != null);
+
+ fName = element.getAttribute(NAME);
+ if (fName == null)
+ fName = fId;
+
+ fClass = element.getAttributeAsIs(CLASS);
+ Assert.isLegal(fClass != null);
+
+ if (element.getAttributeAsIs(PREFERENCES_CLASS) == null)
+ fHasPreferences = false;
+ else
+ fHasPreferences = true;
+ }
+
+ /**
+ * Creates a folding provider as described in the extension's xml.
+ *
+ * @return a new instance of the folding provider described by this
+ * descriptor
+ * @throws CoreException
+ * if creation fails
+ */
+ public IJavaFoldingStructureProvider createProvider() throws CoreException {
+ IJavaFoldingStructureProvider prov = (IJavaFoldingStructureProvider) fElement
+ .createExecutableExtension(CLASS);
+ return prov;
+ }
+
+ /**
+ * Creates a preferences object as described in the extension's xml.
+ *
+ * @return a new instance of the reference provider described by this
+ * descriptor
+ * @throws CoreException
+ * if creation fails
+ */
+ public IJavaFoldingPreferenceBlock createPreferences() throws CoreException {
+ if (fHasPreferences) {
+ IJavaFoldingPreferenceBlock prefs = (IJavaFoldingPreferenceBlock) fElement
+ .createExecutableExtension(PREFERENCES_CLASS);
+ return prefs;
+ } else {
+ return new EmptyJavaFoldingPreferenceBlock();
+ }
+ }
+
+ /**
+ * Returns the identifier of the described extension.
+ *
+ * @return Returns the id
+ */
+ public String getId() {
+ return fId;
+ }
+
+ /**
+ * Returns the name of the described extension.
+ *
+ * @return Returns the name
+ */
+ public String getName() {
+ return fName;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/JavaFoldingStructureProviderRegistry.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/JavaFoldingStructureProviderRegistry.java
new file mode 100644
index 0000000..2228c68
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/JavaFoldingStructureProviderRegistry.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.folding;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * @since 3.0
+ */
+public class JavaFoldingStructureProviderRegistry {
+
+ private static final String EXTENSION_POINT = "foldingStructureProviders"; //$NON-NLS-1$
+
+ /** The map of descriptors, indexed by their identifiers. */
+ private Map fDescriptors;
+
+ /**
+ * Creates a new instance.
+ */
+ public JavaFoldingStructureProviderRegistry() {
+ }
+
+ /**
+ * Returns an array of IJavaFoldingProviderDescriptor
+ * describing all extension to the foldingProviders
extension
+ * point.
+ *
+ * @return the list of extensions to the
+ * quickDiffReferenceProvider
extension point.
+ */
+ public JavaFoldingStructureProviderDescriptor[] getFoldingProviderDescriptors() {
+ synchronized (this) {
+ ensureRegistered();
+ return (JavaFoldingStructureProviderDescriptor[]) fDescriptors
+ .values()
+ .toArray(
+ new JavaFoldingStructureProviderDescriptor[fDescriptors
+ .size()]);
+ }
+ }
+
+ /**
+ * Returns the folding provider with identifier id
or
+ * null
if no such provider is registered.
+ *
+ * @param id
+ * the identifier for which a provider is wanted
+ * @return the corresponding provider, or null
if none can be
+ * found
+ */
+ public JavaFoldingStructureProviderDescriptor getFoldingProviderDescriptor(
+ String id) {
+ synchronized (this) {
+ ensureRegistered();
+ return (JavaFoldingStructureProviderDescriptor) fDescriptors
+ .get(id);
+ }
+ }
+
+ /**
+ * Instantiates and returns the provider that is currently configured in the
+ * preferences.
+ *
+ * @return the current provider according to the preferences
+ */
+ public IJavaFoldingStructureProvider getCurrentFoldingProvider() {
+ String id = WebUI.getDefault().getPreferenceStore()
+ .getString(PreferenceConstants.EDITOR_FOLDING_PROVIDER);
+ JavaFoldingStructureProviderDescriptor desc = getFoldingProviderDescriptor(id);
+ if (desc != null) {
+ try {
+ return desc.createProvider();
+ } catch (CoreException e) {
+ WebUI.log(e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Ensures that the extensions are read and stored in
+ * fDescriptors
.
+ */
+ private void ensureRegistered() {
+ if (fDescriptors == null)
+ reloadExtensions();
+ }
+
+ /**
+ * Reads all extensions.
+ * null
if the working
+ * copy was consistent or reconciliation has been cancelled
+ * @param forced
+ * true
iff this reconciliation was forced
+ * @param progressMonitor
+ * the progress monitor
+ */
+ void reconciled(CompilationUnit ast, boolean forced,
+ IProgressMonitor progressMonitor);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IPHPCompletionProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IPHPCompletionProposal.java
new file mode 100644
index 0000000..98ae9ba
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IPHPCompletionProposal.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+
+/*
+ * CompletionProposal with a relevance value. The relevance value is used to
+ * sort the completion proposals. Proposals with higher relevance should be
+ * listed before proposals with lower relevance.
+ */
+public interface IPHPCompletionProposal extends ICompletionProposal {
+
+ /**
+ * Returns the relevance of the proposal.
+ */
+ int getRelevance();
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IProblemRequestorExtension.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IProblemRequestorExtension.java
new file mode 100644
index 0000000..b9dcb85
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IProblemRequestorExtension.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Extension to IProblemRequestor
.
+ */
+public interface IProblemRequestorExtension {
+
+ /**
+ * Sets the progress monitor to this problem requestor.
+ *
+ * @param monitor
+ * the progress monitor to be used
+ */
+ void setProgressMonitor(IProgressMonitor monitor);
+
+ /**
+ * Sets the active state of this problem requestor.
+ *
+ * @param isActive
+ * the state of this problem requestor
+ */
+ void setIsActive(boolean isActive);
+
+ /**
+ * Informs the problem requestor that a sequence of reportings is about to
+ * start. While a sequence is active, multiple peering calls of
+ * beginReporting
and endReporting
can appear.
+ *
+ * @since 3.0
+ */
+ void beginReportingSequence();
+
+ /**
+ * Informs the problem requestor that the sequence of reportings has been
+ * finished.
+ *
+ * @since 3.0
+ */
+ void endReportingSequence();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IReconcilingParticipant.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IReconcilingParticipant.java
new file mode 100644
index 0000000..9878725
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/IReconcilingParticipant.java
@@ -0,0 +1,17 @@
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/**
+ * Interface of an object participating in reconciling.
+ */
+public interface IReconcilingParticipant {
+
+ /**
+ * Called after reconciling has been finished.
+ */
+ void reconciled();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaFormattingStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaFormattingStrategy.java
new file mode 100644
index 0000000..0fd345d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaFormattingStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001. All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import net.sourceforge.phpdt.core.ICodeFormatter;
+import net.sourceforge.phpdt.core.ToolFactory;
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+import net.sourceforge.phpdt.internal.ui.preferences.CodeFormatterPreferencePage;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.formatter.IFormattingStrategy;
+import org.eclipse.jface.text.source.ISourceViewer;
+
+public class JavaFormattingStrategy implements IFormattingStrategy {
+
+ private String fInitialIndentation;
+
+ private ISourceViewer fViewer;
+
+ public JavaFormattingStrategy(ISourceViewer viewer) {
+ fViewer = viewer;
+ }
+
+ /**
+ * @see IFormattingStrategy#formatterStarts(String)
+ */
+ public void formatterStarts(String initialIndentation) {
+ fInitialIndentation = initialIndentation;
+ }
+
+ /**
+ * @see IFormattingStrategy#formatterStops()
+ */
+ public void formatterStops() {
+ }
+
+ /**
+ * @see IFormattingStrategy#format(String, boolean, String, int[])
+ */
+ public String format(String content, boolean isLineStart,
+ String indentation, int[] positions) {
+ ICodeFormatter formatter = ToolFactory.createCodeFormatter();
+
+ IDocument doc = fViewer.getDocument();
+ String lineDelimiter = StubUtility.getLineDelimiterFor(doc);
+
+ int indent = 0;
+ if (fInitialIndentation != null) {
+ indent = Strings.computeIndent(fInitialIndentation,
+ CodeFormatterPreferencePage.getTabSize());
+ }
+
+ return formatter.format(content, indent, positions, lineDelimiter);
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaHoverMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaHoverMessages.java
new file mode 100644
index 0000000..bedafbc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaHoverMessages.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+class JavaHoverMessages {
+
+ private static final String RESOURCE_BUNDLE = JavaHoverMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private JavaHoverMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * 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
+ * @since 3.0
+ */
+ public static String getFormattedString(String key, Object arg) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ if (arg == null)
+ arg = ""; //$NON-NLS-1$
+ return MessageFormat.format(format, new Object[] { arg });
+ }
+
+ /**
+ * Gets a string from the resource bundle and formats it with the arguments
+ *
+ * @param key
+ * the string used to get the bundle value, must not be null
+ * @since 3.0
+ */
+ public static String getFormattedString(String key, Object arg1, Object arg2) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ if (arg1 == null)
+ arg1 = ""; //$NON-NLS-1$
+ if (arg2 == null)
+ arg2 = ""; //$NON-NLS-1$
+ return MessageFormat.format(format, new Object[] { arg1, arg2 });
+ }
+
+ /**
+ * 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
+ * @since 3.0
+ */
+ public static String getFormattedString(String key, boolean arg) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ return MessageFormat.format(format, new Object[] { new Boolean(arg) });
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaHoverMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaHoverMessages.properties
new file mode 100644
index 0000000..01f64aa
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaHoverMessages.properties
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright (c) 2000, 2004 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+TypeHover.more_to_come=\ ...
+
+JavaTextHover.createTextHover= Could not create PHP text hover
+
+JavaTextHover.makeStickyHint= Press ''{0}'' for focus.
+
+NoBreakpointAnnotation.addBreakpoint= Add a breakpoint
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaParameterListValidator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaParameterListValidator.java
new file mode 100644
index 0000000..71bf6ff
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaParameterListValidator.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.text.java;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+
+public class JavaParameterListValidator implements
+ IContextInformationValidator, IContextInformationPresenter {
+
+ private int fPosition;
+
+ private ITextViewer fViewer;
+
+ private IContextInformation fInformation;
+
+ private int fCurrentParameter;
+
+ public JavaParameterListValidator() {
+ }
+
+ /**
+ * @see IContextInformationValidator#install(IContextInformation,
+ * ITextViewer, int)
+ * @see IContextInformationPresenter#install(IContextInformation,
+ * ITextViewer, int)
+ */
+ public void install(IContextInformation info, ITextViewer viewer,
+ int documentPosition) {
+ fPosition = documentPosition;
+ fViewer = viewer;
+ fInformation = info;
+
+ fCurrentParameter = -1;
+ }
+
+ private int getCommentEnd(IDocument d, int pos, int end)
+ throws BadLocationException {
+ while (pos < end) {
+ char curr = d.getChar(pos);
+ pos++;
+ if (curr == '*') {
+ if (pos < end && d.getChar(pos) == '/') {
+ return pos + 1;
+ }
+ }
+ }
+ return end;
+ }
+
+ private int getStringEnd(IDocument d, int pos, int end, char ch)
+ throws BadLocationException {
+ while (pos < end) {
+ char curr = d.getChar(pos);
+ pos++;
+ if (curr == '\\') {
+ // ignore escaped characters
+ pos++;
+ } else if (curr == ch) {
+ return pos;
+ }
+ }
+ return end;
+ }
+
+ private int getCharCount(IDocument document, int start, int end,
+ String increments, String decrements, boolean considerNesting)
+ throws BadLocationException {
+
+ Assert.isTrue((increments.length() != 0 || decrements.length() != 0)
+ && !increments.equals(decrements));
+
+ int nestingLevel = 0;
+ int charCount = 0;
+ while (start < end) {
+ char curr = document.getChar(start++);
+ switch (curr) {
+ case '/':
+ if (start < end) {
+ char next = document.getChar(start);
+ if (next == '*') {
+ // a comment starts, advance to the comment end
+ start = getCommentEnd(document, start + 1, end);
+ } else if (next == '/') {
+ // '//'-comment: nothing to do anymore on this line
+ start = end;
+ }
+ }
+ break;
+ case '*':
+ if (start < end) {
+ char next = document.getChar(start);
+ if (next == '/') {
+ // we have been in a comment: forget what we read before
+ charCount = 0;
+ ++start;
+ }
+ }
+ break;
+ case '"':
+ case '\'':
+ start = getStringEnd(document, start, end, curr);
+ break;
+ default:
+
+ if (considerNesting) {
+
+ if ('(' == curr)
+ ++nestingLevel;
+ else if (')' == curr)
+ --nestingLevel;
+
+ if (nestingLevel != 0)
+ break;
+ }
+
+ if (increments.indexOf(curr) >= 0) {
+ ++charCount;
+ }
+
+ if (decrements.indexOf(curr) >= 0) {
+ --charCount;
+ }
+ }
+ }
+
+ return charCount;
+ }
+
+ /**
+ * @see IContextInformationValidator#isContextInformationValid(int)
+ */
+ public boolean isContextInformationValid(int position) {
+
+ try {
+ if (position < fPosition)
+ return false;
+
+ IDocument document = fViewer.getDocument();
+ IRegion line = document.getLineInformationOfOffset(fPosition);
+
+ if (position < line.getOffset() || position >= document.getLength())
+ return false;
+
+ return getCharCount(document, fPosition, position,
+ "(<", ")>", false) >= 0; //$NON-NLS-1$//$NON-NLS-2$
+
+ } catch (BadLocationException x) {
+ return false;
+ }
+ }
+
+ /**
+ * @see IContextInformationPresenter#updatePresentation(int,
+ * TextPresentation)
+ */
+ public boolean updatePresentation(int position,
+ TextPresentation presentation) {
+
+ int currentParameter = -1;
+
+ try {
+ currentParameter = getCharCount(fViewer.getDocument(), fPosition,
+ position, ",", "", true); //$NON-NLS-1$//$NON-NLS-2$
+ } catch (BadLocationException x) {
+ return false;
+ }
+
+ if (fCurrentParameter != -1) {
+ if (currentParameter == fCurrentParameter)
+ return false;
+ }
+
+ presentation.clear();
+ fCurrentParameter = currentParameter;
+
+ String s = fInformation.getInformationDisplayString();
+ int start = 0;
+ int occurrences = 0;
+ while (occurrences < fCurrentParameter) {
+ int found = s.indexOf(',', start);
+ if (found == -1)
+ break;
+ start = found + 1;
+ ++occurrences;
+ }
+
+ if (occurrences < fCurrentParameter) {
+ presentation.addStyleRange(new StyleRange(0, s.length(), null,
+ null, SWT.NORMAL));
+ return true;
+ }
+
+ if (start == -1)
+ start = 0;
+
+ int end = s.indexOf(',', start);
+ if (end == -1)
+ end = s.length();
+
+ if (start > 0)
+ presentation.addStyleRange(new StyleRange(0, start, null, null,
+ SWT.NORMAL));
+
+ if (end > start)
+ presentation.addStyleRange(new StyleRange(start, end - start, null,
+ null, SWT.BOLD));
+
+ if (end < s.length())
+ presentation.addStyleRange(new StyleRange(end, s.length() - end,
+ null, null, SWT.NORMAL));
+
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaReconcilingStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaReconcilingStrategy.java
new file mode 100644
index 0000000..7f91e31
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaReconcilingStrategy.java
@@ -0,0 +1,218 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ **********************************************************************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+public class JavaReconcilingStrategy implements IReconcilingStrategy,
+ IReconcilingStrategyExtension {
+
+ private ITextEditor fEditor;
+
+ private IWorkingCopyManager fManager;
+
+ private IDocumentProvider fDocumentProvider;
+
+ private IProgressMonitor fProgressMonitor;
+
+ private boolean fNotify = true;
+
+ private IJavaReconcilingListener fJavaReconcilingListener;
+
+ private boolean fIsJavaReconcilingListener;
+
+ public JavaReconcilingStrategy(ITextEditor editor) {
+ fEditor = editor;
+ fManager = WebUI.getDefault().getWorkingCopyManager();
+ fDocumentProvider = WebUI.getDefault()
+ .getCompilationUnitDocumentProvider();
+ fIsJavaReconcilingListener = fEditor instanceof IJavaReconcilingListener;
+ if (fIsJavaReconcilingListener)
+ fJavaReconcilingListener = (IJavaReconcilingListener) fEditor;
+ }
+
+ private IProblemRequestorExtension getProblemRequestorExtension() {
+ IAnnotationModel model = fDocumentProvider.getAnnotationModel(fEditor
+ .getEditorInput());
+ if (model instanceof IProblemRequestorExtension)
+ return (IProblemRequestorExtension) model;
+ return null;
+ }
+
+ private void reconcile() {
+ // // try {
+ //
+ // /* fix for missing cancel flag communication */
+ // IProblemRequestorExtension extension =
+ // getProblemRequestorExtension();
+ // if (extension != null)
+ // extension.setProgressMonitor(fProgressMonitor);
+ //
+ // // reconcile
+ // // synchronized (unit) {
+ // // unit.reconcile(true, fProgressMonitor);
+ // // }
+ //
+ // Parser parser = new Parser();
+ // parser.initializeScanner();
+ // // actualParser.setFileToParse(fileToParse);
+ // String text =
+ // fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()).get();
+ // parser.init(text);
+ // parser.reportSyntaxError();
+ // // checkAndReportBracketAnomalies(parser.problemReporter());
+ //
+ // /* fix for missing cancel flag communication */
+ // if (extension != null)
+ // extension.setProgressMonitor(null);
+ //
+ // // update participants
+ // try {
+ // if (fEditor instanceof IReconcilingParticipant && fNotify &&
+ // !fProgressMonitor.isCanceled()) {
+ // IReconcilingParticipant p = (IReconcilingParticipant) fEditor;
+ // p.reconciled();
+ // }
+ // } finally {
+ // fNotify = true;
+ // }
+
+ // JDT implementation:
+ try {
+ ICompilationUnit unit = fManager.getWorkingCopy(fEditor
+ .getEditorInput());
+ if (unit != null) {
+ try {
+
+ /* fix for missing cancel flag communication */
+ IProblemRequestorExtension extension = getProblemRequestorExtension();
+ if (extension != null)
+ extension.setProgressMonitor(fProgressMonitor);
+
+ // reconcile
+ synchronized (unit) {
+ unit.reconcile(true, fProgressMonitor);
+ }
+
+ /* fix for missing cancel flag communication */
+ if (extension != null)
+ extension.setProgressMonitor(null);
+
+ // update participants
+ try {
+ if (fEditor instanceof IReconcilingParticipant
+ && fNotify && !fProgressMonitor.isCanceled()) {
+ IReconcilingParticipant p = (IReconcilingParticipant) fEditor;
+ p.reconciled();
+ }
+ } finally {
+ fNotify = true;
+ }
+
+ } catch (JavaModelException x) {
+ // swallow exception
+ }
+ }
+ } finally {
+ // Always notify listeners, see
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=55969 for the final
+ // solution
+ try {
+ if (fIsJavaReconcilingListener) {
+ IProgressMonitor pm = fProgressMonitor;
+ if (pm == null)
+ pm = new NullProgressMonitor();
+ fJavaReconcilingListener.reconciled(null, !fNotify, pm);
+ }
+ } finally {
+ fNotify = true;
+ }
+
+ }
+ }
+
+ /*
+ * @see IReconcilingStrategy#reconcile(IRegion)
+ */
+ public void reconcile(IRegion partition) {
+ reconcile();
+ }
+
+ /*
+ * @see IReconcilingStrategy#reconcile(DirtyRegion, IRegion)
+ */
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ reconcile();
+ }
+
+ /*
+ * @see IReconcilingStrategy#setDocument(IDocument)
+ */
+ public void setDocument(IDocument document) {
+ }
+
+ /*
+ * @see IReconcilingStrategyExtension#setProgressMonitor(IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ fProgressMonitor = monitor;
+ }
+
+ /*
+ * @see IReconcilingStrategyExtension#initialReconcile()
+ */
+ public void initialReconcile() {
+ reconcile();
+ }
+
+ /**
+ * Tells this strategy whether to inform its participants.
+ *
+ * @param notify
+ * true
if participant should be notified
+ */
+ public void notifyParticipants(boolean notify) {
+ fNotify = notify;
+ }
+
+ /**
+ * Tells this strategy whether to inform its listeners.
+ *
+ * @param notify
+ * true
if listeners should be notified
+ */
+ public void notifyListeners(boolean notify) {
+ fNotify = notify;
+ }
+
+ /**
+ * Called before reconciling is started.
+ *
+ * @since 3.0
+ */
+ public void aboutToBeReconciled() {
+ if (fIsJavaReconcilingListener)
+ fJavaReconcilingListener.aboutToBeReconciled();
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategyDQ.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategyDQ.java
new file mode 100644
index 0000000..0f18909
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategyDQ.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+
+/**
+ * Auto indent strategy for java strings
+ */
+public class JavaStringAutoIndentStrategyDQ extends
+ DefaultIndentLineAutoEditStrategy {
+
+ private String fPartitioning;
+
+ /**
+ * The input string doesn't contain any line delimiter.
+ *
+ * @param inputString
+ * the given input string
+ * @return the displayable string.
+ */
+ private String displayString(String inputString, String indentation,
+ String delimiter) {
+
+ int length = inputString.length();
+ StringBuffer buffer = new StringBuffer(length);
+ java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(
+ inputString, "\n\r", true); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens()) {
+
+ String token = tokenizer.nextToken();
+ if (token.equals("\r")) { //$NON-NLS-1$
+ buffer.append("\\r"); //$NON-NLS-1$
+ if (tokenizer.hasMoreTokens()) {
+ token = tokenizer.nextToken();
+ if (token.equals("\n")) { //$NON-NLS-1$
+ buffer.append("\\n"); //$NON-NLS-1$
+ buffer.append("\" . " + delimiter); //$NON-NLS-1$
+ buffer.append(indentation);
+ buffer.append("\""); //$NON-NLS-1$
+ continue;
+ } else {
+ buffer.append("\" . " + delimiter); //$NON-NLS-1$
+ buffer.append(indentation);
+ buffer.append("\""); //$NON-NLS-1$
+ }
+ } else {
+ continue;
+ }
+ } else if (token.equals("\n")) { //$NON-NLS-1$
+ buffer.append("\\n"); //$NON-NLS-1$
+ buffer.append("\" . " + delimiter); //$NON-NLS-1$
+ buffer.append(indentation);
+ buffer.append("\""); //$NON-NLS-1$
+ continue;
+ }
+
+ StringBuffer tokenBuffer = new StringBuffer();
+ for (int i = 0; i < token.length(); i++) {
+ char c = token.charAt(i);
+ switch (c) {
+ case '\r':
+ tokenBuffer.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\n':
+ tokenBuffer.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\b':
+ tokenBuffer.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t':
+ // keep tabs verbatim
+ tokenBuffer.append("\t"); //$NON-NLS-1$
+ break;
+ case '\f':
+ tokenBuffer.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\"':
+ tokenBuffer.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'':
+ tokenBuffer.append("\\'"); //$NON-NLS-1$
+ break;
+ case '\\':
+ tokenBuffer.append("\\\\"); //$NON-NLS-1$
+ break;
+ default:
+ tokenBuffer.append(c);
+ }
+ }
+ buffer.append(tokenBuffer);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Creates a new Java string auto indent strategy for the given document
+ * partitioning.
+ *
+ * @param partitioning
+ * the document partitioning
+ */
+ public JavaStringAutoIndentStrategyDQ(String partitioning) {
+ super();
+ fPartitioning = partitioning;
+ }
+
+ private boolean isLineDelimiter(IDocument document, String text) {
+ String[] delimiters = document.getLegalLineDelimiters();
+ if (delimiters != null)
+ return TextUtilities.equals(delimiters, text) > -1;
+ return false;
+ }
+
+ private String getLineIndentation(IDocument document, int offset)
+ throws BadLocationException {
+
+ // find start of line
+ int adjustedOffset = (offset == document.getLength() ? offset - 1
+ : offset);
+ IRegion line = document.getLineInformationOfOffset(adjustedOffset);
+ int start = line.getOffset();
+
+ // find white spaces
+ int end = findEndOfWhiteSpace(document, start, offset);
+
+ return document.get(start, end - start);
+ }
+
+ private String getModifiedText(String string, String indentation,
+ String delimiter) throws BadLocationException {
+ return displayString(string, indentation, delimiter);
+ }
+
+ private void javaStringIndentAfterNewLine(IDocument document,
+ DocumentCommand command) throws BadLocationException {
+
+ ITypedRegion partition = TextUtilities.getPartition(document,
+ fPartitioning, command.offset, false);
+ int offset = partition.getOffset();
+ int length = partition.getLength();
+
+ if (command.offset == offset) {
+ // we are really just before the string partition -> feet the event
+ // through the java indenter
+ // new
+ // JavaAutoIndentStrategy(fPartitioning).customizeDocumentCommand(document,
+ // command);
+ return;
+ }
+
+ if (command.offset == offset + length
+ && document.getChar(offset + length - 1) == '\"')
+ return;
+
+ String indentation = getLineIndentation(document, command.offset);
+ String delimiter = TextUtilities.getDefaultLineDelimiter(document);
+
+ IRegion line = document.getLineInformationOfOffset(offset);
+ String string = document.get(line.getOffset(), offset
+ - line.getOffset());
+ if (string.trim().length() != 0)
+ indentation += String.valueOf("\t\t"); //$NON-NLS-1$
+
+ IPreferenceStore preferenceStore = WebUI.getDefault()
+ .getPreferenceStore();
+ if (isLineDelimiter(document, command.text))
+ command.text = "\" ." + command.text + indentation + "\""; //$NON-NLS-1$//$NON-NLS-2$
+ else if (command.text.length() > 1
+ && preferenceStore
+ .getBoolean(PreferenceConstants.EDITOR_ESCAPE_STRINGS_DQ))
+ command.text = getModifiedText(command.text, indentation, delimiter);
+ }
+
+ private boolean isSmartMode() {
+ IWorkbenchPage page = WebUI.getActivePage();
+ if (page != null) {
+ IEditorPart part = page.getActiveEditor();
+ if (part instanceof ITextEditorExtension3) {
+ ITextEditorExtension3 extension = (ITextEditorExtension3) part;
+ return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(IDocument,
+ * DocumentCommand)
+ */
+ public void customizeDocumentCommand(IDocument document,
+ DocumentCommand command) {
+ try {
+ if (command.length != 0 || command.text == null)
+ return;
+
+ IPreferenceStore preferenceStore = WebUI.getDefault()
+ .getPreferenceStore();
+
+ if (preferenceStore
+ .getBoolean(PreferenceConstants.EDITOR_WRAP_STRINGS_DQ)
+ && isSmartMode())
+ javaStringIndentAfterNewLine(document, command);
+
+ } catch (BadLocationException e) {
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategySQ.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategySQ.java
new file mode 100644
index 0000000..72e6e67
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategySQ.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+
+/**
+ * Auto indent strategy for java strings
+ */
+public class JavaStringAutoIndentStrategySQ extends
+ DefaultIndentLineAutoEditStrategy {
+
+ private String fPartitioning;
+
+ /**
+ * The input string doesn't contain any line delimiter.
+ *
+ * @param inputString
+ * the given input string
+ * @return the displayable string.
+ */
+ private String displayString(String inputString, String indentation,
+ String delimiter) {
+
+ int length = inputString.length();
+ StringBuffer buffer = new StringBuffer(length);
+ java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(
+ inputString, "\n\r", true); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens()) {
+
+ String token = tokenizer.nextToken();
+ if (token.equals("\r")) { //$NON-NLS-1$
+ buffer.append("\\r"); //$NON-NLS-1$
+ if (tokenizer.hasMoreTokens()) {
+ token = tokenizer.nextToken();
+ if (token.equals("\n")) { //$NON-NLS-1$
+ buffer.append("\\n"); //$NON-NLS-1$
+ buffer.append("\' . " + delimiter); //$NON-NLS-1$
+ buffer.append(indentation);
+ buffer.append("\'"); //$NON-NLS-1$
+ continue;
+ } else {
+ buffer.append("\' . " + delimiter); //$NON-NLS-1$
+ buffer.append(indentation);
+ buffer.append("\'"); //$NON-NLS-1$
+ }
+ } else {
+ continue;
+ }
+ } else if (token.equals("\n")) { //$NON-NLS-1$
+ buffer.append("\\n"); //$NON-NLS-1$
+ buffer.append("\' . " + delimiter); //$NON-NLS-1$
+ buffer.append(indentation);
+ buffer.append("\'"); //$NON-NLS-1$
+ continue;
+ }
+
+ StringBuffer tokenBuffer = new StringBuffer();
+ for (int i = 0; i < token.length(); i++) {
+ char c = token.charAt(i);
+ switch (c) {
+ case '\r':
+ tokenBuffer.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\n':
+ tokenBuffer.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\b':
+ tokenBuffer.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t':
+ // keep tabs verbatim
+ tokenBuffer.append("\t"); //$NON-NLS-1$
+ break;
+ case '\f':
+ tokenBuffer.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\"':
+ tokenBuffer.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'':
+ tokenBuffer.append("\\'"); //$NON-NLS-1$
+ break;
+ case '\\':
+ tokenBuffer.append("\\\\"); //$NON-NLS-1$
+ break;
+ default:
+ tokenBuffer.append(c);
+ }
+ }
+ buffer.append(tokenBuffer);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Creates a new Java string auto indent strategy for the given document
+ * partitioning.
+ *
+ * @param partitioning
+ * the document partitioning
+ */
+ public JavaStringAutoIndentStrategySQ(String partitioning) {
+ super();
+ fPartitioning = partitioning;
+ }
+
+ private boolean isLineDelimiter(IDocument document, String text) {
+ String[] delimiters = document.getLegalLineDelimiters();
+ if (delimiters != null)
+ return TextUtilities.equals(delimiters, text) > -1;
+ return false;
+ }
+
+ private String getLineIndentation(IDocument document, int offset)
+ throws BadLocationException {
+
+ // find start of line
+ int adjustedOffset = (offset == document.getLength() ? offset - 1
+ : offset);
+ IRegion line = document.getLineInformationOfOffset(adjustedOffset);
+ int start = line.getOffset();
+
+ // find white spaces
+ int end = findEndOfWhiteSpace(document, start, offset);
+
+ return document.get(start, end - start);
+ }
+
+ private String getModifiedText(String string, String indentation,
+ String delimiter) throws BadLocationException {
+ return displayString(string, indentation, delimiter);
+ }
+
+ private void javaStringIndentAfterNewLine(IDocument document,
+ DocumentCommand command) throws BadLocationException {
+
+ ITypedRegion partition = TextUtilities.getPartition(document,
+ fPartitioning, command.offset, false);
+ int offset = partition.getOffset();
+ int length = partition.getLength();
+
+ if (command.offset == offset) {
+ // we are really just before the string partition -> feet the event
+ // through the java indenter
+ // new
+ // JavaAutoIndentStrategy(fPartitioning).customizeDocumentCommand(document,
+ // command);
+ return;
+ }
+
+ if (command.offset == offset + length
+ && document.getChar(offset + length - 1) == '\'')
+ return;
+
+ String indentation = getLineIndentation(document, command.offset);
+ String delimiter = TextUtilities.getDefaultLineDelimiter(document);
+
+ IRegion line = document.getLineInformationOfOffset(offset);
+ String string = document.get(line.getOffset(), offset
+ - line.getOffset());
+ if (string.trim().length() != 0)
+ indentation += String.valueOf("\t\t"); //$NON-NLS-1$
+
+ IPreferenceStore preferenceStore = WebUI.getDefault()
+ .getPreferenceStore();
+ if (isLineDelimiter(document, command.text))
+ command.text = "\' ." + command.text + indentation + "\'"; //$NON-NLS-1$//$NON-NLS-2$
+ else if (command.text.length() > 1
+ && preferenceStore
+ .getBoolean(PreferenceConstants.EDITOR_ESCAPE_STRINGS_SQ))
+ command.text = getModifiedText(command.text, indentation, delimiter);
+ }
+
+ private boolean isSmartMode() {
+ IWorkbenchPage page = WebUI.getActivePage();
+ if (page != null) {
+ IEditorPart part = page.getActiveEditor();
+ if (part instanceof ITextEditorExtension3) {
+ ITextEditorExtension3 extension = (ITextEditorExtension3) part;
+ return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(IDocument,
+ * DocumentCommand)
+ */
+ public void customizeDocumentCommand(IDocument document,
+ DocumentCommand command) {
+ try {
+ if (command.length != 0 || command.text == null)
+ return;
+
+ IPreferenceStore preferenceStore = WebUI.getDefault()
+ .getPreferenceStore();
+
+ if (preferenceStore
+ .getBoolean(PreferenceConstants.EDITOR_WRAP_STRINGS_SQ)
+ && isSmartMode())
+ javaStringIndentAfterNewLine(document, command);
+
+ } catch (BadLocationException e) {
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/PHPCompletionProposalComparator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/PHPCompletionProposalComparator.java
new file mode 100644
index 0000000..bad8e94
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/PHPCompletionProposalComparator.java
@@ -0,0 +1,36 @@
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import java.util.Comparator;
+
+public class PHPCompletionProposalComparator implements Comparator {
+
+ private boolean fOrderAlphabetically;
+
+ /**
+ * Constructor for CompletionProposalComparator.
+ */
+ // public PHPCompletionProposalComparator() {
+ // fOrderAlphabetically= false;
+ // }
+ public void setOrderAlphabetically(boolean orderAlphabetically) {
+ fOrderAlphabetically = orderAlphabetically;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see Comparator#compare(Object, Object)
+ */
+ public int compare(Object o1, Object o2) {
+ IPHPCompletionProposal c1 = (IPHPCompletionProposal) o1;
+ IPHPCompletionProposal c2 = (IPHPCompletionProposal) o2;
+ if (!fOrderAlphabetically) {
+ int relevanceDif = c2.getRelevance() - c1.getRelevance();
+ if (relevanceDif != 0) {
+ return relevanceDif;
+ }
+ }
+ return c1.getDisplayString().compareToIgnoreCase(c2.getDisplayString());
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AbstractAnnotationHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AbstractAnnotationHover.java
new file mode 100644
index 0000000..c1bbbdb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AbstractAnnotationHover.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.internal.ui.text.HTMLPrinter;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.JavaAnnotationIterator;
+import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+
+/**
+ * Abstract super class for annotation hovers.
+ *
+ * @since 3.0
+ */
+public abstract class AbstractAnnotationHover extends
+ AbstractJavaEditorTextHover {
+
+ private IPreferenceStore fStore = WebUI.getDefault()
+ .getCombinedPreferenceStore();
+
+ private DefaultMarkerAnnotationAccess fAnnotationAccess = new DefaultMarkerAnnotationAccess();
+
+ private boolean fAllAnnotations;
+
+ public AbstractAnnotationHover(boolean allAnnotations) {
+ fAllAnnotations = allAnnotations;
+ }
+
+ /*
+ * Formats a message as HTML text.
+ */
+ private String formatMessage(String message) {
+ StringBuffer buffer = new StringBuffer();
+ HTMLPrinter.addPageProlog(buffer);
+ HTMLPrinter.addParagraph(buffer, HTMLPrinter
+ .convertToHTMLContent(message));
+ HTMLPrinter.addPageEpilog(buffer);
+ return buffer.toString();
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+
+ if (getEditor() == null)
+ return null;
+
+ IDocumentProvider provider = WebUI.getDefault()
+ .getCompilationUnitDocumentProvider();
+ IAnnotationModel model = provider.getAnnotationModel(getEditor()
+ .getEditorInput());
+
+ if (model != null) {
+ Iterator e = new JavaAnnotationIterator(model, true,
+ fAllAnnotations);
+ int layer = -1;
+ String message = null;
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+
+ AnnotationPreference preference = getAnnotationPreference(a);
+ if (preference == null
+ || !(preference.getTextPreferenceKey() != null
+ && fStore.getBoolean(preference
+ .getTextPreferenceKey()) || (preference
+ .getHighlightPreferenceKey() != null && fStore
+ .getBoolean(preference
+ .getHighlightPreferenceKey()))))
+ continue;
+
+ Position p = model.getPosition(a);
+
+ int l = fAnnotationAccess.getLayer(a);
+
+ if (l > layer
+ && p != null
+ && p.overlapsWith(hoverRegion.getOffset(), hoverRegion
+ .getLength())) {
+ String msg = a.getText();
+ if (msg != null && msg.trim().length() > 0) {
+ message = msg;
+ layer = l;
+ }
+ }
+ }
+ if (layer > -1)
+ return formatMessage(message);
+ }
+
+ return null;
+ }
+
+ /*
+ * @see IJavaEditorTextHover#setEditor(IEditorPart)
+ */
+ public void setEditor(IEditorPart editor) {
+ if (editor instanceof PHPUnitEditor)
+ super.setEditor(editor);
+ else
+ super.setEditor(null);
+ }
+
+ /**
+ * Returns the annotation preference for the given annotation.
+ *
+ * @param annotation
+ * the annotation
+ * @return the annotation preference or null
if none
+ */
+ private AnnotationPreference getAnnotationPreference(Annotation annotation) {
+
+ if (annotation.isMarkedDeleted())
+ return null;
+ return EditorsUI.getAnnotationPreferenceLookup()
+ .getAnnotationPreference(annotation);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AbstractJavaEditorTextHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AbstractJavaEditorTextHover.java
new file mode 100644
index 0000000..70669e4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AbstractJavaEditorTextHover.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.util.List;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
+import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommand;
+import org.eclipse.ui.commands.ICommandManager;
+import org.eclipse.ui.commands.IKeySequenceBinding;
+import org.eclipse.ui.keys.KeySequence;
+
+/**
+ * Abstract class for providing hover information for Java elements.
+ *
+ * @since 2.1
+ */
+public abstract class AbstractJavaEditorTextHover implements
+ IJavaEditorTextHover {
+
+ private IEditorPart fEditor;
+
+ private ICommand fCommand;
+ {
+ ICommandManager commandManager = PlatformUI.getWorkbench()
+ .getCommandSupport().getCommandManager();
+ // fCommand=
+ // commandManager.getCommand(PHPEditorActionDefinitionIds.SHOW_JAVADOC);
+ // if (!fCommand.isDefined())
+ fCommand = null;
+ }
+
+ /*
+ * @see IJavaEditorTextHover#setEditor(IEditorPart)
+ */
+ public void setEditor(IEditorPart editor) {
+ fEditor = editor;
+ }
+
+ protected IEditorPart getEditor() {
+ return fEditor;
+ }
+
+ // protected ICodeAssist getCodeAssist() {
+ // if (fEditor != null) {
+ // IEditorInput input= fEditor.getEditorInput();
+ // if (input instanceof IClassFileEditorInput) {
+ // IClassFileEditorInput cfeInput= (IClassFileEditorInput) input;
+ // return cfeInput.getClassFile();
+ // }
+ //
+ // IWorkingCopyManager manager=
+ // PHPeclipsePlugin.getDefault().getWorkingCopyManager();
+ // return manager.getWorkingCopy(input);
+ // }
+ //
+ // return null;
+ // }
+
+ /*
+ * @see ITextHover#getHoverRegion(ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ return JavaWordFinder.findWord(textViewer.getDocument(), offset);
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+
+ // ICodeAssist resolve= getCodeAssist();
+ // if (resolve != null) {
+ // try {
+ // IJavaElement[] result= null;
+ //
+ // synchronized (resolve) {
+ // result= resolve.codeSelect(hoverRegion.getOffset(),
+ // hoverRegion.getLength());
+ // }
+ //
+ // if (result == null)
+ // return null;
+ //
+ // int nResults= result.length;
+ // if (nResults == 0)
+ // return null;
+ //
+ // return getHoverInfo(result);
+ //
+ // } catch (JavaModelException x) {
+ // PHPeclipsePlugin.log(x.getStatus());
+ // }
+ // }
+ return null;
+ }
+
+ /**
+ * Provides hover information for the given Java elements.
+ *
+ * @return the hover information string
+ * @since 2.1
+ */
+ protected String getHoverInfo(IJavaElement[] javaElements) {
+ return null;
+ }
+
+ /*
+ * @see ITextHoverExtension#getHoverControlCreator()
+ * @since 3.0
+ */
+ public IInformationControlCreator getHoverControlCreator() {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ return new DefaultInformationControl(parent, SWT.NONE,
+ new HTMLTextPresenter(true),
+ getTooltipAffordanceString());
+ }
+ };
+ }
+
+ /**
+ * Returns the tool tip affordance string.
+ *
+ * @return the affordance string or null
if disabled or no
+ * key binding is defined
+ * @since 3.0
+ */
+ protected String getTooltipAffordanceString() {
+ if (!WebUI.getDefault().getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE))
+ return null;
+
+ KeySequence[] sequences = getKeySequences();
+ if (sequences == null)
+ return null;
+
+ String keySequence = sequences[0].format();
+ return JavaHoverMessages.getFormattedString(
+ "JavaTextHover.makeStickyHint", keySequence); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the array of valid key sequence bindings for the show tool tip
+ * description command.
+ *
+ * @return the array with the {@link KeySequence}s
+ *
+ * @since 3.0
+ */
+ private KeySequence[] getKeySequences() {
+ if (fCommand != null) {
+ List list = fCommand.getKeySequenceBindings();
+ if (!list.isEmpty()) {
+ KeySequence[] keySequences = new KeySequence[list.size()];
+ for (int i = 0; i < keySequences.length; i++) {
+ keySequences[i] = ((IKeySequenceBinding) list.get(i))
+ .getKeySequence();
+ }
+ return keySequences;
+ }
+ }
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpandHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpandHover.java
new file mode 100644
index 0000000..581517a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpandHover.java
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+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 net.sourceforge.phpdt.internal.ui.text.java.hover.AnnotationExpansionControl.AnnotationHoverInput;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IInformationControlCreatorExtension;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.CompositeRuler;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationHoverExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ILineRange;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRulerListener;
+import org.eclipse.jface.text.source.LineRange;
+import org.eclipse.jface.text.source.VerticalRulerEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * This class got moved here form Platform Text since it was not used there and
+ * caused discouraged access warnings. It will be moved down again once
+ * annotation roll-over support is provided by Platform Text.
+ *
+ * @since 3.2
+ */
+public class AnnotationExpandHover implements IAnnotationHover,
+ IAnnotationHoverExtension {
+
+ private class InformationControlCreator implements
+ IInformationControlCreator, IInformationControlCreatorExtension {
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
+ */
+ public IInformationControl createInformationControl(Shell parent) {
+ return new AnnotationExpansionControl(parent, SWT.NONE,
+ fAnnotationAccess);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReuse(org.eclipse.jface.text.IInformationControl)
+ */
+ public boolean canReuse(IInformationControl control) {
+ return control instanceof AnnotationExpansionControl;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReplace(org.eclipse.jface.text.IInformationControlCreator)
+ */
+ public boolean canReplace(IInformationControlCreator creator) {
+ return creator == this;
+ }
+ }
+
+ private class VerticalRulerListener implements IVerticalRulerListener {
+
+ /*
+ * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
+ */
+ public void annotationSelected(VerticalRulerEvent event) {
+ fCompositeRuler.fireAnnotationSelected(event);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationDefaultSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
+ */
+ public void annotationDefaultSelected(VerticalRulerEvent event) {
+ fCompositeRuler.fireAnnotationDefaultSelected(event);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationContextMenuAboutToShow(org.eclipse.jface.text.source.VerticalRulerEvent,
+ * org.eclipse.swt.widgets.Menu)
+ */
+ public void annotationContextMenuAboutToShow(VerticalRulerEvent event,
+ Menu menu) {
+ fCompositeRuler.fireAnnotationContextMenuAboutToShow(event, menu);
+ }
+ }
+
+ private final IInformationControlCreator fgCreator = new InformationControlCreator();
+
+ protected final IVerticalRulerListener fgListener = new VerticalRulerListener();
+
+ protected CompositeRuler fCompositeRuler;
+
+ protected IDoubleClickListener fDblClickListener;
+
+ protected IAnnotationAccess fAnnotationAccess;
+
+ /**
+ * Creates a new hover instance.
+ *
+ * @param ruler
+ * @param access
+ * @param doubleClickListener
+ */
+ public AnnotationExpandHover(CompositeRuler ruler,
+ IAnnotationAccess access, IDoubleClickListener doubleClickListener) {
+ fCompositeRuler = ruler;
+ fAnnotationAccess = access;
+ fDblClickListener = doubleClickListener;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationHover#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer,
+ * int)
+ */
+ public String getHoverInfo(ISourceViewer sourceViewer, int line) {
+ // we don't have any sensible return value as text
+ return null;
+ }
+
+ protected Object getHoverInfoForLine(ISourceViewer viewer, int line) {
+ IAnnotationModel model = viewer.getAnnotationModel();
+ IDocument document = viewer.getDocument();
+
+ if (model == null)
+ return null;
+
+ List exact = new ArrayList();
+ HashMap messagesAtPosition = new HashMap();
+
+ Iterator e = model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Annotation annotation = (Annotation) e.next();
+ Position position = model.getPosition(annotation);
+ if (position == null)
+ continue;
+
+ if (compareRulerLine(position, document, line) == 1) {
+ if (isDuplicateMessage(messagesAtPosition, position, annotation
+ .getText()))
+ continue;
+
+ exact.add(annotation);
+ }
+ }
+
+ if (exact.size() < 1)
+ return null;
+
+ sort(exact, model);
+
+ if (exact.size() > 0)
+ setLastRulerMouseLocation(viewer, line);
+
+ AnnotationHoverInput input = new AnnotationHoverInput();
+ input.fAnnotations = (Annotation[]) exact.toArray(new Annotation[0]);
+ input.fViewer = viewer;
+ input.fRulerInfo = fCompositeRuler;
+ input.fAnnotationListener = fgListener;
+ input.fDoubleClickListener = fDblClickListener;
+ input.model = model;
+
+ return input;
+ }
+
+ protected void sort(List exact, final IAnnotationModel model) {
+ class AnnotationComparator implements Comparator {
+
+ /*
+ * @see java.util.Comparator#compare(java.lang.Object,
+ * java.lang.Object)
+ */
+ public int compare(Object o1, Object o2) {
+ Annotation a1 = (Annotation) o1;
+ Annotation a2 = (Annotation) o2;
+
+ Position p1 = model.getPosition(a1);
+ Position p2 = model.getPosition(a2);
+
+ // annotation order:
+ // primary order: by position in line
+ // secondary: annotation importance
+ if (p1.offset == p2.offset)
+ return getOrder(a2) - getOrder(a1);
+ return p1.offset - p2.offset;
+ }
+ }
+
+ Collections.sort(exact, new AnnotationComparator());
+
+ }
+
+ protected int getOrder(Annotation annotation) {
+ if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
+ IAnnotationAccessExtension extension = (IAnnotationAccessExtension) fAnnotationAccess;
+ return extension.getLayer(annotation);
+ }
+ return IAnnotationAccessExtension.DEFAULT_LAYER;
+ }
+
+ protected boolean isDuplicateMessage(Map messagesAtPosition,
+ Position position, String message) {
+ if (message == null)
+ return false;
+
+ if (messagesAtPosition.containsKey(position)) {
+ Object value = messagesAtPosition.get(position);
+ if (message == null || message.equals(value))
+ return true;
+
+ if (value instanceof List) {
+ List messages = (List) value;
+ if (messages.contains(message))
+ return true;
+ messages.add(message);
+ } else {
+ ArrayList messages = new ArrayList();
+ messages.add(value);
+ messages.add(message);
+ messagesAtPosition.put(position, messages);
+ }
+ } else
+ messagesAtPosition.put(position, message);
+ return false;
+ }
+
+ protected void setLastRulerMouseLocation(ISourceViewer viewer, int line) {
+ // set last mouse activity in order to get the correct context menu
+ if (fCompositeRuler != null) {
+ StyledText st = viewer.getTextWidget();
+ if (st != null && !st.isDisposed()) {
+ if (viewer instanceof ITextViewerExtension5) {
+ int widgetLine = ((ITextViewerExtension5) viewer)
+ .modelLine2WidgetLine(line);
+ Point loc = st.getLocationAtOffset(st
+ .getOffsetAtLine(widgetLine));
+ fCompositeRuler.setLocationOfLastMouseButtonActivity(0,
+ loc.y);
+ } else if (viewer instanceof TextViewer) {
+ // TODO remove once TextViewer implements the extension
+ int widgetLine = ((TextViewer) viewer)
+ .modelLine2WidgetLine(line);
+ Point loc = st.getLocationAtOffset(st
+ .getOffsetAtLine(widgetLine));
+ fCompositeRuler.setLocationOfLastMouseButtonActivity(0,
+ loc.y);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the distance to the ruler line.
+ *
+ * @param position
+ * the position
+ * @param document
+ * the document
+ * @param line
+ * the line number
+ * @return the distance to the ruler line
+ */
+ protected int compareRulerLine(Position position, IDocument document,
+ int line) {
+
+ if (position.getOffset() > -1 && position.getLength() > -1) {
+ try {
+ int firstLine = document.getLineOfOffset(position.getOffset());
+ if (line == firstLine)
+ return 1;
+ if (firstLine <= line
+ && line <= document.getLineOfOffset(position
+ .getOffset()
+ + position.getLength()))
+ return 2;
+ } catch (BadLocationException x) {
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverControlCreator()
+ */
+ public IInformationControlCreator getHoverControlCreator() {
+ return fgCreator;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer,
+ * org.eclipse.jface.text.source.ILineRange, int)
+ */
+ public Object getHoverInfo(ISourceViewer sourceViewer,
+ ILineRange lineRange, int visibleLines) {
+ return getHoverInfoForLine(sourceViewer, lineRange.getStartLine());
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverLineRange(org.eclipse.jface.text.source.ISourceViewer,
+ * int)
+ */
+ public ILineRange getHoverLineRange(ISourceViewer viewer, int lineNumber) {
+ return new LineRange(lineNumber, 1);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#canHandleMouseCursor()
+ */
+ public boolean canHandleMouseCursor() {
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpansionControl.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpansionControl.java
new file mode 100644
index 0000000..199eaaf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpansionControl.java
@@ -0,0 +1,890 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.AbstractInformationControlManager;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IInformationControlExtension;
+import org.eclipse.jface.text.IInformationControlExtension2;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.IViewportListener;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.jface.text.source.IVerticalRulerListener;
+import org.eclipse.jface.text.source.VerticalRulerEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.MenuEvent;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseTrackAdapter;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * A control that can display a number of annotations. The control can decide
+ * how it layouts the annotations to present them to the user.
+ * GC
.
+ */
+ private final class MyPaintListener implements PaintListener {
+ /*
+ * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
+ */
+ public void paintControl(PaintEvent e) {
+ Canvas can = (Canvas) e.getSource();
+ Annotation a = ((Item) can.getData()).fAnnotation;
+ if (a != null) {
+ Rectangle rect = new Rectangle(fLayouter.getBorderWidth(),
+ fLayouter.getBorderWidth(), fLayouter
+ .getAnnotationSize(), fLayouter
+ .getAnnotationSize());
+ if (fAnnotationAccessExtension != null)
+ fAnnotationAccessExtension.paint(a, e.gc, can, rect);
+ }
+ }
+ }
+
+ /**
+ * Our own private hover manager used to shop per-item pop-ups.
+ */
+ private final class HoverManager extends AbstractInformationControlManager {
+
+ /**
+ *
+ */
+ public HoverManager() {
+ super(new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ return new DefaultInformationControl(parent);
+ }
+ });
+
+ setMargins(5, 10);
+ setAnchor(ANCHOR_BOTTOM);
+ setFallbackAnchors(new Anchor[] { ANCHOR_BOTTOM, ANCHOR_LEFT,
+ ANCHOR_RIGHT });
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractInformationControlManager#computeInformation()
+ */
+ protected void computeInformation() {
+ if (fSelection != null) {
+ Rectangle subjectArea = fSelection.canvas.getBounds();
+ Annotation annotation = fSelection.fAnnotation;
+ String msg;
+ if (annotation != null)
+ msg = annotation.getText();
+ else
+ msg = null;
+
+ setInformation(msg, subjectArea);
+ }
+ }
+
+ }
+
+ /** Model data. */
+ protected AnnotationHoverInput fInput;
+
+ /** The control's shell */
+ private Shell fShell;
+
+ /** The composite combining all the items. */
+ protected Composite fComposite;
+
+ /** The hand cursor. */
+ private Cursor fHandCursor;
+
+ /** The currently selected item, or null
if none is selected. */
+ private Item fSelection;
+
+ /** The hover manager for the per-item hovers. */
+ private HoverManager fHoverManager;
+
+ /** The annotation access extension. */
+ private IAnnotationAccessExtension fAnnotationAccessExtension;
+
+ /* listener legion */
+ private final MyPaintListener fPaintListener;
+
+ private final MyMouseTrackListener fMouseTrackListener;
+
+ private final MyMouseListener fMouseListener;
+
+ private final MyMenuDetectListener fMenuDetectListener;
+
+ private final DisposeListener fDisposeListener;
+
+ private final IViewportListener fViewportListener;
+
+ private LinearLayouter fLayouter;
+
+ /**
+ * Creates a new control.
+ *
+ * @param parent
+ * @param shellStyle
+ * @param access
+ */
+ public AnnotationExpansionControl(Shell parent, int shellStyle,
+ IAnnotationAccess access) {
+ fPaintListener = new MyPaintListener();
+ fMouseTrackListener = new MyMouseTrackListener();
+ fMouseListener = new MyMouseListener();
+ fMenuDetectListener = new MyMenuDetectListener();
+ fDisposeListener = new MyDisposeListener();
+ fViewportListener = new IViewportListener() {
+
+ public void viewportChanged(int verticalOffset) {
+ dispose();
+ }
+
+ };
+ fLayouter = new LinearLayouter();
+
+ if (access instanceof IAnnotationAccessExtension)
+ fAnnotationAccessExtension = (IAnnotationAccessExtension) access;
+
+ fShell = new Shell(parent, shellStyle | SWT.NO_FOCUS | SWT.ON_TOP);
+ Display display = fShell.getDisplay();
+ fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+ fComposite = new Composite(fShell, SWT.NO_FOCUS | SWT.NO_REDRAW_RESIZE
+ | SWT.NO_TRIM);
+ // fComposite= new Composite(fShell, SWT.NO_FOCUS | SWT.NO_REDRAW_RESIZE
+ // | SWT.NO_TRIM | SWT.V_SCROLL);
+
+ GridLayout layout = new GridLayout(1, true);
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ fShell.setLayout(layout);
+
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.heightHint = fLayouter.getAnnotationSize() + 2
+ * fLayouter.getBorderWidth() + 4;
+ fComposite.setLayoutData(data);
+ fComposite.addMouseTrackListener(new MouseTrackAdapter() {
+
+ public void mouseExit(MouseEvent e) {
+ if (fComposite == null)
+ return;
+ Control[] children = fComposite.getChildren();
+ Rectangle bounds = null;
+ for (int i = 0; i < children.length; i++) {
+ if (bounds == null)
+ bounds = children[i].getBounds();
+ else
+ bounds.add(children[i].getBounds());
+ if (bounds.contains(e.x, e.y))
+ return;
+ }
+
+ // if none of the children contains the event, we leave the
+ // popup
+ dispose();
+ }
+
+ });
+
+ // fComposite.getVerticalBar().addListener(SWT.Selection, new Listener()
+ // {
+ //
+ // public void handleEvent(Event event) {
+ // Rectangle bounds= fShell.getBounds();
+ // int x= bounds.x - fLayouter.getAnnotationSize() -
+ // fLayouter.getBorderWidth();
+ // int y= bounds.y;
+ // fShell.setBounds(x, y, bounds.width, bounds.height);
+ // }
+ //
+ // });
+
+ fHandCursor = new Cursor(display, SWT.CURSOR_HAND);
+ fShell.setCursor(fHandCursor);
+ fComposite.setCursor(fHandCursor);
+
+ setInfoSystemColor();
+ }
+
+ private void setInfoSystemColor() {
+ Display display = fShell.getDisplay();
+ setForegroundColor(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ setBackgroundColor(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String)
+ */
+ public void setInformation(String information) {
+ setInput(null);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
+ */
+ public void setInput(Object input) {
+ if (fInput != null && fInput.fViewer != null)
+ fInput.fViewer.removeViewportListener(fViewportListener);
+
+ if (input instanceof AnnotationHoverInput)
+ fInput = (AnnotationHoverInput) input;
+ else
+ fInput = null;
+
+ inputChanged(fInput, null);
+ }
+
+ protected void inputChanged(Object newInput, Object newSelection) {
+ refresh();
+ }
+
+ protected void refresh() {
+ adjustItemNumber();
+
+ if (fInput == null)
+ return;
+
+ if (fInput.fAnnotations == null)
+ return;
+
+ if (fInput.fViewer != null)
+ fInput.fViewer.addViewportListener(fViewportListener);
+
+ fShell.setRegion(fLayouter.getShellRegion(fInput.fAnnotations.length));
+
+ Layout layout = fLayouter.getLayout(fInput.fAnnotations.length);
+ fComposite.setLayout(layout);
+
+ Control[] children = fComposite.getChildren();
+ for (int i = 0; i < fInput.fAnnotations.length; i++) {
+ Canvas canvas = (Canvas) children[i];
+ Item item = new Item();
+ item.canvas = canvas;
+ item.fAnnotation = fInput.fAnnotations[i];
+ canvas.setData(item);
+ canvas.redraw();
+ }
+
+ }
+
+ protected void adjustItemNumber() {
+ if (fComposite == null)
+ return;
+
+ Control[] children = fComposite.getChildren();
+ int oldSize = children.length;
+ int newSize = fInput == null ? 0 : fInput.fAnnotations.length;
+
+ Display display = fShell.getDisplay();
+
+ // add missing items
+ for (int i = oldSize; i < newSize; i++) {
+ Canvas canvas = new Canvas(fComposite, SWT.NONE);
+ Object gridData = fLayouter.getLayoutData();
+ canvas.setLayoutData(gridData);
+ canvas.setBackground(display
+ .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ canvas.addPaintListener(fPaintListener);
+
+ canvas.addMouseTrackListener(fMouseTrackListener);
+
+ canvas.addMouseListener(fMouseListener);
+
+ canvas.addListener(SWT.MenuDetect, fMenuDetectListener);
+
+ canvas.addDisposeListener(fDisposeListener);
+ }
+
+ // dispose of exceeding resources
+ for (int i = oldSize; i > newSize; i--) {
+ Item item = (Item) children[i - 1].getData();
+ item.deselect();
+ children[i - 1].dispose();
+ }
+
+ }
+
+ /*
+ * @see IInformationControl#setVisible(boolean)
+ */
+ public void setVisible(boolean visible) {
+ fShell.setVisible(visible);
+ }
+
+ /*
+ * @see IInformationControl#dispose()
+ */
+ public void dispose() {
+ if (fShell != null) {
+ if (!fShell.isDisposed())
+ fShell.dispose();
+ fShell = null;
+ fComposite = null;
+ if (fHandCursor != null)
+ fHandCursor.dispose();
+ fHandCursor = null;
+ if (fHoverManager != null)
+ fHoverManager.dispose();
+ fHoverManager = null;
+ fSelection = null;
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlExtension#hasContents()
+ */
+ public boolean hasContents() {
+ return fInput.fAnnotations != null && fInput.fAnnotations.length > 0;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int,
+ * int)
+ */
+ public void setSizeConstraints(int maxWidth, int maxHeight) {
+ // fMaxWidth= maxWidth;
+ // fMaxHeight= maxHeight;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControl#computeSizeHint()
+ */
+ public Point computeSizeHint() {
+ return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ }
+
+ /*
+ * @see IInformationControl#setLocation(Point)
+ */
+ public void setLocation(Point location) {
+ fShell.setLocation(location);
+ }
+
+ /*
+ * @see IInformationControl#setSize(int, int)
+ */
+ public void setSize(int width, int height) {
+ fShell.setSize(width, height);
+ }
+
+ /*
+ * @see IInformationControl#addDisposeListener(DisposeListener)
+ */
+ public void addDisposeListener(DisposeListener listener) {
+ fShell.addDisposeListener(listener);
+ }
+
+ /*
+ * @see IInformationControl#removeDisposeListener(DisposeListener)
+ */
+ public void removeDisposeListener(DisposeListener listener) {
+ fShell.removeDisposeListener(listener);
+ }
+
+ /*
+ * @see IInformationControl#setForegroundColor(Color)
+ */
+ public void setForegroundColor(Color foreground) {
+ fComposite.setForeground(foreground);
+ }
+
+ /*
+ * @see IInformationControl#setBackgroundColor(Color)
+ */
+ public void setBackgroundColor(Color background) {
+ fComposite.setBackground(background);
+ }
+
+ /*
+ * @see IInformationControl#isFocusControl()
+ */
+ public boolean isFocusControl() {
+ if (fComposite.isFocusControl())
+ return true;
+
+ Control[] children = fComposite.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ if (children[i].isFocusControl())
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * @see IInformationControl#setFocus()
+ */
+ public void setFocus() {
+ fShell.forceFocus();
+ }
+
+ /*
+ * @see IInformationControl#addFocusListener(FocusListener)
+ */
+ public void addFocusListener(FocusListener listener) {
+ fShell.addFocusListener(listener);
+ }
+
+ /*
+ * @see IInformationControl#removeFocusListener(FocusListener)
+ */
+ public void removeFocusListener(FocusListener listener) {
+ fShell.removeFocusListener(listener);
+ }
+
+ private StyleRange[] setViewerBackground(Annotation annotation) {
+ StyledText text = fInput.fViewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return null;
+
+ Display disp = text.getDisplay();
+
+ Position pos = fInput.model.getPosition(annotation);
+ if (pos == null)
+ return null;
+
+ IRegion region = ((TextViewer) fInput.fViewer)
+ .modelRange2WidgetRange(new Region(pos.offset, pos.length));
+ if (region == null)
+ return null;
+
+ StyleRange[] ranges = text.getStyleRanges(region.getOffset(), region
+ .getLength());
+
+ List undoRanges = new ArrayList(ranges.length);
+ for (int i = 0; i < ranges.length; i++) {
+ undoRanges.add(ranges[i].clone());
+ }
+
+ int offset = region.getOffset();
+ StyleRange current = undoRanges.size() > 0 ? (StyleRange) undoRanges
+ .get(0) : null;
+ int curStart = current != null ? current.start : region.getOffset()
+ + region.getLength();
+ int curEnd = current != null ? current.start + current.length : -1;
+ int index = 0;
+
+ // fill no-style regions
+ while (curEnd < region.getOffset() + region.getLength()) {
+ // add empty range
+ if (curStart > offset) {
+ StyleRange undoRange = new StyleRange(offset,
+ curStart - offset, null, null);
+ undoRanges.add(index, undoRange);
+ index++;
+ }
+
+ // step
+ index++;
+ if (index < undoRanges.size()) {
+ offset = curEnd;
+ current = (StyleRange) undoRanges.get(index);
+ curStart = current.start;
+ curEnd = current.start + current.length;
+ } else if (index == undoRanges.size()) {
+ // last one
+ offset = curEnd;
+ current = null;
+ curStart = region.getOffset() + region.getLength();
+ curEnd = -1;
+ } else
+ curEnd = region.getOffset() + region.getLength();
+ }
+
+ // create modified styles (with background)
+ List shadedRanges = new ArrayList(undoRanges.size());
+ for (Iterator it = undoRanges.iterator(); it.hasNext();) {
+ StyleRange range = (StyleRange) ((StyleRange) it.next()).clone();
+ shadedRanges.add(range);
+ range.background = getHighlightColor(disp);
+ }
+
+ // set the ranges one by one
+ for (Iterator iter = shadedRanges.iterator(); iter.hasNext();) {
+ text.setStyleRange((StyleRange) iter.next());
+
+ }
+
+ return (StyleRange[]) undoRanges.toArray(undoRanges
+ .toArray(new StyleRange[0]));
+ }
+
+ private void resetViewerBackground(StyleRange[] oldRanges) {
+
+ if (oldRanges == null)
+ return;
+
+ if (fInput == null)
+ return;
+
+ StyledText text = fInput.fViewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+
+ // set the ranges one by one
+ for (int i = 0; i < oldRanges.length; i++) {
+ text.setStyleRange(oldRanges[i]);
+ }
+ }
+
+ private Color getHighlightColor(Display disp) {
+ return disp.getSystemColor(SWT.COLOR_GRAY);
+ }
+
+ private Color getSelectionColor(Display disp) {
+ return disp.getSystemColor(SWT.COLOR_GRAY);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationHover.java
new file mode 100644
index 0000000..d18653e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationHover.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.internal.ui.text.HTMLPrinter;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.JavaAnnotationIterator;
+import net.sourceforge.phpeclipse.phpeditor.PHPTextHover;
+import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+
+public class AnnotationHover extends AbstractJavaEditorTextHover {
+
+ // private IPreferenceStore fStore =
+ // PHPeclipsePlugin.getDefault().getPreferenceStore();
+ private IPreferenceStore fStore = EditorsUI.getPreferenceStore();
+
+ private DefaultMarkerAnnotationAccess fAnnotationAccess = new DefaultMarkerAnnotationAccess();
+
+ private PHPTextHover fPHPTextHover = null;
+
+ /*
+ * Formats a message as HTML text.
+ */
+ private String formatMessage(String message) {
+ StringBuffer buffer = new StringBuffer();
+ HTMLPrinter.addPageProlog(buffer);
+ HTMLPrinter.addParagraph(buffer, message); // HTMLPrinter.convertToHTMLContent(message));
+ HTMLPrinter.addPageEpilog(buffer);
+ return buffer.toString();
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+
+ if (getEditor() == null)
+ return null;
+
+ IDocumentProvider provider = WebUI.getDefault()
+ .getCompilationUnitDocumentProvider();
+ IAnnotationModel model = provider.getAnnotationModel(getEditor()
+ .getEditorInput());
+ String message = null;
+ if (model != null) {
+ Iterator e = new JavaAnnotationIterator(model, true);
+ int layer = -1;
+
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+
+ AnnotationPreference preference = getAnnotationPreference(a);
+ if (preference == null
+ || !(fStore.getBoolean(preference
+ .getTextPreferenceKey()) || (preference
+ .getHighlightPreferenceKey() != null && fStore
+ .getBoolean(preference
+ .getHighlightPreferenceKey()))))
+ continue;
+
+ Position p = model.getPosition(a);
+
+ int l = fAnnotationAccess.getLayer(a);
+
+ if (l > layer
+ && p != null
+ && p.overlapsWith(hoverRegion.getOffset(), hoverRegion
+ .getLength())) {
+ String msg = a.getText();
+ if (msg != null && msg.trim().length() > 0) {
+ message = msg;
+ layer = l;
+ }
+ }
+ }
+ if (layer > -1)
+ return formatMessage(message);
+ }
+ // Added as long as the above doesn't work
+ if (fPHPTextHover != null) {
+ message = fPHPTextHover.getHoverInfo(textViewer, hoverRegion);
+ if (message != null) {
+ return formatMessage(message);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see IJavaEditorTextHover#setEditor(IEditorPart)
+ */
+ public void setEditor(IEditorPart editor) {
+ if (editor instanceof PHPUnitEditor) {
+ super.setEditor(editor);
+ if (editor != null) {
+ IEditorInput editorInput = editor.getEditorInput();
+ if (editorInput instanceof IFileEditorInput) {
+ try {
+ IFile f = ((IFileEditorInput) editorInput).getFile();
+ fPHPTextHover = new PHPTextHover(f.getProject());
+ return;
+ } catch (NullPointerException e) {
+ // this exception occurs, if getTextHover is called by
+ // preference pages !
+ }
+ }
+ }
+ fPHPTextHover = new PHPTextHover(null);
+ } else {
+ super.setEditor(null);
+ }
+ }
+
+ /**
+ * Returns the annotation preference for the given annotation.
+ *
+ * @param annotation
+ * the annotation
+ * @return the annotation preference or null
if none
+ */
+ private AnnotationPreference getAnnotationPreference(Annotation annotation) {
+
+ if (annotation.isMarkedDeleted())
+ return null;
+ return EditorsUI.getAnnotationPreferenceLookup()
+ .getAnnotationPreference(annotation);
+ }
+
+ static boolean isJavaProblemHover(String id) {
+ return PreferenceConstants.ID_PROBLEM_HOVER.equals(id);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java
new file mode 100644
index 0000000..97b1b75
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextHoverExtension;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.information.IInformationProviderExtension2;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Caution: this implementation is a layer breaker and contains some "shortcuts"
+ */
+public class BestMatchHover extends AbstractJavaEditorTextHover implements
+ ITextHoverExtension, IInformationProviderExtension2 {
+
+ private List fTextHoverSpecifications;
+
+ private List fInstantiatedTextHovers;
+
+ private ITextHover fBestHover;
+
+ public BestMatchHover() {
+ installTextHovers();
+ }
+
+ public BestMatchHover(IEditorPart editor) {
+ this();
+ setEditor(editor);
+ }
+
+ /**
+ * Installs all text hovers.
+ */
+ private void installTextHovers() {
+
+ // initialize lists - indicates that the initialization happened
+ fTextHoverSpecifications = new ArrayList(2);
+ fInstantiatedTextHovers = new ArrayList(2);
+
+ // populate list
+ JavaEditorTextHoverDescriptor[] hoverDescs = WebUI
+ .getDefault().getJavaEditorTextHoverDescriptors();
+ for (int i = 0; i < hoverDescs.length; i++) {
+ // ensure that we don't add ourselves to the list
+ if (!PreferenceConstants.ID_BESTMATCH_HOVER.equals(hoverDescs[i]
+ .getId()))
+ fTextHoverSpecifications.add(hoverDescs[i]);
+ }
+ }
+
+ private void checkTextHovers() {
+ if (fTextHoverSpecifications.size() == 0)
+ return;
+
+ for (Iterator iterator = new ArrayList(fTextHoverSpecifications)
+ .iterator(); iterator.hasNext();) {
+ JavaEditorTextHoverDescriptor spec = (JavaEditorTextHoverDescriptor) iterator
+ .next();
+
+ IJavaEditorTextHover hover = spec.createTextHover();
+ if (hover != null) {
+ hover.setEditor(getEditor());
+ addTextHover(hover);
+ fTextHoverSpecifications.remove(spec);
+ }
+ }
+ }
+
+ protected void addTextHover(ITextHover hover) {
+ if (!fInstantiatedTextHovers.contains(hover))
+ fInstantiatedTextHovers.add(hover);
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+
+ checkTextHovers();
+ fBestHover = null;
+
+ if (fInstantiatedTextHovers == null)
+ return null;
+
+ for (Iterator iterator = fInstantiatedTextHovers.iterator(); iterator
+ .hasNext();) {
+ ITextHover hover = (ITextHover) iterator.next();
+
+ String s = hover.getHoverInfo(textViewer, hoverRegion);
+ if (s != null && s.trim().length() > 0) {
+ fBestHover = hover;
+ return s;
+ }
+ }
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
+ * @since 3.0
+ */
+ public IInformationControlCreator getHoverControlCreator() {
+ if (fBestHover instanceof ITextHoverExtension)
+ return ((ITextHoverExtension) fBestHover).getHoverControlCreator();
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.information.IInformationProviderExtension2#getInformationPresenterControlCreator()
+ * @since 3.0
+ */
+ public IInformationControlCreator getInformationPresenterControlCreator() {
+ if (fBestHover instanceof IInformationProviderExtension2)
+ return ((IInformationProviderExtension2) fBestHover)
+ .getInformationPresenterControlCreator();
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaEditorTextHoverDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaEditorTextHoverDescriptor.java
new file mode 100644
index 0000000..3d65241
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaEditorTextHoverDescriptor.java
@@ -0,0 +1,366 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.EditorUtility;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.swt.SWT;
+import org.osgi.framework.Bundle;
+
+/**
+ * Describes a Java editor text hover.
+ *
+ * @since 2.1
+ */
+public class JavaEditorTextHoverDescriptor implements Comparable {
+
+ private static final String JAVA_EDITOR_TEXT_HOVER_EXTENSION_POINT = "net.sourceforge.phpeclipse.phpEditorTextHovers"; //$NON-NLS-1$
+
+ private static final String HOVER_TAG = "hover"; //$NON-NLS-1$
+
+ private static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$
+
+ private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+
+ private static final String LABEL_ATTRIBUTE = "label"; //$NON-NLS-1$
+
+ private static final String ACTIVATE_PLUG_IN_ATTRIBUTE = "activate"; //$NON-NLS-1$
+
+ private static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
+
+ public static final String NO_MODIFIER = "0"; //$NON-NLS-1$
+
+ public static final String DISABLED_TAG = "!"; //$NON-NLS-1$
+
+ public static final String VALUE_SEPARATOR = ";"; //$NON-NLS-1$
+
+ private int fStateMask;
+
+ private String fModifierString;
+
+ private boolean fIsEnabled;
+
+ private IConfigurationElement fElement;
+
+ /**
+ * Returns all Java editor text hovers contributed to the workbench.
+ */
+ public static JavaEditorTextHoverDescriptor[] getContributedHovers() {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IConfigurationElement[] elements = registry
+ .getConfigurationElementsFor(JAVA_EDITOR_TEXT_HOVER_EXTENSION_POINT);
+ JavaEditorTextHoverDescriptor[] hoverDescs = createDescriptors(elements);
+ initializeFromPreferences(hoverDescs);
+ return hoverDescs;
+ }
+
+ /**
+ * Computes the state mask for the given modifier string.
+ *
+ * @param modifiers
+ * the string with the modifiers, separated by '+', '-', ';', ','
+ * or '.'
+ * @return the state mask or -1 if the input is invalid
+ */
+ public static int computeStateMask(String modifiers) {
+ if (modifiers == null)
+ return -1;
+
+ if (modifiers.length() == 0)
+ return SWT.NONE;
+
+ int stateMask = 0;
+ StringTokenizer modifierTokenizer = new StringTokenizer(modifiers,
+ ",;.:+-* "); //$NON-NLS-1$
+ while (modifierTokenizer.hasMoreTokens()) {
+ int modifier = EditorUtility
+ .findLocalizedModifier(modifierTokenizer.nextToken());
+ if (modifier == 0 || (stateMask & modifier) == modifier)
+ return -1;
+ stateMask = stateMask | modifier;
+ }
+ return stateMask;
+ }
+
+ /**
+ * Creates a new Java Editor text hover descriptor from the given
+ * configuration element.
+ */
+ private JavaEditorTextHoverDescriptor(IConfigurationElement element) {
+ Assert.isNotNull(element);
+ fElement = element;
+ }
+
+ /**
+ * Creates the Java editor text hover.
+ */
+ public IJavaEditorTextHover createTextHover() {
+ String pluginId = fElement.getDeclaringExtension().getNamespace();
+ boolean isHoversPlugInActivated = Platform.getBundle(pluginId)
+ .getState() == Bundle.ACTIVE;
+ if (isHoversPlugInActivated || canActivatePlugIn()) {
+ try {
+ return (IJavaEditorTextHover) fElement
+ .createExecutableExtension(CLASS_ATTRIBUTE);
+ } catch (CoreException x) {
+ WebUI.log(new Status(IStatus.ERROR, WebUI
+ .getPluginId(), 0, JavaHoverMessages
+ .getString("JavaTextHover.createTextHover"), null)); //$NON-NLS-1$
+ }
+ }
+
+ return null;
+ }
+
+ // ---- XML Attribute accessors
+ // ---------------------------------------------
+
+ /**
+ * Returns the hover's id.
+ */
+ public String getId() {
+ return fElement.getAttribute(ID_ATTRIBUTE);
+ }
+
+ /**
+ * Returns the hover's class name.
+ */
+ public String getHoverClassName() {
+ return fElement.getAttribute(CLASS_ATTRIBUTE);
+ }
+
+ /**
+ * Returns the hover's label.
+ */
+ public String getLabel() {
+ String label = fElement.getAttribute(LABEL_ATTRIBUTE);
+ if (label != null)
+ return label;
+
+ // Return simple class name
+ label = getHoverClassName();
+ int lastDot = label.lastIndexOf('.');
+ if (lastDot >= 0 && lastDot < label.length() - 1)
+ return label.substring(lastDot + 1);
+ else
+ return label;
+ }
+
+ /**
+ * Returns the hover's description.
+ *
+ * @return the hover's description or null
if not provided
+ */
+ public String getDescription() {
+ return fElement.getAttribute(DESCRIPTION_ATTRIBUTE);
+ }
+
+ public boolean canActivatePlugIn() {
+ return Boolean.valueOf(
+ fElement.getAttribute(ACTIVATE_PLUG_IN_ATTRIBUTE))
+ .booleanValue();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == null || !obj.getClass().equals(this.getClass())
+ || getId() == null)
+ return false;
+ return getId().equals(((JavaEditorTextHoverDescriptor) obj).getId());
+ }
+
+ public int hashCode() {
+ return getId().hashCode();
+ }
+
+ /*
+ * Implements a method from IComparable
+ */
+ public int compareTo(Object o) {
+ return Collator.getInstance().compare(getLabel(),
+ ((JavaEditorTextHoverDescriptor) o).getLabel());
+ }
+
+ // /**
+ // * @param descriptor a JavaEditorTextHoverDescriptor
+ // * @return true
if this contributed hover depends on the
+ // other one
+ // */
+ // public boolean dependsOn(JavaEditorTextHoverDescriptor descriptor) {
+ // if (descriptor == null)
+ // return false;
+ //
+ // IPluginDescriptor thisPluginDescriptor=
+ // fElement.getDeclaringExtension().getDeclaringPluginDescriptor();
+ // IPluginDescriptor otherPluginDescriptor=
+ // descriptor.fElement.getDeclaringExtension().getDeclaringPluginDescriptor();
+ // return dependsOn(thisPluginDescriptor, otherPluginDescriptor);
+ // }
+
+ // private boolean dependsOn(IPluginDescriptor descriptor0,
+ // IPluginDescriptor descriptor1) {
+ //
+ // IPluginRegistry registry= Platform.getPluginRegistry();
+ // IPluginPrerequisite[] prerequisites=
+ // descriptor0.getPluginPrerequisites();
+ //
+ // for (int i= 0; i < prerequisites.length; i++) {
+ // IPluginPrerequisite prerequisite= prerequisites[i];
+ // String id= prerequisite.getUniqueIdentifier();
+ // IPluginDescriptor descriptor= registry.getPluginDescriptor(id);
+ //
+ // if (descriptor != null && (descriptor.equals(descriptor1) ||
+ // dependsOn(descriptor, descriptor1)))
+ // return true;
+ // }
+ //
+ // return false;
+ // }
+
+ private static JavaEditorTextHoverDescriptor[] createDescriptors(
+ IConfigurationElement[] elements) {
+ List result = new ArrayList(elements.length);
+ for (int i = 0; i < elements.length; i++) {
+ IConfigurationElement element = elements[i];
+ if (HOVER_TAG.equals(element.getName())) {
+ JavaEditorTextHoverDescriptor desc = new JavaEditorTextHoverDescriptor(
+ element);
+ result.add(desc);
+ }
+ }
+ Collections.sort(result);
+ return (JavaEditorTextHoverDescriptor[]) result
+ .toArray(new JavaEditorTextHoverDescriptor[result.size()]);
+ }
+
+ private static void initializeFromPreferences(
+ JavaEditorTextHoverDescriptor[] hovers) {
+ String compiledTextHoverModifiers = WebUI.getDefault()
+ .getPreferenceStore().getString(
+ PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
+
+ StringTokenizer tokenizer = new StringTokenizer(
+ compiledTextHoverModifiers, VALUE_SEPARATOR);
+ HashMap idToModifier = new HashMap(tokenizer.countTokens() / 2);
+
+ while (tokenizer.hasMoreTokens()) {
+ String id = tokenizer.nextToken();
+ if (tokenizer.hasMoreTokens())
+ idToModifier.put(id, tokenizer.nextToken());
+ }
+
+ String compiledTextHoverModifierMasks = WebUI.getDefault()
+ .getPreferenceStore().getString(
+ PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
+
+ tokenizer = new StringTokenizer(compiledTextHoverModifierMasks,
+ VALUE_SEPARATOR);
+ HashMap idToModifierMask = new HashMap(tokenizer.countTokens() / 2);
+
+ while (tokenizer.hasMoreTokens()) {
+ String id = tokenizer.nextToken();
+ if (tokenizer.hasMoreTokens())
+ idToModifierMask.put(id, tokenizer.nextToken());
+ }
+
+ for (int i = 0; i < hovers.length; i++) {
+ String modifierString = (String) idToModifier
+ .get(hovers[i].getId());
+ boolean enabled = true;
+ if (modifierString == null)
+ modifierString = DISABLED_TAG;
+
+ if (modifierString.startsWith(DISABLED_TAG)) {
+ enabled = false;
+ modifierString = modifierString.substring(1);
+ }
+
+ if (modifierString.equals(NO_MODIFIER))
+ modifierString = ""; //$NON-NLS-1$
+
+ hovers[i].fModifierString = modifierString;
+ hovers[i].fIsEnabled = enabled;
+ hovers[i].fStateMask = computeStateMask(modifierString);
+ if (hovers[i].fStateMask == -1) {
+ // Fallback: use stored modifier masks
+ try {
+ hovers[i].fStateMask = Integer
+ .parseInt((String) idToModifierMask.get(hovers[i]
+ .getId()));
+ } catch (NumberFormatException ex) {
+ hovers[i].fStateMask = -1;
+ }
+ // Fix modifier string
+ int stateMask = hovers[i].fStateMask;
+ if (stateMask == -1)
+ hovers[i].fModifierString = ""; //$NON-NLS-1$
+ else
+ hovers[i].fModifierString = EditorUtility
+ .getModifierString(stateMask);
+ }
+ }
+ }
+
+ /**
+ * Returns the configured modifier getStateMask for this hover.
+ *
+ * @return the hover modifier stateMask or -1 if no hover is configured
+ */
+ public int getStateMask() {
+ return fStateMask;
+ }
+
+ /**
+ * Returns the modifier String as set in the preference store.
+ *
+ * @return the modifier string
+ */
+ public String getModifierString() {
+ return fModifierString;
+ }
+
+ /**
+ * Returns whether this hover is enabled or not.
+ *
+ * @return true
if enabled
+ */
+ public boolean isEnabled() {
+ return fIsEnabled;
+ }
+
+ /**
+ * Returns this hover descriptors configuration element.
+ *
+ * @return the configuration element
+ * @since 3.0
+ */
+ public IConfigurationElement getConfigurationElement() {
+ return fElement;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaEditorTextHoverProxy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaEditorTextHoverProxy.java
new file mode 100644
index 0000000..7304174
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaEditorTextHoverProxy.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Proxy for JavaEditorTextHovers.
+ *
+ * @since 2.1
+ */
+public class JavaEditorTextHoverProxy extends AbstractJavaEditorTextHover {
+
+ private JavaEditorTextHoverDescriptor fHoverDescriptor;
+
+ private IJavaEditorTextHover fHover;
+
+ public JavaEditorTextHoverProxy(JavaEditorTextHoverDescriptor descriptor,
+ IEditorPart editor) {
+ fHoverDescriptor = descriptor;
+ setEditor(editor);
+ }
+
+ /*
+ * @see IJavaEditorTextHover#setEditor(IEditorPart)
+ */
+ public void setEditor(IEditorPart editor) {
+ super.setEditor(editor);
+
+ if (fHover != null)
+ fHover.setEditor(getEditor());
+ }
+
+ public boolean isEnabled() {
+ return true;
+ }
+
+ /*
+ * @see ITextHover#getHoverRegion(ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ if (!isEnabled() || fHoverDescriptor == null)
+ return null;
+
+ if (isCreated() || createHover())
+ return fHover.getHoverRegion(textViewer, offset);
+ else
+ return null;
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+ if (!isEnabled() || fHoverDescriptor == null)
+ return null;
+
+ if (isCreated() || createHover())
+ return fHover.getHoverInfo(textViewer, hoverRegion);
+ else
+ return null;
+ }
+
+ private boolean isCreated() {
+ return fHover != null;
+ }
+
+ private boolean createHover() {
+ fHover = fHoverDescriptor.createTextHover();
+ if (fHover != null)
+ fHover.setEditor(getEditor());
+ return isCreated();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaExpandHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaExpandHover.java
new file mode 100644
index 0000000..cd37c94
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaExpandHover.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.java.hover.AnnotationExpansionControl.AnnotationHoverInput;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.IJavaAnnotation;
+import net.sourceforge.phpeclipse.phpeditor.JavaMarkerAnnotation;
+import net.sourceforge.phpeclipse.phpeditor.PHPDocumentProvider.ProblemAnnotation;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControlExtension2;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.CompositeRuler;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationPresentation;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.ImageUtilities;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.AnnotationPreferenceLookup;
+
+/**
+ *
+ *
+ * @since 3.0
+ */
+public class JavaExpandHover extends AnnotationExpandHover {
+
+ /** Id of the no breakpoint fake annotation */
+ public static final String NO_BREAKPOINT_ANNOTATION = "net.sourceforge.phpdt.internal.ui.NoBreakpointAnnotation"; //$NON-NLS-1$
+
+ private static class NoBreakpointAnnotation extends Annotation implements
+ IAnnotationPresentation {
+
+ public NoBreakpointAnnotation() {
+ super(NO_BREAKPOINT_ANNOTATION, false, JavaHoverMessages
+ .getString("NoBreakpointAnnotation.addBreakpoint"));
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationPresentation#paint(org.eclipse.swt.graphics.GC,
+ * org.eclipse.swt.widgets.Canvas,
+ * org.eclipse.swt.graphics.Rectangle)
+ */
+ public void paint(GC gc, Canvas canvas, Rectangle bounds) {
+ // draw affordance so the user know she can click here to get a
+ // breakpoint
+ Image fImage = PHPUiImages.get(PHPUiImages.IMG_FIELD_PUBLIC);
+ ImageUtilities.drawImage(fImage, gc, canvas, bounds, SWT.CENTER);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationPresentation#getLayer()
+ */
+ public int getLayer() {
+ return IAnnotationPresentation.DEFAULT_LAYER;
+ }
+ }
+
+ private AnnotationPreferenceLookup fLookup = new AnnotationPreferenceLookup();
+
+ private IPreferenceStore fStore = WebUI.getDefault()
+ .getCombinedPreferenceStore();
+
+ public JavaExpandHover(CompositeRuler ruler, IAnnotationAccess access,
+ IDoubleClickListener doubleClickListener) {
+ super(ruler, access, doubleClickListener);
+ }
+
+ /*
+ * @see org.eclipse.ui.internal.texteditor.AnnotationExpandHover#getHoverInfoForLine(org.eclipse.jface.text.source.ISourceViewer,
+ * int)
+ */
+ protected Object getHoverInfoForLine(final ISourceViewer viewer,
+ final int line) {
+ final boolean showTemporaryProblems = PreferenceConstants
+ .getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_CORRECTION_INDICATION);
+ IAnnotationModel model = viewer.getAnnotationModel();
+ IDocument document = viewer.getDocument();
+
+ if (model == null)
+ return null;
+
+ List exact = new ArrayList();
+ HashMap messagesAtPosition = new HashMap();
+
+ Iterator e = model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Annotation annotation = (Annotation) e.next();
+
+ if (fAnnotationAccess instanceof IAnnotationAccessExtension)
+ if (!((IAnnotationAccessExtension) fAnnotationAccess)
+ .isPaintable(annotation))
+ continue;
+
+ if (annotation instanceof IJavaAnnotation
+ && !isIncluded((IJavaAnnotation) annotation,
+ showTemporaryProblems))
+ continue;
+
+ AnnotationPreference pref = fLookup
+ .getAnnotationPreference(annotation);
+ if (pref != null) {
+ String key = pref.getVerticalRulerPreferenceKey();
+ if (key != null && !fStore.getBoolean(key))
+ continue;
+ }
+
+ Position position = model.getPosition(annotation);
+ if (position == null)
+ continue;
+
+ if (compareRulerLine(position, document, line) == 1) {
+
+ if (isDuplicateMessage(messagesAtPosition, position, annotation
+ .getText()))
+ continue;
+
+ exact.add(annotation);
+ }
+ }
+
+ sort(exact, model);
+
+ if (exact.size() > 0)
+ setLastRulerMouseLocation(viewer, line);
+
+ if (exact.size() > 0) {
+ Annotation first = (Annotation) exact.get(0);
+ if (!isBreakpointAnnotation(first))
+ exact.add(0, new NoBreakpointAnnotation());
+ }
+
+ if (exact.size() <= 1)
+ return null;
+
+ AnnotationHoverInput input = new AnnotationHoverInput();
+ input.fAnnotations = (Annotation[]) exact.toArray(new Annotation[0]);
+ input.fViewer = viewer;
+ input.fRulerInfo = fCompositeRuler;
+ input.fAnnotationListener = fgListener;
+ input.fDoubleClickListener = fDblClickListener;
+ input.redoAction = new AnnotationExpansionControl.ICallback() {
+
+ public void run(IInformationControlExtension2 control) {
+ control.setInput(getHoverInfoForLine(viewer, line));
+ }
+
+ };
+ input.model = model;
+
+ return input;
+ }
+
+ private boolean isIncluded(IJavaAnnotation annotation,
+ boolean showTemporaryProblems) {
+
+ // XXX: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=138601
+ if (annotation instanceof ProblemAnnotation
+ && JavaMarkerAnnotation.TASK_ANNOTATION_TYPE.equals(annotation
+ .getType()))
+ return false;
+
+ if (!annotation.isProblem())
+ return true;
+
+ if (annotation.isMarkedDeleted() && !annotation.hasOverlay())
+ return true;
+
+ if (annotation.hasOverlay() && !annotation.isMarkedDeleted())
+ return true;
+
+ if (annotation.hasOverlay())
+ return (!isIncluded(annotation.getOverlay(), showTemporaryProblems));
+
+ return showTemporaryProblems; // &&
+ // JavaCorrectionProcessor.hasCorrections((Annotation)annotation);
+ }
+
+ /*
+ * @see org.eclipse.ui.internal.texteditor.AnnotationExpandHover#getOrder(org.eclipse.jface.text.source.Annotation)
+ */
+ protected int getOrder(Annotation annotation) {
+ if (isBreakpointAnnotation(annotation))
+ return 1000;
+ else
+ return super.getOrder(annotation);
+ }
+
+ private boolean isBreakpointAnnotation(Annotation a) {
+ if (a instanceof JavaMarkerAnnotation) {
+ JavaMarkerAnnotation jma = (JavaMarkerAnnotation) a;
+ // HACK to get breakpoints to show up first
+ return jma.getType().equals("org.eclipse.debug.core.breakpoint"); //$NON-NLS-1$
+ }
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaHoverMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaHoverMessages.java
new file mode 100644
index 0000000..3582118
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaHoverMessages.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+class JavaHoverMessages {
+
+ private static final String RESOURCE_BUNDLE = "net.sourceforge.phpdt.internal.ui.text.java.hover.JavaHoverMessages";//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private JavaHoverMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * 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
+ * @since 3.0
+ */
+ public static String getFormattedString(String key, Object arg) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ if (arg == null)
+ arg = ""; //$NON-NLS-1$
+ return MessageFormat.format(format, new Object[] { arg });
+ }
+
+ /**
+ * Gets a string from the resource bundle and formats it with the arguments
+ *
+ * @param key
+ * the string used to get the bundle value, must not be null
+ * @since 3.0
+ */
+ public static String getFormattedString(String key, Object arg1, Object arg2) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ if (arg1 == null)
+ arg1 = ""; //$NON-NLS-1$
+ if (arg2 == null)
+ arg2 = ""; //$NON-NLS-1$
+ return MessageFormat.format(format, new Object[] { arg1, arg2 });
+ }
+
+ /**
+ * 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
+ * @since 3.0
+ */
+ public static String getFormattedString(String key, boolean arg) {
+ String format = null;
+ try {
+ format = fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ return MessageFormat.format(format, new Object[] { new Boolean(arg) });
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaHoverMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaHoverMessages.properties
new file mode 100644
index 0000000..ea58cad
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaHoverMessages.properties
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright (c) 2000, 2003 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+TypeHover.more_to_come=\ ...
+
+JavaTextHover.createTextHover= Could not create PHP text hover
+
+JavaTextHover.makeStickyHint= Press ''{0}'' for focus.
+
+NoBreakpointAnnotation.addBreakpoint= Add a breakpoint
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaInformationProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaInformationProvider.java
new file mode 100644
index 0000000..a8f3a8e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaInformationProvider.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder;
+import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+
+public class JavaInformationProvider implements IInformationProvider {
+
+ class EditorWatcher implements IPartListener {
+
+ /**
+ * @see IPartListener#partOpened(IWorkbenchPart)
+ */
+ public void partOpened(IWorkbenchPart part) {
+ }
+
+ /**
+ * @see IPartListener#partDeactivated(IWorkbenchPart)
+ */
+ public void partDeactivated(IWorkbenchPart part) {
+ }
+
+ /**
+ * @see IPartListener#partClosed(IWorkbenchPart)
+ */
+ public void partClosed(IWorkbenchPart part) {
+ if (part == fEditor) {
+ fEditor.getSite().getWorkbenchWindow().getPartService()
+ .removePartListener(fPartListener);
+ fPartListener = null;
+ }
+ }
+
+ /**
+ * @see IPartListener#partActivated(IWorkbenchPart)
+ */
+ public void partActivated(IWorkbenchPart part) {
+ update();
+ }
+
+ public void partBroughtToTop(IWorkbenchPart part) {
+ update();
+ }
+ }
+
+ protected IEditorPart fEditor;
+
+ protected IPartListener fPartListener;
+
+ protected String fCurrentPerspective;
+
+ protected IJavaEditorTextHover fImplementation;
+
+ public JavaInformationProvider(IEditorPart editor) {
+
+ fEditor = editor;
+
+ if (fEditor != null) {
+
+ fPartListener = new EditorWatcher();
+ IWorkbenchWindow window = fEditor.getSite().getWorkbenchWindow();
+ window.getPartService().addPartListener(fPartListener);
+
+ update();
+ }
+ }
+
+ protected void update() {
+
+ IWorkbenchWindow window = fEditor.getSite().getWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ if (page != null) {
+
+ IPerspectiveDescriptor perspective = page.getPerspective();
+ if (perspective != null) {
+ String perspectiveId = perspective.getId();
+
+ if (fCurrentPerspective == null
+ || fCurrentPerspective != perspectiveId) {
+ fCurrentPerspective = perspectiveId;
+
+ fImplementation = new JavaTypeHover();
+ fImplementation.setEditor(fEditor);
+ }
+ }
+ }
+ }
+
+ /*
+ * @see IInformationProvider#getSubject(ITextViewer, int)
+ */
+ public IRegion getSubject(ITextViewer textViewer, int offset) {
+
+ if (textViewer != null)
+ return JavaWordFinder.findWord(textViewer.getDocument(), offset);
+
+ return null;
+ }
+
+ /*
+ * @see IInformationProvider#getInformation(ITextViewer, IRegion)
+ */
+ public String getInformation(ITextViewer textViewer, IRegion subject) {
+ if (fImplementation != null) {
+ String s = fImplementation.getHoverInfo(textViewer, subject);
+ if (s != null && s.trim().length() > 0)
+ return s;
+ }
+
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaSourceHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaSourceHover.java
new file mode 100644
index 0000000..f8dd369
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaSourceHover.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.io.IOException;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.text.HTMLPrinter;
+import net.sourceforge.phpdt.internal.ui.text.PHPCodeReader;
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Provides source as hover info for Java elements.
+ */
+public class JavaSourceHover extends AbstractJavaEditorTextHover {
+
+ private final int LABEL_FLAGS = JavaElementLabels.ALL_FULLY_QUALIFIED
+ | JavaElementLabels.M_PRE_RETURNTYPE
+ | JavaElementLabels.M_PARAMETER_TYPES
+ | JavaElementLabels.M_PARAMETER_NAMES
+ | JavaElementLabels.M_EXCEPTIONS
+ | JavaElementLabels.F_PRE_TYPE_SIGNATURE;
+
+ /*
+ * @see JavaElementHover
+ */
+ protected String getHoverInfo(IJavaElement[] result) {
+ int nResults = result.length;
+ StringBuffer buffer = new StringBuffer();
+
+ if (nResults > 1) {
+
+ for (int i = 0; i < result.length; i++) {
+ HTMLPrinter.startBulletList(buffer);
+ IJavaElement curr = result[i];
+ if (curr instanceof IMember)
+ HTMLPrinter.addBullet(buffer, getInfoText((IMember) curr));
+ HTMLPrinter.endBulletList(buffer);
+ }
+
+ } else {
+
+ IJavaElement curr = result[0];
+ if (curr instanceof IMember && curr instanceof ISourceReference) {
+ HTMLPrinter.addSmallHeader(buffer,
+ getInfoText(((IMember) curr)));
+ try {
+ String source = ((ISourceReference) curr).getSource();
+ source = removeLeadingComments(source);
+ HTMLPrinter.addParagraph(buffer, ""); //$NON-NLS-1$
+ HTMLPrinter.addParagraph(buffer, source);
+ HTMLPrinter.addParagraph(buffer, "
"); //$NON-NLS-1$
+ } catch (JavaModelException ex) {
+ // only write small header
+ }
+ }
+ }
+
+ if (buffer.length() > 0) {
+ HTMLPrinter.insertPageProlog(buffer, 0);
+ HTMLPrinter.addPageEpilog(buffer);
+ return buffer.toString();
+ }
+
+ return null;
+ }
+
+ private String getInfoText(IMember member) {
+ return JavaElementLabels.getElementLabel(member, LABEL_FLAGS);
+ }
+
+ private String removeLeadingComments(String source) {
+ PHPCodeReader reader = new PHPCodeReader();
+ IDocument document = new Document(source);
+ int i;
+ try {
+ reader.configureForwardReader(document, 0, document.getLength(),
+ true, false);
+ int c = reader.read();
+ while (c != -1 && (c == '\r' || c == '\n')) {
+ c = reader.read();
+ }
+ i = reader.getOffset();
+ reader.close();
+ } catch (IOException ex) {
+ i = 0;
+ } finally {
+ try {
+ if (reader != null)
+ reader.close();
+ } catch (IOException ex) {
+ WebUI.log(ex);
+ }
+ }
+
+ if (i < 0)
+ return source;
+ return source.substring(i);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaTypeHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaTypeHover.java
new file mode 100644
index 0000000..a2b08f1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/JavaTypeHover.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.ui.IEditorPart;
+
+public class JavaTypeHover implements IJavaEditorTextHover {
+
+ private IJavaEditorTextHover fAnnotationHover;
+
+ // private IJavaEditorTextHover fJavadocHover;
+
+ public JavaTypeHover() {
+ fAnnotationHover = new AnnotationHover();
+ // fJavadocHover= new JavadocHover();
+ }
+
+ /**
+ * @see IJavaEditorTextHover#setEditor(IEditorPart)
+ */
+ public void setEditor(IEditorPart editor) {
+ fAnnotationHover.setEditor(editor);
+ // fJavadocHover.setEditor(editor);
+ }
+
+ /*
+ * @see ITextHover#getHoverRegion(ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ // return fJavadocHover.getHoverRegion(textViewer, offset);
+ return null;
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+ String hoverInfo = fAnnotationHover.getHoverInfo(textViewer,
+ hoverRegion);
+ if (hoverInfo != null)
+ return hoverInfo;
+
+ // return fJavadocHover.getHoverInfo(textViewer, hoverRegion);
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/ProblemHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/ProblemHover.java
new file mode 100644
index 0000000..ea51f8e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/ProblemHover.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+/**
+ * This annotation hover shows the description of the selected java annotation.
+ *
+ * XXX: Currently this problem hover only works for Java problems. see:
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=62081
+ *
+ * @since 3.0
+ */
+public class ProblemHover extends AbstractAnnotationHover {
+
+ public ProblemHover() {
+ super(false);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java
new file mode 100644
index 0000000..d2760fc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java
@@ -0,0 +1,447 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlExtension;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+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.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Source viewer based implementation of IInformationControl
.
+ * Displays information in a source viewer.
+ *
+ * @since 3.0
+ */
+public class SourceViewerInformationControl implements IInformationControl,
+ IInformationControlExtension, DisposeListener {
+
+ /** Border thickness in pixels. */
+ private static final int BORDER = 1;
+
+ /** The control's shell */
+ private Shell fShell;
+
+ /** The control's text widget */
+ private StyledText fText;
+
+ /** The control's source viewer */
+ private SourceViewer fViewer;
+
+ /**
+ * The optional status field.
+ *
+ * @since 3.0
+ */
+ private Label fStatusField;
+
+ /**
+ * The separator for the optional status field.
+ *
+ * @since 3.0
+ */
+ private Label fSeparator;
+
+ /**
+ * The font of the optional status text label.
+ *
+ * @since 3.0
+ */
+ private Font fStatusTextFont;
+
+ /**
+ * Creates a default information control with the given shell as parent. The
+ * given information presenter is used to process the information to be
+ * displayed. The given styles are applied to the created styled text
+ * widget.
+ *
+ * @param parent
+ * the parent shell
+ * @param shellStyle
+ * the additional styles for the shell
+ * @param style
+ * the additional styles for the styled text widget
+ */
+ public SourceViewerInformationControl(Shell parent, int shellStyle,
+ int style) {
+ this(parent, shellStyle, style, null);
+ }
+
+ /**
+ * Creates a default information control with the given shell as parent. The
+ * given information presenter is used to process the information to be
+ * displayed. The given styles are applied to the created styled text
+ * widget.
+ *
+ * @param parent
+ * the parent shell
+ * @param shellStyle
+ * the additional styles for the shell
+ * @param style
+ * the additional styles for the styled text widget
+ * @param statusFieldText
+ * the text to be used in the optional status field or
+ * null
if the status field should be hidden
+ * @since 3.0
+ */
+ public SourceViewerInformationControl(Shell parent, int shellStyle,
+ int style, String statusFieldText) {
+ GridLayout layout;
+ GridData gd;
+
+ fShell = new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle);
+ Display display = fShell.getDisplay();
+ fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+
+ Composite composite = fShell;
+ layout = new GridLayout(1, false);
+ int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
+ layout.marginHeight = border;
+ layout.marginWidth = border;
+ composite.setLayout(layout);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ composite.setLayoutData(gd);
+
+ if (statusFieldText != null) {
+ composite = new Composite(composite, SWT.NONE);
+ layout = new GridLayout(1, false);
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+ gd = new GridData(GridData.FILL_BOTH);
+ composite.setLayoutData(gd);
+ composite.setForeground(display
+ .getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ composite.setBackground(display
+ .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ }
+
+ // Source viewer
+ IPreferenceStore store = WebUI.getDefault()
+ .getCombinedPreferenceStore();
+ fViewer = new JavaSourceViewer(composite, null, null, false, style,
+ store);
+ fViewer.configure(new PHPSourceViewerConfiguration(WebUI
+ .getDefault().getJavaTextTools().getColorManager(), store,
+ null, null));
+ fViewer.setEditable(false);
+
+ fText = fViewer.getTextWidget();
+ gd = new GridData(GridData.BEGINNING | GridData.FILL_BOTH);
+ fText.setLayoutData(gd);
+ fText.setForeground(parent.getDisplay().getSystemColor(
+ SWT.COLOR_INFO_FOREGROUND));
+ fText.setBackground(parent.getDisplay().getSystemColor(
+ SWT.COLOR_INFO_BACKGROUND));
+
+ fText.addKeyListener(new KeyListener() {
+
+ public void keyPressed(KeyEvent e) {
+ if (e.character == 0x1B) // ESC
+ fShell.dispose();
+ }
+
+ public void keyReleased(KeyEvent e) {
+ }
+ });
+
+ // Status field
+ if (statusFieldText != null) {
+
+ // Horizontal separator line
+ fSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL
+ | SWT.LINE_DOT);
+ fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // Status field label
+ fStatusField = new Label(composite, SWT.RIGHT);
+ fStatusField.setText(statusFieldText);
+ Font font = fStatusField.getFont();
+ FontData[] fontDatas = font.getFontData();
+ for (int i = 0; i < fontDatas.length; i++)
+ fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
+ fStatusTextFont = new Font(fStatusField.getDisplay(), fontDatas);
+ fStatusField.setFont(fStatusTextFont);
+ GridData gd2 = new GridData(GridData.FILL_VERTICAL
+ | GridData.FILL_HORIZONTAL
+ | GridData.HORIZONTAL_ALIGN_BEGINNING
+ | GridData.VERTICAL_ALIGN_BEGINNING);
+ fStatusField.setLayoutData(gd2);
+
+ // Regarding the color see bug 41128
+ fStatusField.setForeground(display
+ .getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
+
+ fStatusField.setBackground(display
+ .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ }
+
+ addDisposeListener(this);
+ }
+
+ /**
+ * Creates a default information control with the given shell as parent. The
+ * given information presenter is used to process the information to be
+ * displayed. The given styles are applied to the created styled text
+ * widget.
+ *
+ * @param parent
+ * the parent shell
+ * @param style
+ * the additional styles for the styled text widget
+ */
+ public SourceViewerInformationControl(Shell parent, int style) {
+ this(parent, SWT.NO_TRIM, style);
+ }
+
+ /**
+ * Creates a default information control with the given shell as parent. The
+ * given information presenter is used to process the information to be
+ * displayed. The given styles are applied to the created styled text
+ * widget.
+ *
+ * @param parent
+ * the parent shell
+ * @param style
+ * the additional styles for the styled text widget
+ * @param statusFieldText
+ * the text to be used in the optional status field or
+ * null
if the status field should be hidden
+ * @since 3.0
+ */
+ public SourceViewerInformationControl(Shell parent, int style,
+ String statusFieldText) {
+ this(parent, SWT.NO_TRIM, style, statusFieldText);
+ }
+
+ /**
+ * Creates a default information control with the given shell as parent. No
+ * information presenter is used to process the information to be displayed.
+ * No additional styles are applied to the styled text widget.
+ *
+ * @param parent
+ * the parent shell
+ */
+ public SourceViewerInformationControl(Shell parent) {
+ this(parent, SWT.NONE);
+ }
+
+ /**
+ * Creates a default information control with the given shell as parent. No
+ * information presenter is used to process the information to be displayed.
+ * No additional styles are applied to the styled text widget.
+ *
+ * @param parent
+ * the parent shell
+ * @param statusFieldText
+ * the text to be used in the optional status field or
+ * null
if the status field should be hidden
+ * @since 3.0
+ */
+ public SourceViewerInformationControl(Shell parent, String statusFieldText) {
+ this(parent, SWT.NONE, statusFieldText);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
+ */
+ public void setInput(Object input) {
+ if (input instanceof String)
+ setInformation((String) input);
+ else
+ setInformation(null);
+ }
+
+ /*
+ * @see IInformationControl#setInformation(String)
+ */
+ public void setInformation(String content) {
+ if (content == null) {
+ fViewer.setInput(null);
+ return;
+ }
+
+ IDocument doc = new Document(content);
+ WebUI.getDefault().getJavaTextTools()
+ .setupJavaDocumentPartitioner(doc);
+
+ fViewer.setInput(doc);
+ }
+
+ /*
+ * @see IInformationControl#setVisible(boolean)
+ */
+ public void setVisible(boolean visible) {
+ fShell.setVisible(visible);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 3.0
+ */
+ public void widgetDisposed(DisposeEvent event) {
+ if (fStatusTextFont != null && !fStatusTextFont.isDisposed())
+ fStatusTextFont.dispose();
+
+ fStatusTextFont = null;
+ fShell = null;
+ fText = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void dispose() {
+ if (fShell != null && !fShell.isDisposed())
+ fShell.dispose();
+ else
+ widgetDisposed(null);
+ }
+
+ /*
+ * @see IInformationControl#setSize(int, int)
+ */
+ public void setSize(int width, int height) {
+
+ if (fStatusField != null) {
+ GridData gd = (GridData) fViewer.getTextWidget().getLayoutData();
+ Point statusSize = fStatusField.computeSize(SWT.DEFAULT,
+ SWT.DEFAULT, true);
+ Point separatorSize = fSeparator.computeSize(SWT.DEFAULT,
+ SWT.DEFAULT, true);
+ gd.heightHint = height - statusSize.y - separatorSize.y;
+ }
+ fShell.setSize(width, height);
+
+ if (fStatusField != null)
+ fShell.pack(true);
+ }
+
+ /*
+ * @see IInformationControl#setLocation(Point)
+ */
+ public void setLocation(Point location) {
+ Rectangle trim = fShell.computeTrim(0, 0, 0, 0);
+ Point textLocation = fText.getLocation();
+ location.x += trim.x - textLocation.x;
+ location.y += trim.y - textLocation.y;
+ fShell.setLocation(location);
+ }
+
+ /*
+ * @see IInformationControl#setSizeConstraints(int, int)
+ */
+ public void setSizeConstraints(int maxWidth, int maxHeight) {
+ maxWidth = maxHeight;
+ }
+
+ /*
+ * @see IInformationControl#computeSizeHint()
+ */
+ public Point computeSizeHint() {
+ return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ }
+
+ /*
+ * @see IInformationControl#addDisposeListener(DisposeListener)
+ */
+ public void addDisposeListener(DisposeListener listener) {
+ fShell.addDisposeListener(listener);
+ }
+
+ /*
+ * @see IInformationControl#removeDisposeListener(DisposeListener)
+ */
+ public void removeDisposeListener(DisposeListener listener) {
+ fShell.removeDisposeListener(listener);
+ }
+
+ /*
+ * @see IInformationControl#setForegroundColor(Color)
+ */
+ public void setForegroundColor(Color foreground) {
+ fText.setForeground(foreground);
+ }
+
+ /*
+ * @see IInformationControl#setBackgroundColor(Color)
+ */
+ public void setBackgroundColor(Color background) {
+ fText.setBackground(background);
+ }
+
+ /*
+ * @see IInformationControl#isFocusControl()
+ */
+ public boolean isFocusControl() {
+ return fText.isFocusControl();
+ }
+
+ /*
+ * @see IInformationControl#setFocus()
+ */
+ public void setFocus() {
+ fShell.forceFocus();
+ fText.setFocus();
+ }
+
+ /*
+ * @see IInformationControl#addFocusListener(FocusListener)
+ */
+ public void addFocusListener(FocusListener listener) {
+ fText.addFocusListener(listener);
+ }
+
+ /*
+ * @see IInformationControl#removeFocusListener(FocusListener)
+ */
+ public void removeFocusListener(FocusListener listener) {
+ fText.removeFocusListener(listener);
+ }
+
+ /*
+ * @see IInformationControlExtension#hasContents()
+ */
+ public boolean hasContents() {
+ return fText.getCharCount() > 0;
+ }
+
+ protected ISourceViewer getViewer() {
+ return fViewer;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/ILinkedPositionListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/ILinkedPositionListener.java
new file mode 100644
index 0000000..b462ede
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/ILinkedPositionListener.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.link;
+
+import org.eclipse.jface.text.Position;
+
+/**
+ * A listener for highlight change notification and exititing linked mode.
+ */
+public interface ILinkedPositionListener {
+
+ /**
+ * Notifies that the linked mode has been left. On success, all changes are
+ * kept, otherwise all changes made to the linked positions are restored to
+ * the state before entering linked mode.
+ */
+ void exit(int flags);
+
+ /**
+ * Notifies the changed linked position. The listener is asked to reposition
+ * the caret at the given offset.
+ *
+ * @param position
+ * the linked position which initiated the change.
+ * @param caretOffset
+ * the caret offset relative to the position.
+ */
+ void setCurrentPosition(Position position, int caretOffset);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionListener.java
new file mode 100644
index 0000000..f204eb1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionListener.java
@@ -0,0 +1,39 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.link;
+
+import org.eclipse.jface.text.Position;
+
+/**
+ * A listener for highlight change notification and exititing linked mode.
+ */
+public interface LinkedPositionListener {
+
+ /**
+ * Notifies that the linked mode has been left. On success, all changes are
+ * kept, otherwise all changes made to the linked positions are restored to
+ * the state before entering linked mode.
+ */
+ void exit(boolean success);
+
+ /**
+ * Notifies the changed linked position. The listener is asked to reposition
+ * the caret at the given offset.
+ *
+ * @param position
+ * the linked position which initiated the change.
+ * @param caretOffset
+ * the caret offset relative to the position.
+ */
+ void setCurrentPosition(Position position, int caretOffset);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java
new file mode 100644
index 0000000..3a89914
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java
@@ -0,0 +1,831 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.link;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TypedPosition;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+
+/**
+ * This class manages linked positions in a document. Positions are linked by
+ * type names. If positions have the same type name, they are considered as
+ * linked.
+ *
+ * The manager remains active on a document until any of the following actions
+ * occurs:
+ *
+ *
+ *
+ */
+public class LinkedPositionManager implements IDocumentListener,
+ IPositionUpdater, IAutoEditStrategy {
+
+ // This class still exists to properly handle code assist.
+ // This is due to the fact that it cannot be distinguished betweeen document
+ // changes which are
+ // issued by code assist and document changes which origin from another text
+ // viewer.
+ // There is a conflict in interest since in the latter case the linked mode
+ // should be left, but in the former case
+ // the linked mode should remain.
+ // To support content assist, document changes have to be propagated to
+ // connected positions
+ // by registering replace commands using IDocumentExtension.
+ // if it wasn't for the support of content assist, the documentChanged()
+ // method could be reduced to
+ // a simple call to leave(true)
+ private class Replace implements IDocumentExtension.IReplace {
+
+ private Position fReplacePosition;
+
+ private int fReplaceDeltaOffset;
+
+ private int fReplaceLength;
+
+ private String fReplaceText;
+
+ public Replace(Position position, int deltaOffset, int length,
+ String text) {
+ fReplacePosition = position;
+ fReplaceDeltaOffset = deltaOffset;
+ fReplaceLength = length;
+ fReplaceText = text;
+ }
+
+ public void perform(IDocument document, IDocumentListener owner) {
+ document.removeDocumentListener(owner);
+ try {
+ document.replace(fReplacePosition.getOffset()
+ + fReplaceDeltaOffset, fReplaceLength, fReplaceText);
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ // TBD
+ }
+ document.addDocumentListener(owner);
+ }
+ }
+
+ private static class PositionComparator implements Comparator {
+ /*
+ * @see Comparator#compare(Object, Object)
+ */
+ public int compare(Object object0, Object object1) {
+ Position position0 = (Position) object0;
+ Position position1 = (Position) object1;
+
+ return position0.getOffset() - position1.getOffset();
+ }
+ }
+
+ private static final String LINKED_POSITION_PREFIX = "LinkedPositionManager.linked.position"; //$NON-NLS-1$
+
+ private static final Comparator fgPositionComparator = new PositionComparator();
+
+ private static final Map fgActiveManagers = new HashMap();
+
+ private static int fgCounter = 0;
+
+ private IDocument fDocument;
+
+ private ILinkedPositionListener fListener;
+
+ private String fPositionCategoryName;
+
+ private boolean fMustLeave;
+
+ /**
+ * Flag that records the state of this manager. As there are many different
+ * entities that may call leave or exit, these cannot always be sure whether
+ * the linked position infrastructure is still active. This is especially
+ * true for multithreaded situations.
+ */
+ private boolean fIsActive = false;
+
+ /**
+ * Creates a uninstall()
is called.LinkedPositionManager
tries to gain
+ * control of the same document.
+ * LinkedPositionManager
for a
+ * IDocument
.
+ *
+ * @param document
+ * the document to use with linked positions.
+ * @param canCoexist
+ * true
if this manager can coexist with an
+ * already existing one
+ */
+ public LinkedPositionManager(IDocument document, boolean canCoexist) {
+ Assert.isNotNull(document);
+ fDocument = document;
+ fPositionCategoryName = LINKED_POSITION_PREFIX + (fgCounter++);
+ install(canCoexist);
+ }
+
+ /**
+ * Creates a LinkedPositionManager
for a
+ * IDocument
.
+ *
+ * @param document
+ * the document to use with linked positions.
+ */
+ public LinkedPositionManager(IDocument document) {
+ this(document, false);
+ }
+
+ /**
+ * Sets a listener to notify changes of current linked position.
+ */
+ public void setLinkedPositionListener(ILinkedPositionListener listener) {
+ fListener = listener;
+ }
+
+ /**
+ * Adds a linked position to the manager with the type being the content of
+ * the document at the specified range. There are the following constraints
+ * for linked positions:
+ *
+ *
+ *
+ *
+ * @param offset
+ * the offset of the position.
+ * @param length
+ * the length of the position.
+ */
+ public void addPosition(int offset, int length) throws BadLocationException {
+ String type = fDocument.get(offset, length);
+ addPosition(offset, length, type);
+ }
+
+ /**
+ * Adds a linked position of the specified position type to the manager.
+ * There are the following constraints for linked positions:
+ *
+ *
+ *
+ *
+ * @param offset
+ * the offset of the position.
+ * @param length
+ * the length of the position.
+ * @param type
+ * the position type name - any positions with the same type are
+ * linked.
+ */
+ public void addPosition(int offset, int length, String type)
+ throws BadLocationException {
+ Position[] positions = getPositions(fDocument);
+
+ if (positions != null) {
+ for (int i = 0; i < positions.length; i++)
+ if (collides(positions[i], offset, length))
+ throw new BadLocationException(
+ LinkedPositionMessages
+ .getString(("LinkedPositionManager.error.position.collision"))); //$NON-NLS-1$
+ }
+
+ String content = fDocument.get(offset, length);
+
+ if (containsLineDelimiters(content))
+ throw new BadLocationException(
+ LinkedPositionMessages
+ .getString(("LinkedPositionManager.error.contains.line.delimiters"))); //$NON-NLS-1$
+
+ try {
+ fDocument.addPosition(fPositionCategoryName, new TypedPosition(
+ offset, length, type));
+ } catch (BadPositionCategoryException e) {
+ WebUI.log(e);
+ Assert.isTrue(false);
+ }
+ }
+
+ /**
+ * Adds a linked position to the manager. The current document content at
+ * the specified range is taken as the position type.
+ *
+ *
+ *
+ * It is usually best to set the first item in
+ * additionalChoices
to be equal with the text inserted at
+ * the current position.
+ *
type
.
+ */
+ public void addPosition(int offset, int length,
+ ICompletionProposal[] additionalChoices)
+ throws BadLocationException {
+ String type = fDocument.get(offset, length);
+ addPosition(offset, length, type, additionalChoices);
+ }
+
+ /**
+ * Adds a linked position of the specified position type to the manager.
+ * There are the following constraints for linked positions:
+ *
+ * additionalChoices
to be equal with the text inserted at
+ * the current position.
+ *
+ * @param offset
+ * the offset of the position.
+ * @param length
+ * the length of the position.
+ * @param type
+ * the position type name - any positions with the same type are
+ * linked.
+ * @param additionalChoices
+ * a number of additional choices to be displayed when selecting
+ * a position of this type
.
+ */
+ public void addPosition(int offset, int length, String type,
+ ICompletionProposal[] additionalChoices)
+ throws BadLocationException {
+ Position[] positions = getPositions(fDocument);
+
+ if (positions != null) {
+ for (int i = 0; i < positions.length; i++)
+ if (collides(positions[i], offset, length))
+ throw new BadLocationException(
+ LinkedPositionMessages
+ .getString(("LinkedPositionManager.error.position.collision"))); //$NON-NLS-1$
+ }
+
+ String content = fDocument.get(offset, length);
+
+ if (containsLineDelimiters(content))
+ throw new BadLocationException(
+ LinkedPositionMessages
+ .getString(("LinkedPositionManager.error.contains.line.delimiters"))); //$NON-NLS-1$
+
+ try {
+ fDocument.addPosition(fPositionCategoryName, new ProposalPosition(
+ offset, length, type, additionalChoices));
+ } catch (BadPositionCategoryException e) {
+ WebUI.log(e);
+ Assert.isTrue(false);
+ }
+ }
+
+ /**
+ * Tests if a manager is already active for a document.
+ */
+ public static boolean hasActiveManager(IDocument document) {
+ return fgActiveManagers.get(document) != null;
+ }
+
+ private void install(boolean canCoexist) {
+
+ if (fIsActive)
+ ;// JavaPlugin.log(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionManager
+ // is already active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+ else {
+ fIsActive = true;
+ // JavaPlugin.log(new Status(IStatus.INFO, JavaPlugin.getPluginId(),
+ // IStatus.OK, "LinkedPositionManager activated:
+ // "+fPositionCategoryName, new Exception())); //$NON-NLS-1$
+ }
+
+ if (!canCoexist) {
+ LinkedPositionManager manager = (LinkedPositionManager) fgActiveManagers
+ .get(fDocument);
+ if (manager != null)
+ manager.leave(true);
+ }
+
+ fgActiveManagers.put(fDocument, this);
+ fDocument.addPositionCategory(fPositionCategoryName);
+ fDocument.addPositionUpdater(this);
+ fDocument.addDocumentListener(this);
+
+ fMustLeave = false;
+ }
+
+ /**
+ * Leaves the linked mode. If unsuccessful, the linked positions are
+ * restored to the values at the time they were added.
+ */
+ public void uninstall(boolean success) {
+
+ if (!fIsActive)
+ // we migth also just return
+ ;// JavaPlugin(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionManager
+ // activated: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+ else {
+ fDocument.removeDocumentListener(this);
+
+ try {
+ Position[] positions = getPositions(fDocument);
+ if ((!success) && (positions != null)) {
+ // restore
+ for (int i = 0; i != positions.length; i++) {
+ TypedPosition position = (TypedPosition) positions[i];
+ fDocument.replace(position.getOffset(), position
+ .getLength(), position.getType());
+ }
+ }
+
+ fDocument.removePositionCategory(fPositionCategoryName);
+
+ fIsActive = false;
+ // JavaPlugin.log(new Status(IStatus.INFO,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionManager
+ // deactivated: "+fPositionCategoryName, new Exception()));
+ // //$NON-NLS-1$
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ Assert.isTrue(false);
+
+ } catch (BadPositionCategoryException e) {
+ WebUI.log(e);
+ Assert.isTrue(false);
+
+ } finally {
+ fDocument.removePositionUpdater(this);
+ fgActiveManagers.remove(fDocument);
+ }
+ }
+
+ }
+
+ /**
+ * Returns the position at the given offset, null
if there is
+ * no position.
+ *
+ * @since 2.1
+ */
+ public Position getPosition(int offset) {
+ Position[] positions = getPositions(fDocument);
+ if (positions == null)
+ return null;
+
+ for (int i = positions.length - 1; i >= 0; i--) {
+ Position position = positions[i];
+ if (offset >= position.getOffset()
+ && offset <= position.getOffset() + position.getLength())
+ return positions[i];
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the first linked position.
+ *
+ * @return returns null
if no linked position exist.
+ */
+ public Position getFirstPosition() {
+ return getNextPosition(-1);
+ }
+
+ public Position getLastPosition() {
+ Position[] positions = getPositions(fDocument);
+ for (int i = positions.length - 1; i >= 0; i--) {
+ String type = ((TypedPosition) positions[i]).getType();
+ int j;
+ for (j = 0; j != i; j++)
+ if (((TypedPosition) positions[j]).getType().equals(type))
+ break;
+
+ if (j == i)
+ return positions[i];
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the next linked position with an offset greater than
+ * offset
. If another position with the same type and offset
+ * lower than offset
exists, the position is skipped.
+ *
+ * @return returns null
if no linked position exist.
+ */
+ public Position getNextPosition(int offset) {
+ Position[] positions = getPositions(fDocument);
+ return findNextPosition(positions, offset);
+ }
+
+ private static Position findNextPosition(Position[] positions, int offset) {
+ // skip already visited types
+ for (int i = 0; i != positions.length; i++) {
+ if (positions[i].getOffset() > offset) {
+ String type = ((TypedPosition) positions[i]).getType();
+ int j;
+ for (j = 0; j != i; j++)
+ if (((TypedPosition) positions[j]).getType().equals(type))
+ break;
+
+ if (j == i)
+ return positions[i];
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the position with the greatest offset smaller than
+ * offset
.
+ *
+ * @return returns null
if no linked position exist.
+ */
+ public Position getPreviousPosition(int offset) {
+ Position[] positions = getPositions(fDocument);
+ if (positions == null)
+ return null;
+
+ TypedPosition currentPosition = (TypedPosition) findCurrentPosition(
+ positions, offset);
+ String currentType = currentPosition == null ? null : currentPosition
+ .getType();
+
+ Position lastPosition = null;
+ Position position = getFirstPosition();
+
+ while (position != null && position.getOffset() < offset) {
+ if (!((TypedPosition) position).getType().equals(currentType))
+ lastPosition = position;
+ position = findNextPosition(positions, position.getOffset());
+ }
+
+ return lastPosition;
+ }
+
+ private Position[] getPositions(IDocument document) {
+
+ if (!fIsActive)
+ // we migth also just return an empty array
+ ;// JavaPlugin(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionManager
+ // is not active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+
+ try {
+ Position[] positions = document.getPositions(fPositionCategoryName);
+ Arrays.sort(positions, fgPositionComparator);
+ return positions;
+
+ } catch (BadPositionCategoryException e) {
+ WebUI.log(e);
+ Assert.isTrue(false);
+ }
+
+ return null;
+ }
+
+ public static boolean includes(Position position, int offset, int length) {
+ return (offset >= position.getOffset())
+ && (offset + length <= position.getOffset()
+ + position.getLength());
+ }
+
+ public static boolean excludes(Position position, int offset, int length) {
+ return (offset + length <= position.getOffset())
+ || (position.getOffset() + position.getLength() <= offset);
+ }
+
+ /*
+ * Collides if spacing if positions intersect each other or are adjacent.
+ */
+ private static boolean collides(Position position, int offset, int length) {
+ return (offset <= position.getOffset() + position.getLength())
+ && (position.getOffset() <= offset + length);
+ }
+
+ private void leave(boolean success) {
+ try {
+ uninstall(success);
+
+ if (fListener != null)
+ fListener.exit((success ? LinkedPositionUI.COMMIT : 0)
+ | LinkedPositionUI.UPDATE_CARET);
+ } finally {
+ fMustLeave = false;
+ }
+ }
+
+ private void abort() {
+ uninstall(true); // don't revert anything
+
+ if (fListener != null)
+ fListener.exit(LinkedPositionUI.COMMIT); // don't let the UI
+ // restore anything
+
+ // don't set fMustLeave, as we will get re-registered by a document
+ // event
+ }
+
+ /*
+ * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+
+ if (fMustLeave) {
+ event.getDocument().removeDocumentListener(this);
+ return;
+ }
+
+ IDocument document = event.getDocument();
+
+ Position[] positions = getPositions(document);
+ Position position = findCurrentPosition(positions, event.getOffset());
+
+ // modification outside editable position
+ if (position == null) {
+ // check for destruction of constraints (spacing of at least 1)
+ if ((event.getText() == null || event.getText().length() == 0)
+ && (findCurrentPosition(positions, event.getOffset()) != null)
+ && // will never become true, see condition above
+ (findCurrentPosition(positions, event.getOffset()
+ + event.getLength()) != null)) {
+ leave(true);
+ }
+
+ // modification intersects editable position
+ } else {
+ // modificaction inside editable position
+ if (includes(position, event.getOffset(), event.getLength())) {
+ if (containsLineDelimiters(event.getText()))
+ leave(true);
+
+ // modificaction exceeds editable position
+ } else {
+ leave(true);
+ }
+ }
+ }
+
+ /*
+ * @see IDocumentListener#documentChanged(DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+
+ // have to handle code assist, so can't just leave the linked mode
+ // leave(true);
+
+ IDocument document = event.getDocument();
+
+ Position[] positions = getPositions(document);
+ TypedPosition currentPosition = (TypedPosition) findCurrentPosition(
+ positions, event.getOffset());
+
+ // ignore document changes (assume it won't invalidate constraints)
+ if (currentPosition == null)
+ return;
+
+ int deltaOffset = event.getOffset() - currentPosition.getOffset();
+
+ if (fListener != null) {
+ int length = event.getText() == null ? 0 : event.getText().length();
+ fListener.setCurrentPosition(currentPosition, deltaOffset + length);
+ }
+
+ for (int i = 0; i != positions.length; i++) {
+ TypedPosition p = (TypedPosition) positions[i];
+
+ if (p.getType().equals(currentPosition.getType())
+ && !p.equals(currentPosition)) {
+ Replace replace = new Replace(p, deltaOffset,
+ event.getLength(), event.getText());
+ ((IDocumentExtension) document)
+ .registerPostNotificationReplace(this, replace);
+ }
+ }
+ }
+
+ /*
+ * @see IPositionUpdater#update(DocumentEvent)
+ */
+ public void update(DocumentEvent event) {
+
+ int eventOffset = event.getOffset();
+ int eventOldLength = event.getLength();
+ int eventNewLength = event.getText() == null ? 0 : event.getText()
+ .length();
+ int deltaLength = eventNewLength - eventOldLength;
+
+ Position[] positions = getPositions(event.getDocument());
+
+ for (int i = 0; i != positions.length; i++) {
+
+ Position position = positions[i];
+
+ if (position.isDeleted())
+ continue;
+
+ int offset = position.getOffset();
+ int length = position.getLength();
+ int end = offset + length;
+
+ if (offset > eventOffset + eventOldLength) // position comes way
+ // after change - shift
+ position.setOffset(offset + deltaLength);
+ else if (end < eventOffset) // position comes way before change -
+ // leave alone
+ ;
+ else if (offset <= eventOffset
+ && end >= eventOffset + eventOldLength) {
+ // event completely internal to the position - adjust length
+ position.setLength(length + deltaLength);
+ } else if (offset < eventOffset) {
+ // event extends over end of position - adjust length
+ int newEnd = eventOffset + eventNewLength;
+ position.setLength(newEnd - offset);
+ } else if (end > eventOffset + eventOldLength) {
+ // event extends from before position into it - adjust offset
+ // and length
+ // offset becomes end of event, length ajusted acordingly
+ // we want to recycle the overlapping part
+ int newOffset = eventOffset + eventNewLength;
+ position.setOffset(newOffset);
+ position.setLength(length + deltaLength);
+ } else {
+ // event consumes the position - delete it
+ position.delete();
+ // JavaPlugin.log(new Status(IStatus.INFO,
+ // JavaPlugin.getPluginId(), IStatus.OK, "linked position
+ // deleted -> must leave: "+fPositionCategoryName, null));
+ // //$NON-NLS-1$
+ fMustLeave = true;
+ }
+ }
+
+ if (fMustLeave)
+ abort();
+ }
+
+ private static Position findCurrentPosition(Position[] positions, int offset) {
+ for (int i = 0; i != positions.length; i++)
+ if (includes(positions[i], offset, 0))
+ return positions[i];
+
+ return null;
+ }
+
+ private boolean containsLineDelimiters(String string) {
+
+ if (string == null)
+ return false;
+
+ String[] delimiters = fDocument.getLegalLineDelimiters();
+
+ for (int i = 0; i != delimiters.length; i++)
+ if (string.indexOf(delimiters[i]) != -1)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Test if ok to modify through UI.
+ */
+ public boolean anyPositionIncludes(int offset, int length) {
+ Position[] positions = getPositions(fDocument);
+
+ Position position = findCurrentPosition(positions, offset);
+ if (position == null)
+ return false;
+
+ return includes(position, offset, length);
+ }
+
+ /**
+ * Returns the position that includes the given range.
+ *
+ * @param offset
+ * @param length
+ * @return position that includes the given range
+ */
+ public Position getEmbracingPosition(int offset, int length) {
+ Position[] positions = getPositions(fDocument);
+
+ Position position = findCurrentPosition(positions, offset);
+ if (position != null && includes(position, offset, length))
+ return position;
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(org.eclipse.jface.text.IDocument,
+ * org.eclipse.jface.text.DocumentCommand)
+ */
+ public void customizeDocumentCommand(IDocument document,
+ DocumentCommand command) {
+
+ if (fMustLeave) {
+ leave(true);
+ return;
+ }
+
+ // don't interfere with preceding auto edit strategies
+ if (command.getCommandCount() != 1) {
+ leave(true);
+ return;
+ }
+
+ Position[] positions = getPositions(document);
+ TypedPosition currentPosition = (TypedPosition) findCurrentPosition(
+ positions, command.offset);
+
+ // handle edits outside of a position
+ if (currentPosition == null) {
+ leave(true);
+ return;
+ }
+
+ if (!command.doit)
+ return;
+
+ command.doit = false;
+ command.owner = this;
+ command.caretOffset = command.offset + command.length;
+
+ int deltaOffset = command.offset - currentPosition.getOffset();
+
+ if (fListener != null)
+ fListener.setCurrentPosition(currentPosition, deltaOffset
+ + command.text.length());
+
+ for (int i = 0; i != positions.length; i++) {
+ TypedPosition position = (TypedPosition) positions[i];
+
+ try {
+ if (position.getType().equals(currentPosition.getType())
+ && !position.equals(currentPosition))
+ command.addCommand(position.getOffset() + deltaOffset,
+ command.length, command.text, this);
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ }
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionMessages.java
new file mode 100644
index 0000000..decf492
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionMessages.java
@@ -0,0 +1,46 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.link;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class LinkedPositionMessages {
+
+ private static final String RESOURCE_BUNDLE = LinkedPositionMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private LinkedPositionMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionMessages.properties
new file mode 100644
index 0000000..267939d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionMessages.properties
@@ -0,0 +1,9 @@
+#########################################
+# (c) Copyright IBM Corp. 2000, 2001.
+# All Rights Reserved.
+#########################################
+
+LinkedPositionUI.error.title=Error in LinkedPositionError
+
+LinkedPositionManager.error.contains.line.delimiters=String contains line delimiters.
+LinkedPositionManager.error.position.collision=Linked position collides with another linked position.
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionUI.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionUI.java
new file mode 100644
index 0000000..04d120f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionUI.java
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.link;
+
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultPositionUpdater;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.IRewriteTarget;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.jface.text.ITextViewerExtension2;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextEvent;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.custom.VerifyKeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.events.ShellListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A user interface for LinkedPositionManager
, using
+ * ITextViewer
.
+ */
+public class LinkedPositionUI implements ILinkedPositionListener,
+ ITextInputListener, ITextListener, ModifyListener, VerifyListener,
+ VerifyKeyListener, PaintListener, IPropertyChangeListener,
+ ShellListener {
+
+ /**
+ * A listener for notification when the user cancelled the edit operation.
+ */
+ public interface ExitListener {
+ void exit(boolean accept);
+ }
+
+ public static class ExitFlags {
+ public int flags;
+
+ public boolean doit;
+
+ public ExitFlags(int flags, boolean doit) {
+ this.flags = flags;
+ this.doit = doit;
+ }
+ }
+
+ public interface ExitPolicy {
+ ExitFlags doExit(LinkedPositionManager manager, VerifyEvent event,
+ int offset, int length);
+ }
+
+ // leave flags
+ private static final int UNINSTALL = 1; // uninstall linked position manager
+
+ public static final int COMMIT = 2; // commit changes
+
+ private static final int DOCUMENT_CHANGED = 4; // document has changed
+
+ public static final int UPDATE_CARET = 8; // update caret
+
+ private static final IPreferenceStore fgStore = WebUI
+ .getDefault().getPreferenceStore();
+
+ private static final String CARET_POSITION_PREFIX = "LinkedPositionUI.caret.position"; //$NON-NLS-1$
+
+ private static int fgCounter = 0;
+
+ private final ITextViewer fViewer;
+
+ private final LinkedPositionManager fManager;
+
+ private final IPositionUpdater fUpdater;
+
+ private final String fPositionCategoryName;
+
+ private Color fFrameColor;
+
+ private int fFinalCaretOffset = -1; // no final caret offset
+
+ private Position fFinalCaretPosition;
+
+ private Position fFramePosition;
+
+ private int fInitialOffset = -1;
+
+ private int fCaretOffset;
+
+ private ExitPolicy fExitPolicy;
+
+ private ExitListener fExitListener;
+
+ private boolean fNeedRedraw;
+
+ private String fContentType;
+
+ private Position fPreviousPosition;
+
+ // private ContentAssistant2 fAssistant;
+
+ /**
+ * Flag that records the state of this ui object. As there are many
+ * different entities that may call leave or exit, these cannot always be
+ * sure whether the linked position infrastructure is still active. This is
+ * especially true for multithreaded situations.
+ */
+ private boolean fIsActive = false;
+
+ /**
+ * Creates a user interface for LinkedPositionManager
.
+ *
+ * @param viewer
+ * the text viewer.
+ * @param manager
+ * the LinkedPositionManager
managing a
+ * IDocument
of the ITextViewer
.
+ */
+ public LinkedPositionUI(ITextViewer viewer, LinkedPositionManager manager) {
+ Assert.isNotNull(viewer);
+ Assert.isNotNull(manager);
+
+ fViewer = viewer;
+ fManager = manager;
+
+ fPositionCategoryName = CARET_POSITION_PREFIX + (fgCounter++);
+ fUpdater = new DefaultPositionUpdater(fPositionCategoryName);
+
+ fManager.setLinkedPositionListener(this);
+
+ initializeHighlightColor(viewer);
+ }
+
+ /*
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (event.getProperty().equals(
+ PreferenceConstants.EDITOR_LINKED_POSITION_COLOR)) {
+ initializeHighlightColor(fViewer);
+ redrawRegion();
+ }
+ }
+
+ private void initializeHighlightColor(ITextViewer viewer) {
+
+ if (fFrameColor != null)
+ fFrameColor.dispose();
+
+ StyledText text = viewer.getTextWidget();
+ if (text != null) {
+ Display display = text.getDisplay();
+ fFrameColor = createColor(fgStore,
+ PreferenceConstants.EDITOR_LINKED_POSITION_COLOR, display);
+ }
+ }
+
+ /**
+ * Creates a color from the information stored in the given preference
+ * store. Returns null
if there is no such information
+ * available.
+ */
+ private Color createColor(IPreferenceStore store, String key,
+ Display display) {
+
+ RGB rgb = null;
+
+ if (store.contains(key)) {
+
+ if (store.isDefault(key))
+ rgb = PreferenceConverter.getDefaultColor(store, key);
+ else
+ rgb = PreferenceConverter.getColor(store, key);
+
+ if (rgb != null)
+ return new Color(display, rgb);
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the initial offset.
+ *
+ * @param offset
+ */
+ public void setInitialOffset(int offset) {
+ fInitialOffset = offset;
+ }
+
+ /**
+ * Sets the final position of the caret when the linked mode is exited
+ * successfully by leaving the last linked position using TAB. The set
+ * position will be a TAB stop as well as the positions configured in the
+ * LinkedPositionManager
.
+ */
+ public void setFinalCaretOffset(int offset) {
+ fFinalCaretOffset = offset;
+ }
+
+ /**
+ * Sets a CancelListener
which is notified if the linked mode
+ * is exited unsuccessfully by hitting ESC.
+ */
+ public void setCancelListener(ExitListener listener) {
+ fExitListener = listener;
+ }
+
+ /**
+ * Sets an ExitPolicy
which decides when and how the linked
+ * mode is exited.
+ */
+ public void setExitPolicy(ExitPolicy policy) {
+ fExitPolicy = policy;
+ }
+
+ /*
+ * @see LinkedPositionManager.LinkedPositionListener#setCurrentPositions(Position,
+ * int)
+ */
+ public void setCurrentPosition(Position position, int caretOffset) {
+ if (!fIsActive)
+ ;// JavaPlugin.log(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionUI is
+ // not active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+
+ if (!fFramePosition.equals(position)) {
+ fNeedRedraw = true;
+ fFramePosition = position;
+ }
+
+ fCaretOffset = caretOffset;
+ }
+
+ /**
+ * Enters the linked mode. The linked mode can be left by calling
+ * exit
.
+ *
+ * @see #exit(boolean)
+ */
+ public void enter() {
+ if (fIsActive)
+ ;// JavaPlugin.log(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionUI is
+ // already active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+ else {
+ fIsActive = true;
+ // JavaPlugin.log(new Status(IStatus.INFO, JavaPlugin.getPluginId(),
+ // IStatus.OK, "LinkedPositionUI activated: "+fPositionCategoryName,
+ // new Exception())); //$NON-NLS-1$
+ }
+
+ // track final caret
+ IDocument document = fViewer.getDocument();
+ document.addPositionCategory(fPositionCategoryName);
+ document.addPositionUpdater(fUpdater);
+
+ try {
+ if (fFinalCaretOffset != -1) {
+ fFinalCaretPosition = new Position(fFinalCaretOffset);
+ document
+ .addPosition(fPositionCategoryName, fFinalCaretPosition);
+ }
+ } catch (BadLocationException e) {
+ handleException(fViewer.getTextWidget().getShell(), e);
+
+ } catch (BadPositionCategoryException e) {
+ WebUI.log(e);
+ Assert.isTrue(false);
+ }
+
+ fViewer.addTextInputListener(this);
+ fViewer.addTextListener(this);
+
+ ITextViewerExtension extension = (ITextViewerExtension) fViewer;
+ extension.prependVerifyKeyListener(this);
+
+ StyledText text = fViewer.getTextWidget();
+ text.addVerifyListener(this);
+ text.addModifyListener(this);
+ text.addPaintListener(this);
+ text.showSelection();
+
+ Shell shell = text.getShell();
+ shell.addShellListener(this);
+
+ fFramePosition = (fInitialOffset == -1) ? fManager.getFirstPosition()
+ : fManager.getPosition(fInitialOffset);
+ if (fFramePosition == null) {
+ leave(UNINSTALL | COMMIT | UPDATE_CARET);
+ return;
+ }
+
+ fgStore.addPropertyChangeListener(this);
+
+ // try {
+ // fContentType= TextUtilities.getContentType(document,
+ // IJavaPartitions.JAVA_PARTITIONING, fFramePosition.offset);
+ // if (fViewer instanceof ITextViewerExtension2) {
+ // ((ITextViewerExtension2) fViewer).prependAutoEditStrategy(fManager,
+ // fContentType);
+ // } else {
+ // Assert.isTrue(false);
+ // }
+ //
+ // } catch (BadLocationException e) {
+ // handleException(fViewer.getTextWidget().getShell(), e);
+ // }
+ try {
+ fContentType = document.getContentType(fFramePosition.offset);
+ if (fViewer instanceof ITextViewerExtension2) {
+ ((ITextViewerExtension2) fViewer).prependAutoEditStrategy(
+ fManager, fContentType);
+ } else {
+ Assert.isTrue(false);
+ }
+
+ } catch (BadLocationException e) {
+ handleException(fViewer.getTextWidget().getShell(), e);
+ }
+ selectRegion();
+ // triggerContentAssist();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.link.ILinkedPositionListener#exit(boolean)
+ */
+ public void exit(int flags) {
+ leave(flags);
+ }
+
+ /**
+ * Returns the cursor selection, after having entered the linked mode.
+ * enter()
must be called prior to a call to this method.
+ */
+ public IRegion getSelectedRegion() {
+ if (!fIsActive)
+ ;// JavaPlugin.log(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionUI is
+ // not active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+
+ if (fFramePosition == null)
+ return new Region(fFinalCaretOffset, 0);
+ else
+ return new Region(fFramePosition.getOffset(), fFramePosition
+ .getLength());
+ }
+
+ private void leave(int flags) {
+ if (!fIsActive)
+ ;// JavaPlugin.log(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionUI is
+ // not active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+ else {
+ fIsActive = false;
+ // JavaPlugin.log(new Status(IStatus.INFO, JavaPlugin.getPluginId(),
+ // IStatus.OK, "LinkedPositionUI deactivated:
+ // "+fPositionCategoryName, new Exception())); //$NON-NLS-1$
+ }
+
+ fInitialOffset = -1;
+
+ if ((flags & UNINSTALL) != 0)
+ fManager.uninstall((flags & COMMIT) != 0);
+
+ fgStore.removePropertyChangeListener(this);
+
+ if (fFrameColor != null) {
+ fFrameColor.dispose();
+ fFrameColor = null;
+ }
+
+ StyledText text = fViewer.getTextWidget();
+ // bail out if the styled text is null, meaning the viewer has been
+ // disposed (-> document is null as well)
+ // see pr https://bugs.eclipse.org/bugs/show_bug.cgi?id=46821
+ if (text == null)
+ return;
+
+ text.removePaintListener(this);
+ text.removeModifyListener(this);
+ text.removeVerifyListener(this);
+
+ Shell shell = text.getShell();
+ shell.removeShellListener(this);
+
+ // if (fAssistant != null) {
+ // Display display= text.getDisplay();
+ // if (display != null && !display.isDisposed()) {
+ // display.asyncExec(new Runnable() {
+ // public void run() {
+ // if (fAssistant != null) {
+ // fAssistant.uninstall();
+ // fAssistant= null;
+ // }
+ // }
+ // });
+ // }
+ // }
+
+ ITextViewerExtension extension = (ITextViewerExtension) fViewer;
+ extension.removeVerifyKeyListener(this);
+
+ IRewriteTarget target = extension.getRewriteTarget();
+ target.endCompoundChange();
+
+ if (fViewer instanceof ITextViewerExtension2 && fContentType != null)
+ ((ITextViewerExtension2) fViewer).removeAutoEditStrategy(fManager,
+ fContentType);
+ fContentType = null;
+
+ fViewer.removeTextListener(this);
+ fViewer.removeTextInputListener(this);
+
+ try {
+ IDocument document = fViewer.getDocument();
+
+ if (((flags & COMMIT) != 0) && ((flags & DOCUMENT_CHANGED) == 0)
+ && ((flags & UPDATE_CARET) != 0)) {
+ Position[] positions = document
+ .getPositions(fPositionCategoryName);
+ if ((positions != null) && (positions.length != 0)) {
+
+ if (fViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension3 = (ITextViewerExtension5) fViewer;
+ int widgetOffset = extension3
+ .modelOffset2WidgetOffset(positions[0]
+ .getOffset());
+ if (widgetOffset >= 0)
+ text.setSelection(widgetOffset, widgetOffset);
+
+ } else {
+ IRegion region = fViewer.getVisibleRegion();
+ int offset = positions[0].getOffset()
+ - region.getOffset();
+ if ((offset >= 0) && (offset <= region.getLength()))
+ text.setSelection(offset, offset);
+ }
+ }
+ }
+
+ document.removePositionUpdater(fUpdater);
+ document.removePositionCategory(fPositionCategoryName);
+
+ if (fExitListener != null)
+ fExitListener.exit(((flags & COMMIT) != 0)
+ || ((flags & DOCUMENT_CHANGED) != 0));
+
+ } catch (BadPositionCategoryException e) {
+ WebUI.log(e);
+ Assert.isTrue(false);
+ }
+
+ if ((flags & DOCUMENT_CHANGED) == 0)
+ text.redraw();
+ }
+
+ private void next() {
+ if (!fIsActive)
+ ;// JavaPlugin.log(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionUI is
+ // not active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+
+ redrawRegion();
+
+ if (fFramePosition == fFinalCaretPosition)
+ fFramePosition = fManager.getFirstPosition();
+ else
+ fFramePosition = fManager.getNextPosition(fFramePosition
+ .getOffset());
+ if (fFramePosition == null) {
+ if (fFinalCaretPosition != null)
+ fFramePosition = fFinalCaretPosition;
+ else
+ fFramePosition = fManager.getFirstPosition();
+ }
+ if (fFramePosition == null) {
+ leave(UNINSTALL | COMMIT | UPDATE_CARET);
+ } else {
+ selectRegion();
+ // triggerContentAssist();
+ redrawRegion();
+ }
+ }
+
+ private void previous() {
+ if (!fIsActive)
+ ;// JavaPlugin.log(new Status(IStatus.WARNING,
+ // JavaPlugin.getPluginId(), IStatus.OK, "LinkedPositionUI is
+ // not active: "+fPositionCategoryName, new
+ // IllegalStateException())); //$NON-NLS-1$
+
+ redrawRegion();
+
+ fFramePosition = fManager.getPreviousPosition(fFramePosition
+ .getOffset());
+ if (fFramePosition == null) {
+ if (fFinalCaretPosition != null)
+ fFramePosition = fFinalCaretPosition;
+ else
+ fFramePosition = fManager.getLastPosition();
+ }
+ if (fFramePosition == null) {
+ leave(UNINSTALL | COMMIT | UPDATE_CARET);
+ } else {
+ selectRegion();
+ // triggerContentAssist();
+ redrawRegion();
+ }
+ }
+
+ /** Trigger content assist on choice positions */
+ // private void triggerContentAssist() {
+ // if (fFramePosition instanceof ProposalPosition) {
+ //
+ // ProposalPosition pp= (ProposalPosition) fFramePosition;
+ // initializeContentAssistant();
+ // if (fAssistant == null)
+ // return;
+ // fAssistant.setCompletions(pp.getChoices());
+ // fAssistant.showPossibleCompletions();
+ // } else {
+ // if (fAssistant != null)
+ // fAssistant.setCompletions(new ICompletionProposal[0]);
+ // }
+ // }
+ /** Lazy initialize content assistant for this linked ui */
+ // private void initializeContentAssistant() {
+ // if (fAssistant != null)
+ // return;
+ // fAssistant= new ContentAssistant2();
+ // fAssistant.setDocumentPartitioning(IJavaPartitions.JAVA_PARTITIONING);
+ // fAssistant.install(fViewer);
+ // }
+ /*
+ * @see VerifyKeyListener#verifyKey(VerifyEvent)
+ */
+ public void verifyKey(VerifyEvent event) {
+
+ if (!event.doit || !fIsActive)
+ return;
+
+ Point selection = fViewer.getSelectedRange();
+ int offset = selection.x;
+ int length = selection.y;
+
+ ExitFlags exitFlags = fExitPolicy == null ? null : fExitPolicy.doExit(
+ fManager, event, offset, length);
+ if (exitFlags != null) {
+ leave(UNINSTALL | exitFlags.flags);
+ event.doit = exitFlags.doit;
+ return;
+ }
+
+ switch (event.character) {
+ // [SHIFT-]TAB = hop between edit boxes
+ case 0x09: {
+ // if tab was treated as a document change, would it exceed variable
+ // range?
+ if (!LinkedPositionManager.includes(fFramePosition, offset, length)) {
+ leave(UNINSTALL | COMMIT);
+ return;
+ }
+ }
+
+ if (event.stateMask == SWT.SHIFT)
+ previous();
+ else
+ next();
+
+ event.doit = false;
+ break;
+
+ // ENTER
+ case 0x0A: // Ctrl+Enter
+ case 0x0D: {
+ // if (fAssistant != null && fAssistant.wasProposalChosen()) {
+ // next();
+ // event.doit= false;
+ // break;
+ // }
+
+ // if enter was treated as a document change, would it exceed
+ // variable range?
+ if (!LinkedPositionManager.includes(fFramePosition, offset, length)
+ || (fFramePosition == fFinalCaretPosition)) {
+ leave(UNINSTALL | COMMIT);
+ return;
+ }
+ }
+
+ leave(UNINSTALL | COMMIT | UPDATE_CARET);
+ event.doit = false;
+ break;
+
+ // ESC
+ case 0x1B:
+ leave(UNINSTALL | COMMIT);
+ event.doit = false;
+ break;
+
+ case ';':
+ leave(UNINSTALL | COMMIT);
+ event.doit = true;
+ break;
+
+ default:
+ if (event.character != 0) {
+ if (!controlUndoBehavior(offset, length)
+ || fFramePosition == fFinalCaretPosition) {
+ leave(UNINSTALL | COMMIT);
+ break;
+ }
+ }
+ }
+ }
+
+ private boolean controlUndoBehavior(int offset, int length) {
+
+ Position position = fManager.getEmbracingPosition(offset, length);
+ if (position != null) {
+
+ ITextViewerExtension extension = (ITextViewerExtension) fViewer;
+ IRewriteTarget target = extension.getRewriteTarget();
+
+ if (fPreviousPosition != null
+ && !fPreviousPosition.equals(position))
+ target.endCompoundChange();
+ target.beginCompoundChange();
+ }
+
+ fPreviousPosition = position;
+ return fPreviousPosition != null;
+ }
+
+ /*
+ * @see VerifyListener#verifyText(VerifyEvent)
+ */
+ public void verifyText(VerifyEvent event) {
+ if (!event.doit)
+ return;
+
+ int offset = 0;
+ int length = 0;
+
+ if (fViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) fViewer;
+ IRegion modelRange = extension.widgetRange2ModelRange(new Region(
+ event.start, event.end - event.start));
+ if (modelRange == null)
+ return;
+
+ offset = modelRange.getOffset();
+ length = modelRange.getLength();
+
+ } else {
+ IRegion visibleRegion = fViewer.getVisibleRegion();
+ offset = event.start + visibleRegion.getOffset();
+ length = event.end - event.start;
+ }
+
+ // allow changes only within linked positions when coming through UI
+ if (!fManager.anyPositionIncludes(offset, length))
+ leave(UNINSTALL | COMMIT);
+ }
+
+ /*
+ * @see PaintListener#paintControl(PaintEvent)
+ */
+ public void paintControl(PaintEvent event) {
+ if (fFramePosition == null)
+ return;
+
+ IRegion widgetRange = asWidgetRange(fFramePosition);
+ if (widgetRange == null) {
+ leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED);
+ return;
+ }
+
+ int offset = widgetRange.getOffset();
+ int length = widgetRange.getLength();
+
+ StyledText text = fViewer.getTextWidget();
+
+ // support for bidi
+ Point minLocation = getMinimumLocation(text, offset, length);
+ Point maxLocation = getMaximumLocation(text, offset, length);
+
+ int x1 = minLocation.x;
+ int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
+ int y = minLocation.y + text.getLineHeight() - 1;
+
+ GC gc = event.gc;
+ gc.setForeground(fFrameColor);
+ gc.drawLine(x1, y, x2, y);
+ }
+
+ protected IRegion asWidgetRange(Position position) {
+ if (fViewer instanceof ITextViewerExtension5) {
+
+ ITextViewerExtension5 extension = (ITextViewerExtension5) fViewer;
+ return extension.modelRange2WidgetRange(new Region(position
+ .getOffset(), position.getLength()));
+
+ } else {
+
+ IRegion region = fViewer.getVisibleRegion();
+ if (includes(region, position))
+ return new Region(position.getOffset() - region.getOffset(),
+ position.getLength());
+ }
+
+ return null;
+ }
+
+ private static Point getMinimumLocation(StyledText text, int offset,
+ int length) {
+ Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+
+ for (int i = 0; i <= length; i++) {
+ Point location = text.getLocationAtOffset(offset + i);
+
+ if (location.x < minLocation.x)
+ minLocation.x = location.x;
+ if (location.y < minLocation.y)
+ minLocation.y = location.y;
+ }
+
+ return minLocation;
+ }
+
+ private static Point getMaximumLocation(StyledText text, int offset,
+ int length) {
+ Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
+
+ for (int i = 0; i <= length; i++) {
+ Point location = text.getLocationAtOffset(offset + i);
+
+ if (location.x > maxLocation.x)
+ maxLocation.x = location.x;
+ if (location.y > maxLocation.y)
+ maxLocation.y = location.y;
+ }
+
+ return maxLocation;
+ }
+
+ private void redrawRegion() {
+ IRegion widgetRange = asWidgetRange(fFramePosition);
+ if (widgetRange == null) {
+ leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED);
+ return;
+ }
+
+ StyledText text = fViewer.getTextWidget();
+ if (text != null && !text.isDisposed())
+ text.redrawRange(widgetRange.getOffset(), widgetRange.getLength(),
+ true);
+ }
+
+ private void selectRegion() {
+
+ IRegion widgetRange = asWidgetRange(fFramePosition);
+ if (widgetRange == null) {
+ leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED);
+ return;
+ }
+
+ StyledText text = fViewer.getTextWidget();
+ if (text != null && !text.isDisposed()) {
+ int start = widgetRange.getOffset();
+ int end = widgetRange.getLength() + start;
+ text.setSelection(start, end);
+ }
+ }
+
+ private void updateCaret() {
+
+ IRegion widgetRange = asWidgetRange(fFramePosition);
+ if (widgetRange == null) {
+ leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED);
+ return;
+ }
+
+ int offset = widgetRange.getOffset() + fCaretOffset;
+ StyledText text = fViewer.getTextWidget();
+ if (text != null && !text.isDisposed())
+ text.setCaretOffset(offset);
+ }
+
+ /*
+ * @see ModifyListener#modifyText(ModifyEvent)
+ */
+ public void modifyText(ModifyEvent e) {
+ // reposition caret after StyledText
+ redrawRegion();
+ updateCaret();
+ }
+
+ private static void handleException(Shell shell, Exception e) {
+ String title = LinkedPositionMessages
+ .getString("LinkedPositionUI.error.title"); //$NON-NLS-1$
+ if (e instanceof CoreException)
+ ExceptionHandler.handle((CoreException) e, shell, title, null);
+ else if (e instanceof InvocationTargetException)
+ ExceptionHandler.handle((InvocationTargetException) e, shell,
+ title, null);
+ else {
+ MessageDialog.openError(shell, title, e.getMessage());
+ WebUI.log(e);
+ }
+ }
+
+ /*
+ * @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument,
+ * IDocument)
+ */
+ public void inputDocumentAboutToBeChanged(IDocument oldInput,
+ IDocument newInput) {
+ // 5326: leave linked mode on document change
+ int flags = UNINSTALL | COMMIT
+ | (oldInput.equals(newInput) ? 0 : DOCUMENT_CHANGED);
+ leave(flags);
+ }
+
+ /*
+ * @see ITextInputListener#inputDocumentChanged(IDocument, IDocument)
+ */
+ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+ }
+
+ private static boolean includes(IRegion region, Position position) {
+ return position.getOffset() >= region.getOffset()
+ && position.getOffset() + position.getLength() <= region
+ .getOffset()
+ + region.getLength();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextListener#textChanged(TextEvent)
+ */
+ public void textChanged(TextEvent event) {
+ if (!fNeedRedraw)
+ return;
+
+ redrawRegion();
+ fNeedRedraw = false;
+ }
+
+ /*
+ * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
+ */
+ public void shellActivated(ShellEvent event) {
+ }
+
+ /*
+ * @see org.eclipse.swt.events.ShellListener#shellClosed(org.eclipse.swt.events.ShellEvent)
+ */
+ public void shellClosed(ShellEvent event) {
+ leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED);
+ }
+
+ /*
+ * @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
+ */
+ public void shellDeactivated(ShellEvent event) {
+ // don't deactivate on focus lost, since the proposal popups may take
+ // focus
+ // plus: it doesn't hurt if you can check with another window without
+ // losing linked mode
+ // since there is no intrusive popup sticking out.
+
+ // need to check first what happens on reentering based on an open
+ // action
+ // Seems to be no problem
+
+ // TODO check whether we can leave it or uncomment it after debugging
+ // PS: why DOCUMENT_CHANGED? We want to trigger a redraw! (Shell
+ // deactivated does not mean
+ // it is not visible any longer.
+ // leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED);
+
+ // Better:
+ // Check with content assistant and only leave if its not the proposal
+ // shell that took the
+ // focus away.
+
+ StyledText text;
+ Display display;
+
+ // if (fAssistant == null || fViewer == null || (text=
+ // fViewer.getTextWidget()) == null
+ // || (display= text.getDisplay()) == null || display.isDisposed()) {
+ if (fViewer == null || (text = fViewer.getTextWidget()) == null
+ || (display = text.getDisplay()) == null
+ || display.isDisposed()) {
+ leave(UNINSTALL | COMMIT);
+ } else {
+ // Post in UI thread since the assistant popup will only get the
+ // focus after we lose it.
+ display.asyncExec(new Runnable() {
+ public void run() {
+ // TODO add isDisposed / isUninstalled / hasLeft check? for
+ // now: check for content type,
+ // since it gets nullified in leave()
+ if (fIsActive) {// && (fAssistant == null ||
+ // !fAssistant.hasFocus())) {
+ leave(UNINSTALL | COMMIT);
+ }
+ }
+ });
+ }
+ }
+
+ /*
+ * @see org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse.swt.events.ShellEvent)
+ */
+ public void shellDeiconified(ShellEvent event) {
+ }
+
+ /*
+ * @see org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt.events.ShellEvent)
+ */
+ public void shellIconified(ShellEvent event) {
+ leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/ProposalPosition.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/ProposalPosition.java
new file mode 100644
index 0000000..4996443
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/link/ProposalPosition.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.link;
+
+import java.util.Arrays;
+
+import org.eclipse.jface.text.TypedPosition;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+
+/**
+ *
+ */
+public class ProposalPosition extends TypedPosition {
+
+ /**
+ * The choices available for this position, fChoices[0] is the original
+ * type.
+ */
+ private final ICompletionProposal[] fChoices;
+
+ /*
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object o) {
+ if (o instanceof ProposalPosition) {
+ if (super.equals(o)) {
+ return Arrays.equals(fChoices, ((ProposalPosition) o).fChoices);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param offset
+ * @param length
+ * @param type
+ */
+ public ProposalPosition(int offset, int length, String type,
+ ICompletionProposal[] choices) {
+ super(offset, length, type);
+ fChoices = new ICompletionProposal[choices.length];
+ System.arraycopy(choices, 0, fChoices, 0, choices.length);
+ }
+
+ /**
+ *
+ * @return an array of choices, including the initial one. Clients must not
+ * modify it.
+ */
+ public ICompletionProposal[] getChoices() {
+ updateChoicePositions();
+ return fChoices;
+ }
+
+ /**
+ *
+ */
+ private void updateChoicePositions() {
+ for (int i = 0; i < fChoices.length; i++) {
+ // if (fChoices[i] instanceof JavaCompletionProposal)
+ // ((JavaCompletionProposal)fChoices[i]).setReplacementOffset(offset);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/IHtmlTagConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/IHtmlTagConstants.java
new file mode 100644
index 0000000..859d9b3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/IHtmlTagConstants.java
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *****************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.phpdoc;
+
+/**
+ * Html tag constants.
+ *
+ * @since 3.0
+ */
+public interface IHtmlTagConstants {
+
+ /** Html tag close prefix */
+ public static final String HTML_CLOSE_PREFIX = ""; //$NON-NLS-1$
+
+ /** Html entity characters */
+ public static final char[] HTML_ENTITY_CHARACTERS = new char[] { '<', '>',
+ ' ', '&', '^', '~', '\"' };
+
+ /** Html entity codes */
+ public static final String[] HTML_ENTITY_CODES = new String[] {
+ "<", ">", " ", "&", "ˆ", "˜", """ }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+
+ /** Html general tags */
+ public static final String[] HTML_GENERAL_TAGS = new String[] {
+ "b", "blockquote", "br", "code", "dd", "dl", "dt", "em", "hr", "h1", "h2", "h3", "h4", "h5", "h6", "i", "li", "nl", "ol", "p", "pre", "q", "td", "th", "tr", "tt", "ul" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ //$NON-NLS-19$ //$NON-NLS-20$ //$NON-NLS-21$ //$NON-NLS-22$ //$NON-NLS-23$ //$NON-NLS-24$ //$NON-NLS-25$ //$NON-NLS-26$ //$NON-NLS-27$
+
+ /** Html tag postfix */
+ public static final char HTML_TAG_POSTFIX = '>';
+
+ /** Html tag prefix */
+ public static final char HTML_TAG_PREFIX = '<';
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/IJavaDocTagConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/IJavaDocTagConstants.java
new file mode 100644
index 0000000..c815382
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/IJavaDocTagConstants.java
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *****************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.phpdoc;
+
+/**
+ * Javadoc tag constants.
+ *
+ * @since 3.0
+ */
+public interface IJavaDocTagConstants {
+
+ /** Javadoc break tags */
+ public static final String[] JAVADOC_BREAK_TAGS = new String[] {
+ "dd", "dt", "li", "td", "th", "tr", "h1", "h2", "h3", "h4", "h5", "h6", "q" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$
+
+ /** Javadoc single break tag */
+ public static final String[] JAVADOC_SINGLE_BREAK_TAG = new String[] { "br" }; //$NON-NLS-1$
+
+ /** Javadoc code tags */
+ public static final String[] JAVADOC_CODE_TAGS = new String[] { "pre" }; //$NON-NLS-1$
+
+ /** Javadoc general tags */
+ public static final String[] JAVADOC_GENERAL_TAGS = new String[] {
+ "@author", "@deprecated", "@exception", "@link", "@param", "@return", "@see", "@since", "@throws", "@value", "@version", "@license", "@abstract", "@access", "@category",
+ "@copyright", "@example", "@final", "@filesource", "@global", "@ignore", "@internal", "@link", "@method", "@name", "@package", "@param", "@property", "@static",
+ "@staticvar", "@subpackage", "@todo", "@tutorial", "@uses", "@var","@id", "inheritdoc", "@property-read", "@property-write", "@source"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$
+
+ /** Javadoc immutable tags */
+ public static final String[] JAVADOC_IMMUTABLE_TAGS = new String[] {
+ "code", "em", "pre", "q", "tt" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ /** Javadoc link tags */
+ public static final String[] JAVADOC_LINK_TAGS = new String[] {
+ "@docRoot", "@inheritDoc", "@link", "@linkplain" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ /** Javadoc new line tags */
+ public static final String[] JAVADOC_NEWLINE_TAGS = new String[] {
+ "dd", "dt", "li", "td", "th", "tr", "h1", "h2", "h3", "h4", "h5", "h6", "q" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$
+
+ /** Javadoc parameter tags */
+ public static final String[] JAVADOC_PARAM_TAGS = new String[] {
+ "@exception", "@param", "@serialField", "@throws" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ /** Javadoc reference tags */
+ public static final String[] JAVADOC_REFERENCE_TAGS = new String[] { "@see" }; //$NON-NLS-1$
+
+ /** Javadoc root tags */
+ public static final String[] JAVADOC_ROOT_TAGS = new String[] {
+ "@author", "@deprecated", "@return", "@see", "@serial", "@serialData", "@since", "@version", "@inheritDoc" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
+
+ /** Javadoc separator tags */
+ public static final String[] JAVADOC_SEPARATOR_TAGS = new String[] {
+ "dl", "hr", "nl", "p", "pre", "ul", "ol" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+
+ /** Javadoc tag prefix */
+ public static final char JAVADOC_TAG_PREFIX = '@';
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/JavaDocAutoIndentStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/JavaDocAutoIndentStrategy.java
new file mode 100644
index 0000000..708a7b6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/JavaDocAutoIndentStrategy.java
@@ -0,0 +1,938 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.phpdoc;
+
+import java.text.BreakIterator;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+import net.sourceforge.phpdt.ui.CodeGeneration;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+
+/**
+ * Auto indent strategy for java doc comments
+ */
+public class JavaDocAutoIndentStrategy extends
+ DefaultIndentLineAutoEditStrategy {
+
+ private String fPartitioning;
+
+ /**
+ * Creates a new Javadoc auto indent strategy for the given document
+ * partitioning.
+ *
+ * @param partitioning
+ * the document partitioning
+ */
+ public JavaDocAutoIndentStrategy(String partitioning) {
+ fPartitioning = partitioning;
+ }
+
+ private static String getLineDelimiter(IDocument document) {
+ try {
+ if (document.getNumberOfLines() > 1)
+ return document.getLineDelimiter(0);
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ }
+
+ return System.getProperty("line.separator"); //$NON-NLS-1$
+ }
+
+ /**
+ * Copies the indentation of the previous line and add a star. If the
+ * javadoc just started on this line add standard method tags and close the
+ * javadoc.
+ *
+ * @param d
+ * the document to work on
+ * @param c
+ * the command to deal with
+ */
+ private void jdocIndentAfterNewLine(IDocument d, DocumentCommand c) {
+
+ if (c.offset == -1 || d.getLength() == 0)
+ return;
+
+ try {
+ // find start of line
+ int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset);
+ IRegion info = d.getLineInformationOfOffset(p);
+ int start = info.getOffset();
+
+ // find white spaces
+ int end = findEndOfWhiteSpace(d, start, c.offset);
+
+ StringBuffer buf = new StringBuffer(c.text);
+ if (end >= start) { // 1GEYL1R: ITPJUI:ALL - java doc edit smartness
+ // not work for class comments
+ // append to input
+ String indentation = jdocExtractLinePrefix(d, d
+ .getLineOfOffset(c.offset));
+ buf.append(indentation);
+ if (end < c.offset) {
+ if (d.getChar(end) == '/') {
+ // javadoc started on this line
+ buf.append(" * "); //$NON-NLS-1$
+
+ if (WebUI
+ .getDefault()
+ .getPreferenceStore()
+ .getBoolean(
+ PreferenceConstants.EDITOR_CLOSE_JAVADOCS)
+ && isNewComment(d, c.offset, fPartitioning)) {
+ String lineDelimiter = getLineDelimiter(d);
+
+ String endTag = lineDelimiter + indentation + " */"; //$NON-NLS-1$
+ d.replace(c.offset, 0, endTag); //$NON-NLS-1$
+ // evaluate method signature
+ ICompilationUnit unit = getCompilationUnit();
+
+ // if
+ // (PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS)
+ // &&
+ // unit != null)
+ // {
+ // try {
+ // JavaModelUtil.reconcile(unit);
+ // String string= createJavaDocTags(d, c,
+ // indentation, lineDelimiter, unit);
+ // if (string != null) {
+ // d.replace(c.offset, 0, string);
+ // }
+ // } catch (CoreException e) {
+ // // ignore
+ // }
+ // }
+ }
+
+ }
+ }
+ }
+
+ c.text = buf.toString();
+
+ } catch (BadLocationException excp) {
+ // stop work
+ }
+ }
+
+ private String createJavaDocTags(IDocument document,
+ DocumentCommand command, String indentation, String lineDelimiter,
+ ICompilationUnit unit) throws CoreException, BadLocationException {
+ IJavaElement element = unit.getElementAt(command.offset);
+ if (element == null)
+ return null;
+
+ switch (element.getElementType()) {
+ case IJavaElement.TYPE:
+ return createTypeTags(document, command, indentation,
+ lineDelimiter, (IType) element);
+
+ case IJavaElement.METHOD:
+ return createMethodTags(document, command, indentation,
+ lineDelimiter, (IMethod) element);
+
+ default:
+ return null;
+ }
+ }
+
+ /*
+ * Removes start and end of a comment and corrects indentation and line
+ * delimiters.
+ */
+ private String prepareTemplateComment(String comment, String indentation,
+ String lineDelimiter) {
+ // trim comment start and end if any
+ if (comment.endsWith("*/")) //$NON-NLS-1$
+ comment = comment.substring(0, comment.length() - 2);
+ comment = comment.trim();
+ if (comment.startsWith("/*")) { //$NON-NLS-1$
+ if (comment.length() > 2 && comment.charAt(2) == '*') {
+ comment = comment.substring(3); // remove '/**'
+ } else {
+ comment = comment.substring(2); // remove '/*'
+ }
+ }
+ // return Strings.changeIndent(comment, 0,
+ // CodeFormatterUtil.getTabWidth(), indentation, lineDelimiter);
+ return Strings.changeIndent(comment, 0, getTabWidth(), indentation,
+ lineDelimiter);
+ }
+
+ public static int getTabWidth() {
+ Preferences preferences = WebUI.getDefault()
+ .getPluginPreferences();
+ return preferences
+ .getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
+ }
+
+ private String createTypeTags(IDocument document, DocumentCommand command,
+ String indentation, String lineDelimiter, IType type)
+ throws CoreException {
+ String comment = CodeGeneration.getTypeComment(type
+ .getCompilationUnit(), type.getTypeQualifiedName('.'),
+ lineDelimiter);
+ if (comment != null) {
+ return prepareTemplateComment(comment.trim(), indentation,
+ lineDelimiter);
+ }
+ return null;
+ }
+
+ private String createMethodTags(IDocument document,
+ DocumentCommand command, String indentation, String lineDelimiter,
+ IMethod method) throws CoreException, BadLocationException {
+ IRegion partition = TextUtilities.getPartition(document, fPartitioning,
+ command.offset, false);
+ ISourceRange sourceRange = method.getSourceRange();
+ if (sourceRange == null
+ || sourceRange.getOffset() != partition.getOffset())
+ return null;
+
+ // IMethod inheritedMethod= getInheritedMethod(method);
+ // String comment= CodeGeneration.getMethodComment(method,
+ // inheritedMethod, lineDelimiter);
+ // if (comment != null) {
+ // comment= comment.trim();
+ // boolean javadocComment= comment.startsWith("/**"); //$NON-NLS-1$
+ // boolean isJavaDoc= partition.getLength() >= 3 &&
+ // document.get(partition.getOffset(), 3).equals("/**"); //$NON-NLS-1$
+ // if (javadocComment == isJavaDoc) {
+ // return prepareTemplateComment(comment, indentation, lineDelimiter);
+ // }
+ // }
+ return null;
+ }
+
+ /**
+ * Returns the method inherited from, null
if method is newly
+ * defined.
+ */
+ // private static IMethod getInheritedMethod(IMethod method) throws
+ // JavaModelException {
+ // IType declaringType= method.getDeclaringType();
+ // ITypeHierarchy typeHierarchy=
+ // SuperTypeHierarchyCache.getTypeHierarchy(declaringType);
+ // return JavaModelUtil.findMethodDeclarationInHierarchy(typeHierarchy,
+ // declaringType,
+ // method.getElementName(), method.getParameterTypes(),
+ // method.isConstructor());
+ // }
+ protected void jdocIndentForCommentEnd(IDocument d, DocumentCommand c) {
+ if (c.offset < 2 || d.getLength() == 0) {
+ return;
+ }
+ try {
+ if ("* ".equals(d.get(c.offset - 2, 2))) { //$NON-NLS-1$
+ // modify document command
+ c.length++;
+ c.offset--;
+ }
+ } catch (BadLocationException excp) {
+ // stop work
+ }
+ }
+
+ /**
+ * Guesses if the command operates within a newly created javadoc comment or
+ * not. If in doubt, it will assume that the javadoc is new.
+ */
+ private static boolean isNewComment(IDocument document, int commandOffset,
+ String partitioning) {
+
+ try {
+ int lineIndex = document.getLineOfOffset(commandOffset) + 1;
+ if (lineIndex >= document.getNumberOfLines())
+ return true;
+
+ IRegion line = document.getLineInformation(lineIndex);
+ ITypedRegion partition = TextUtilities.getPartition(document,
+ partitioning, commandOffset, false);
+ int partitionEnd = partition.getOffset() + partition.getLength();
+ if (line.getOffset() >= partitionEnd)
+ return false;
+
+ if (document.getLength() == partitionEnd)
+ return true; // partition goes to end of document - probably
+ // a new comment
+
+ String comment = document.get(partition.getOffset(), partition
+ .getLength());
+ if (comment.indexOf("/*", 2) != -1) //$NON-NLS-1$
+ return true; // enclosed another comment -> probably a new
+ // comment
+
+ return false;
+
+ } catch (BadLocationException e) {
+ return false;
+ }
+ }
+
+ private boolean isSmartMode() {
+ IWorkbenchPage page = WebUI.getActivePage();
+ if (page != null) {
+ IEditorPart part = page.getActiveEditor();
+ if (part instanceof ITextEditorExtension3) {
+ ITextEditorExtension3 extension = (ITextEditorExtension3) part;
+ return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see IAutoIndentStrategy#customizeDocumentCommand
+ */
+ public void customizeDocumentCommand(IDocument document,
+ DocumentCommand command) {
+
+ if (!isSmartMode())
+ return;
+
+ try {
+
+ if (command.text != null && command.length == 0) {
+ String[] lineDelimiters = document.getLegalLineDelimiters();
+ int index = TextUtilities
+ .endsWith(lineDelimiters, command.text);
+ if (index > -1) {
+ // ends with line delimiter
+ if (lineDelimiters[index].equals(command.text))
+ // just the line delimiter
+ jdocIndentAfterNewLine(document, command);
+ return;
+ }
+ }
+
+ if (command.text != null && command.text.equals("/")) { //$NON-NLS-1$
+ jdocIndentForCommentEnd(document, command);
+ return;
+ }
+
+ ITypedRegion partition = TextUtilities.getPartition(document,
+ fPartitioning, command.offset, true);
+ int partitionStart = partition.getOffset();
+ int partitionEnd = partition.getLength() + partitionStart;
+
+ String text = command.text;
+ int offset = command.offset;
+ int length = command.length;
+
+ // partition change
+ final int PREFIX_LENGTH = "/*".length(); //$NON-NLS-1$
+ final int POSTFIX_LENGTH = "*/".length(); //$NON-NLS-1$
+ if ((offset < partitionStart + PREFIX_LENGTH || offset + length > partitionEnd
+ - POSTFIX_LENGTH)
+ || text != null
+ && text.length() >= 2
+ && ((text.indexOf("*/") != -1) || (document.getChar(offset) == '*' && text.startsWith("/")))) //$NON-NLS-1$ //$NON-NLS-2$
+ return;
+
+ if (command.text == null || command.text.length() == 0)
+ jdocHandleBackspaceDelete(document, command);
+
+ else if (command.text != null && command.length == 0
+ && command.text.length() > 0)
+ jdocWrapParagraphOnInsert(document, command);
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ }
+ }
+
+ private void flushCommand(IDocument document, DocumentCommand command)
+ throws BadLocationException {
+
+ if (!command.doit)
+ return;
+
+ document.replace(command.offset, command.length, command.text);
+
+ command.doit = false;
+ if (command.text != null)
+ command.offset += command.text.length();
+ command.length = 0;
+ command.text = null;
+ }
+
+ protected void jdocWrapParagraphOnInsert(IDocument document,
+ DocumentCommand command) throws BadLocationException {
+
+ // Assert.isTrue(command.length == 0);
+ // Assert.isTrue(command.text != null && command.text.length() == 1);
+
+ if (!getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_FORMAT_JAVADOCS))
+ return;
+
+ int line = document.getLineOfOffset(command.offset);
+ IRegion region = document.getLineInformation(line);
+ int lineOffset = region.getOffset();
+ int lineLength = region.getLength();
+
+ String lineContents = document.get(lineOffset, lineLength);
+ StringBuffer buffer = new StringBuffer(lineContents);
+ int start = command.offset - lineOffset;
+ int end = command.length + start;
+ buffer.replace(start, end, command.text);
+
+ // handle whitespace
+ if (command.text != null && command.text.length() != 0
+ && command.text.trim().length() == 0) {
+
+ String endOfLine = document.get(command.offset, lineOffset
+ + lineLength - command.offset);
+
+ // end of line
+ if (endOfLine.length() == 0) {
+ // move caret to next line
+ flushCommand(document, command);
+
+ if (isLineTooShort(document, line)) {
+ int[] caretOffset = { command.offset };
+ jdocWrapParagraphFromLine(document, line, caretOffset,
+ false);
+ command.offset = caretOffset[0];
+ return;
+ }
+
+ // move caret to next line if possible
+ if (line < document.getNumberOfLines() - 1
+ && isJavaDocLine(document, line + 1)) {
+ String lineDelimiter = document.getLineDelimiter(line);
+ String nextLinePrefix = jdocExtractLinePrefix(document,
+ line + 1);
+ command.offset += lineDelimiter.length()
+ + nextLinePrefix.length();
+ }
+ return;
+
+ // inside whitespace at end of line
+ } else if (endOfLine.trim().length() == 0) {
+ // simply insert space
+ return;
+ }
+ }
+
+ // change in prefix region
+ String prefix = jdocExtractLinePrefix(document, line);
+ boolean wrapAlways = command.offset >= lineOffset
+ && command.offset <= lineOffset + prefix.length();
+
+ // must insert the text now because it may include whitepace
+ flushCommand(document, command);
+
+ if (wrapAlways
+ || calculateDisplayedWidth(buffer.toString()) > getMargin()
+ || isLineTooShort(document, line)) {
+ int[] caretOffset = { command.offset };
+ jdocWrapParagraphFromLine(document, line, caretOffset, wrapAlways);
+
+ if (!wrapAlways)
+ command.offset = caretOffset[0];
+ }
+ }
+
+ /**
+ * Method jdocWrapParagraphFromLine.
+ *
+ * @param document
+ * @param line
+ * @param always
+ */
+ private void jdocWrapParagraphFromLine(IDocument document, int line,
+ int[] caretOffset, boolean always) throws BadLocationException {
+
+ String indent = jdocExtractLinePrefix(document, line);
+ if (!always) {
+ if (!indent.trim().startsWith("*")) //$NON-NLS-1$
+ return;
+
+ if (indent.trim().startsWith("*/")) //$NON-NLS-1$
+ return;
+
+ if (!isLineTooLong(document, line)
+ && !isLineTooShort(document, line))
+ return;
+ }
+
+ boolean caretRelativeToParagraphOffset = false;
+ int caret = caretOffset[0];
+
+ int caretLine = document.getLineOfOffset(caret);
+ int lineOffset = document.getLineOffset(line);
+ int paragraphOffset = lineOffset + indent.length();
+ if (paragraphOffset < caret) {
+ caret -= paragraphOffset;
+ caretRelativeToParagraphOffset = true;
+ } else {
+ caret -= lineOffset;
+ }
+
+ StringBuffer buffer = new StringBuffer();
+ int currentLine = line;
+ while (line == currentLine || isJavaDocLine(document, currentLine)) {
+
+ if (buffer.length() != 0
+ && !Character.isWhitespace(buffer
+ .charAt(buffer.length() - 1))) {
+ buffer.append(' ');
+ if (currentLine <= caretLine) {
+ // in this case caretRelativeToParagraphOffset is always
+ // true
+ ++caret;
+ }
+ }
+
+ String string = getLineContents(document, currentLine);
+ buffer.append(string);
+ currentLine++;
+ }
+ String paragraph = buffer.toString();
+
+ if (paragraph.trim().length() == 0)
+ return;
+
+ caretOffset[0] = caretRelativeToParagraphOffset ? caret : 0;
+ String delimiter = document.getLineDelimiter(0);
+ String wrapped = formatParagraph(paragraph, caretOffset, indent,
+ delimiter, getMargin());
+
+ int beginning = document.getLineOffset(line);
+ int end = document.getLineOffset(currentLine);
+ document.replace(beginning, end - beginning, wrapped.toString());
+
+ caretOffset[0] = caretRelativeToParagraphOffset ? caretOffset[0]
+ + beginning : caret + beginning;
+ }
+
+ /**
+ * Line break iterator to handle whitespaces as first class citizens.
+ */
+ private static class LineBreakIterator {
+
+ private final String fString;
+
+ private final BreakIterator fIterator = BreakIterator.getLineInstance();
+
+ private int fStart;
+
+ private int fEnd;
+
+ private int fBufferedEnd;
+
+ public LineBreakIterator(String string) {
+ fString = string;
+ fIterator.setText(string);
+ }
+
+ public int first() {
+ fBufferedEnd = -1;
+ fStart = fIterator.first();
+ return fStart;
+ }
+
+ public int next() {
+
+ if (fBufferedEnd != -1) {
+ fStart = fEnd;
+ fEnd = fBufferedEnd;
+ fBufferedEnd = -1;
+ return fEnd;
+ }
+
+ fStart = fEnd;
+ fEnd = fIterator.next();
+
+ if (fEnd == BreakIterator.DONE)
+ return fEnd;
+
+ final String string = fString.substring(fStart, fEnd);
+
+ // whitespace
+ if (string.trim().length() == 0)
+ return fEnd;
+
+ final String word = string.trim();
+ if (word.length() == string.length())
+ return fEnd;
+
+ // suspected whitespace
+ fBufferedEnd = fEnd;
+ return fStart + word.length();
+ }
+ }
+
+ /**
+ * Formats a paragraph, using break iterator.
+ *
+ * @param offset
+ * an offset within the paragraph, which will be updated with
+ * respect to formatting.
+ */
+ private static String formatParagraph(String paragraph, int[] offset,
+ String prefix, String lineDelimiter, int margin) {
+
+ LineBreakIterator iterator = new LineBreakIterator(paragraph);
+
+ StringBuffer paragraphBuffer = new StringBuffer();
+ StringBuffer lineBuffer = new StringBuffer();
+ StringBuffer whiteSpaceBuffer = new StringBuffer();
+
+ int index = offset[0];
+ int indexBuffer = -1;
+
+ // line delimiter could be null
+ if (lineDelimiter == null)
+ lineDelimiter = ""; //$NON-NLS-1$
+
+ for (int start = iterator.first(), end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator
+ .next()) {
+
+ String word = paragraph.substring(start, end);
+
+ // word is whitespace
+ if (word.trim().length() == 0) {
+ whiteSpaceBuffer.append(word);
+
+ // first word of line is always appended
+ } else if (lineBuffer.length() == 0) {
+ lineBuffer.append(prefix);
+ lineBuffer.append(whiteSpaceBuffer.toString());
+ lineBuffer.append(word);
+
+ } else {
+ String line = lineBuffer.toString()
+ + whiteSpaceBuffer.toString() + word.toString();
+
+ // margin exceeded
+ if (calculateDisplayedWidth(line) > margin) {
+ // flush line buffer and wrap paragraph
+ paragraphBuffer.append(lineBuffer.toString());
+ paragraphBuffer.append(lineDelimiter);
+ lineBuffer.setLength(0);
+ lineBuffer.append(prefix);
+ lineBuffer.append(word);
+
+ // flush index buffer
+ if (indexBuffer != -1) {
+ offset[0] = indexBuffer;
+ // correct for caret in whitespace at the end of line
+ if (whiteSpaceBuffer.length() != 0 && index < start
+ && index >= start - whiteSpaceBuffer.length())
+ offset[0] -= (index - (start - whiteSpaceBuffer
+ .length()));
+ indexBuffer = -1;
+ }
+
+ whiteSpaceBuffer.setLength(0);
+
+ // margin not exceeded
+ } else {
+ lineBuffer.append(whiteSpaceBuffer.toString());
+ lineBuffer.append(word);
+ whiteSpaceBuffer.setLength(0);
+ }
+ }
+
+ if (index >= start && index < end) {
+ indexBuffer = paragraphBuffer.length() + lineBuffer.length()
+ + (index - start);
+ if (word.trim().length() != 0)
+ indexBuffer -= word.length();
+ }
+ }
+
+ // flush line buffer
+ paragraphBuffer.append(lineBuffer.toString());
+ paragraphBuffer.append(lineDelimiter);
+
+ // flush index buffer
+ if (indexBuffer != -1)
+ offset[0] = indexBuffer;
+
+ // last position is not returned by break iterator
+ else if (offset[0] == paragraph.length())
+ offset[0] = paragraphBuffer.length() - lineDelimiter.length();
+
+ return paragraphBuffer.toString();
+ }
+
+ private static IPreferenceStore getPreferenceStore() {
+ return WebUI.getDefault().getPreferenceStore();
+ }
+
+ /**
+ * Returns the displayed width of a string, taking in account the displayed
+ * tab width. The result can be compared against the print margin.
+ */
+ private static int calculateDisplayedWidth(String string) {
+
+ int tabWidth = getPreferenceStore()
+ .getInt(
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
+ if (tabWidth <= 0) {
+ tabWidth = 2;
+ }
+ int column = 0;
+ for (int i = 0; i < string.length(); i++)
+ if ('\t' == string.charAt(i))
+ column += tabWidth - (column % tabWidth);
+ else
+ column++;
+
+ return column;
+ }
+
+ private String jdocExtractLinePrefix(IDocument d, int line)
+ throws BadLocationException {
+
+ IRegion region = d.getLineInformation(line);
+ int lineOffset = region.getOffset();
+ int index = findEndOfWhiteSpace(d, lineOffset, lineOffset
+ + d.getLineLength(line));
+ if (d.getChar(index) == '*') {
+ index++;
+ if (index != lineOffset + region.getLength()
+ && d.getChar(index) == ' ')
+ index++;
+ }
+ return d.get(lineOffset, index - lineOffset);
+ }
+
+ private String getLineContents(IDocument d, int line)
+ throws BadLocationException {
+ int offset = d.getLineOffset(line);
+ int length = d.getLineLength(line);
+ String lineDelimiter = d.getLineDelimiter(line);
+ if (lineDelimiter != null)
+ length = length - lineDelimiter.length();
+ String lineContents = d.get(offset, length);
+ int trim = jdocExtractLinePrefix(d, line).length();
+ return lineContents.substring(trim);
+ }
+
+ private static String getLine(IDocument document, int line)
+ throws BadLocationException {
+ IRegion region = document.getLineInformation(line);
+ return document.get(region.getOffset(), region.getLength());
+ }
+
+ /**
+ * Returns true
if the javadoc line is too short,
+ * false
otherwise.
+ */
+ private boolean isLineTooShort(IDocument document, int line)
+ throws BadLocationException {
+
+ if (!isJavaDocLine(document, line + 1))
+ return false;
+
+ String nextLine = getLineContents(document, line + 1);
+ if (nextLine.trim().length() == 0)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns true
if the line is too long, false
+ * otherwise.
+ */
+ private boolean isLineTooLong(IDocument document, int line)
+ throws BadLocationException {
+ String lineContents = getLine(document, line);
+ return calculateDisplayedWidth(lineContents) > getMargin();
+ }
+
+ private static int getMargin() {
+ return getPreferenceStore()
+ .getInt(
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN);
+ }
+
+ private static final String[] fgInlineTags = {
+ "", "", "", "", "" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ };
+
+ private boolean isInlineTag(String string) {
+ for (int i = 0; i < fgInlineTags.length; i++)
+ if (string.startsWith(fgInlineTags[i]))
+ return true;
+ return false;
+ }
+
+ /**
+ * returns true if the specified line is part of a paragraph and should be
+ * merged with the previous line.
+ */
+ private boolean isJavaDocLine(IDocument document, int line)
+ throws BadLocationException {
+
+ if (document.getNumberOfLines() < line)
+ return false;
+
+ int offset = document.getLineOffset(line);
+ int length = document.getLineLength(line);
+ int firstChar = findEndOfWhiteSpace(document, offset, offset + length);
+ length -= firstChar - offset;
+ String lineContents = document.get(firstChar, length);
+
+ String prefix = lineContents.trim();
+ if (!prefix.startsWith("*") || prefix.startsWith("*/")) //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+
+ lineContents = lineContents.substring(1).trim().toLowerCase();
+
+ // preserve empty lines
+ if (lineContents.length() == 0)
+ return false;
+
+ // preserve @TAGS
+ if (lineContents.startsWith("@")) //$NON-NLS-1$
+ return false;
+
+ // preserve HTML tags which are not inline
+ if (lineContents.startsWith("<") && !isInlineTag(lineContents)) //$NON-NLS-1$
+ return false;
+
+ return true;
+ }
+
+ protected void jdocHandleBackspaceDelete(IDocument document,
+ DocumentCommand c) {
+
+ if (!getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_FORMAT_JAVADOCS))
+ return;
+
+ try {
+ String text = document.get(c.offset, c.length);
+ int line = document.getLineOfOffset(c.offset);
+ int lineOffset = document.getLineOffset(line);
+
+ // erase line delimiter
+ String lineDelimiter = document.getLineDelimiter(line);
+ if (lineDelimiter != null && lineDelimiter.equals(text)) {
+
+ String prefix = jdocExtractLinePrefix(document, line + 1);
+
+ // strip prefix if any
+ if (prefix.length() > 0) {
+ int length = document.getLineDelimiter(line).length()
+ + prefix.length();
+ document.replace(c.offset, length, null);
+
+ c.doit = false;
+ c.length = 0;
+ return;
+ }
+
+ // backspace: beginning of a javadoc line
+ } else if (document.getChar(c.offset - 1) == '*'
+ && jdocExtractLinePrefix(document, line).length() - 1 >= c.offset
+ - lineOffset) {
+
+ lineDelimiter = document.getLineDelimiter(line - 1);
+ String prefix = jdocExtractLinePrefix(document, line);
+ int length = (lineDelimiter != null ? lineDelimiter.length()
+ : 0)
+ + prefix.length();
+ document.replace(c.offset - length + 1, length, null);
+
+ c.doit = false;
+ c.offset -= length - 1;
+ c.length = 0;
+ return;
+
+ } else {
+ document.replace(c.offset, c.length, null);
+ c.doit = false;
+ c.length = 0;
+ }
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ }
+
+ try {
+ int line = document.getLineOfOffset(c.offset);
+ int lineOffset = document.getLineOffset(line);
+ String prefix = jdocExtractLinePrefix(document, line);
+ boolean always = c.offset > lineOffset
+ && c.offset <= lineOffset + prefix.length();
+ int[] caretOffset = { c.offset };
+ jdocWrapParagraphFromLine(document, document
+ .getLineOfOffset(c.offset), caretOffset, always);
+ c.offset = caretOffset[0];
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ }
+ }
+
+ /**
+ * Returns the compilation unit of the CompilationUnitEditor invoking the
+ * AutoIndentStrategy, might return null
on error.
+ */
+ private static ICompilationUnit getCompilationUnit() {
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow();
+ if (window == null)
+ return null;
+
+ IWorkbenchPage page = window.getActivePage();
+ if (page == null)
+ return null;
+
+ IEditorPart editor = page.getActiveEditor();
+ if (editor == null)
+ return null;
+
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ ICompilationUnit unit = manager.getWorkingCopy(editor.getEditorInput());
+ if (unit == null)
+ return null;
+
+ return unit;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/PHPDocCodeScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/PHPDocCodeScanner.java
new file mode 100644
index 0000000..4e10a0c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/PHPDocCodeScanner.java
@@ -0,0 +1,179 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.phpdoc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPWhitespaceDetector;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+
+/**
+ * A rule based PHPDoc scanner.
+ */
+public final class PHPDocCodeScanner extends AbstractJavaScanner {
+
+ /**
+ * A key word detector.
+ */
+ static class JavaDocKeywordDetector implements IWordDetector {
+
+ /**
+ * @see IWordDetector#isWordStart
+ */
+ public boolean isWordStart(char c) {
+ return (c == '@');
+ }
+
+ /**
+ * @see IWordDetector#isWordPart
+ */
+ public boolean isWordPart(char c) {
+ return Character.isLetter(c);
+ }
+ };
+
+ /**
+ * Detector for HTML comment delimiters.
+ */
+ static class HTMLCommentDetector implements IWordDetector {
+
+ /**
+ * @see IWordDetector#isWordStart
+ */
+ public boolean isWordStart(char c) {
+ return (c == '<' || c == '-');
+ }
+
+ /**
+ * @see IWordDetector#isWordPart
+ */
+ public boolean isWordPart(char c) {
+ return (c == '-' || c == '!' || c == '>');
+ }
+ };
+
+ class TagRule extends SingleLineRule {
+
+ /*
+ * @see SingleLineRule
+ */
+ public TagRule(IToken token) {
+ super("<", ">", token, (char) 0); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ /*
+ * @see SingleLineRule
+ */
+ public TagRule(IToken token, char escapeCharacter) {
+ super("<", ">", token, escapeCharacter); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ private IToken checkForWhitespace(ICharacterScanner scanner) {
+
+ try {
+
+ char c = getDocument().getChar(getTokenOffset() + 1);
+ if (!Character.isWhitespace(c))
+ return fToken;
+
+ } catch (BadLocationException x) {
+ }
+
+ return Token.UNDEFINED;
+ }
+
+ /*
+ * @see PatternRule#evaluate(ICharacterScanner)
+ */
+ public IToken evaluate(ICharacterScanner scanner) {
+ IToken result = super.evaluate(scanner);
+ if (result == fToken)
+ return checkForWhitespace(scanner);
+ return result;
+ }
+ };
+
+ private static String[] fgKeywords = {"@author", "@deprecated", "@exception", "@link", "@param", "@return", "@see", "@since", "@throws", "@value", "@version", "@license", "@abstract", "@access", "@category",
+ "@copyright", "@example", "@final", "@filesource", "@global", "@ignore", "@internal", "@link", "@method", "@name", "@package", "@param", "@property", "@static",
+ "@staticvar", "@subpackage", "@todo", "@tutorial", "@uses", "@var","@id", "inheritdoc", "@property-read", "@property-write", "@source" }; //$NON-NLS-12$ //$NON-NLS-11$ //$NON-NLS-10$ //$NON-NLS-7$ //$NON-NLS-9$ //$NON-NLS-8$ //$NON-NLS-6$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+
+ private static String[] fgTokenProperties = {
+ IPreferenceConstants.PHPDOC_KEYWORD,
+ IPreferenceConstants.PHPDOC_TAG, IPreferenceConstants.PHPDOC_LINK,
+ IPreferenceConstants.PHPDOC_DEFAULT };
+
+ public PHPDocCodeScanner(IColorManager manager, IPreferenceStore store) {
+ super(manager, store);
+ initialize();
+ }
+
+ public IDocument getDocument() {
+ return fDocument;
+ }
+
+ /*
+ * @see AbstractJavaScanner#getTokenProperties()
+ */
+ protected String[] getTokenProperties() {
+ return fgTokenProperties;
+ }
+
+ /*
+ * @see AbstractJavaScanner#createRules()
+ */
+ protected List createRules() {
+
+ List list = new ArrayList();
+
+ // Add rule for tags.
+ Token token = getToken(IPreferenceConstants.PHPDOC_TAG);
+ list.add(new TagRule(token));
+
+ // Add rule for HTML comments
+ WordRule wordRule = new WordRule(new HTMLCommentDetector(), token);
+ wordRule.addWord("", token); //$NON-NLS-1$
+ list.add(wordRule);
+
+ // Add rule for links.
+ token = getToken(IPreferenceConstants.PHPDOC_LINK);
+ list.add(new SingleLineRule("{@link", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
+
+ // Add generic whitespace rule.
+ list.add(new WhitespaceRule(new PHPWhitespaceDetector()));
+
+ // Add word rule for keywords.
+ token = getToken(IPreferenceConstants.PHPDOC_DEFAULT);
+ wordRule = new WordRule(new JavaDocKeywordDetector(), token);
+
+ token = getToken(IPreferenceConstants.PHPDOC_KEYWORD);
+ for (int i = 0; i < fgKeywords.length; i++)
+ wordRule.addWord(fgKeywords[i], token);
+ list.add(wordRule);
+
+ setDefaultReturnToken(getToken(IPreferenceConstants.PHPDOC_DEFAULT));
+ return list;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/PHPDocCompletionProcessor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/PHPDocCompletionProcessor.java
new file mode 100644
index 0000000..8053a3a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/phpdoc/PHPDocCompletionProcessor.java
@@ -0,0 +1,209 @@
+package net.sourceforge.phpdt.internal.ui.text.phpdoc;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpdt.internal.ui.text.java.PHPCompletionProposalComparator;
+import net.sourceforge.phpdt.internal.ui.text.template.contentassist.TemplateEngine;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+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.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.ui.IEditorPart;
+
+/**
+ * Simple PHPDoc completion processor.
+ */
+public class PHPDocCompletionProcessor implements IContentAssistProcessor {
+
+ private static class PHPDocCompletionProposalComparator implements
+ Comparator {
+ public int compare(Object o1, Object o2) {
+ ICompletionProposal c1 = (ICompletionProposal) o1;
+ ICompletionProposal c2 = (ICompletionProposal) o2;
+ return c1.getDisplayString().compareTo(c2.getDisplayString());
+ }
+ };
+
+ // private IEditorPart fEditor;
+ // private IWorkingCopyManager fManager;
+ private char[] fProposalAutoActivationSet;
+
+ private PHPCompletionProposalComparator fComparator;
+
+ private TemplateEngine fTemplateEngine;
+
+ private boolean fRestrictToMatchingCase;
+
+ private IEditorPart fEditor;
+
+ protected IWorkingCopyManager fManager;
+
+ public PHPDocCompletionProcessor(IEditorPart editor) {
+ fEditor = editor;
+ fManager = WebUI.getDefault().getWorkingCopyManager();
+
+ // fEditor= editor;
+ // fManager= JavaPlugin.getDefault().getWorkingCopyManager();
+ TemplateContextType contextType = WebUI.getDefault()
+ .getTemplateContextRegistry().getContextType("phpdoc"); //$NON-NLS-1$
+ if (contextType != null)
+ fTemplateEngine = new TemplateEngine(contextType);
+ fRestrictToMatchingCase = false;
+
+ fComparator = new PHPCompletionProposalComparator();
+ }
+
+ /**
+ * Tells this processor to order the proposals alphabetically.
+ *
+ * @param order
+ * true
if proposals should be ordered.
+ */
+ public void orderProposalsAlphabetically(boolean order) {
+ fComparator.setOrderAlphabetically(order);
+ }
+
+ /**
+ * Tells this processor to restrict is proposals to those starting with
+ * matching cases.
+ *
+ * @param restrict
+ * true
if proposals should be restricted
+ */
+ public void restrictProposalsToMatchingCases(boolean restrict) {
+ fRestrictToMatchingCase = restrict;
+ }
+
+ /**
+ * @see IContentAssistProcessor#getErrorMessage()
+ */
+ public String getErrorMessage() {
+ return null;
+ }
+
+ /**
+ * @see IContentAssistProcessor#getContextInformationValidator()
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ return null;
+ }
+
+ /**
+ * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters()
+ */
+ public char[] getContextInformationAutoActivationCharacters() {
+ return null;
+ }
+
+ /**
+ * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
+ */
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return fProposalAutoActivationSet;
+ }
+
+ /**
+ * Sets this processor's set of characters triggering the activation of the
+ * completion proposal computation.
+ *
+ * @param activationSet
+ * the activation set
+ */
+ public void setCompletionProposalAutoActivationCharacters(
+ char[] activationSet) {
+ fProposalAutoActivationSet = activationSet;
+ }
+
+ /**
+ * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
+ */
+ public IContextInformation[] computeContextInformation(ITextViewer viewer,
+ int offset) {
+ return null;
+ }
+
+ /**
+ * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)
+ */
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
+ int documentOffset) {
+ ICompilationUnit unit = fManager.getWorkingCopy(fEditor
+ .getEditorInput());
+ IDocument document = viewer.getDocument();
+
+ IPHPCompletionProposal[] results = new IPHPCompletionProposal[0];
+
+ // try {
+ // if (unit != null) {
+ //
+ // int offset= documentOffset;
+ // int length= 0;
+ //
+ // Point selection= viewer.getSelectedRange();
+ // if (selection.y > 0) {
+ // offset= selection.x;
+ // length= selection.y;
+ // }
+ //
+ // JavaDocCompletionEvaluator evaluator= new
+ // JavaDocCompletionEvaluator(unit, document, offset, length);
+ // evaluator.restrictProposalsToMatchingCases(fRestrictToMatchingCase);
+ // results= evaluator.computeProposals();
+ // }
+ // } catch (JavaModelException e) {
+ // JavaPlugin.log(e);
+ // }
+
+ if (fTemplateEngine != null) {
+ // try {
+ fTemplateEngine.reset();
+ fTemplateEngine.complete(viewer, documentOffset, unit);
+ // } catch (JavaModelException x) {
+ // }
+
+ IPHPCompletionProposal[] templateResults = fTemplateEngine
+ .getResults();
+ if (results.length == 0) {
+ results = templateResults;
+ } else {
+ // concatenate arrays
+ IPHPCompletionProposal[] total = new IPHPCompletionProposal[results.length
+ + templateResults.length];
+ System.arraycopy(templateResults, 0, total, 0,
+ templateResults.length);
+ System.arraycopy(results, 0, total, templateResults.length,
+ results.length);
+ results = total;
+ }
+ }
+
+ /*
+ * Order here and not in result collector to make sure that the order
+ * applies to all proposals and not just those of the compilation unit.
+ */
+ return order(results);
+ }
+
+ /**
+ * Order the given proposals.
+ */
+ private IPHPCompletionProposal[] order(IPHPCompletionProposal[] proposals) {
+ Arrays.sort(proposals, fComparator);
+ return proposals;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/AddWordProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/AddWordProposal.java
new file mode 100644
index 0000000..b19a9eb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/AddWordProposal.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.text.MessageFormat;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.java.IInvocationContext;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Proposal to add the unknown word to the dictionaries.
+ *
+ * @since 3.0
+ */
+public class AddWordProposal implements IPHPCompletionProposal {
+
+ /** The invocation context */
+ private final IInvocationContext fContext;
+
+ /** The word to add */
+ private final String fWord;
+
+ /**
+ * Creates a new add word proposal
+ *
+ * @param word
+ * The word to add
+ * @param context
+ * The invocation context
+ */
+ public AddWordProposal(final String word, final IInvocationContext context) {
+ fContext = context;
+ fWord = word;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+ */
+ public final void apply(final IDocument document) {
+
+ final ISpellCheckEngine engine = SpellCheckEngine.getInstance();
+ final ISpellChecker checker = engine.createSpellChecker(engine
+ .getLocale(), PreferenceConstants.getPreferenceStore());
+
+ if (checker != null)
+ checker.addWord(fWord);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return MessageFormat
+ .format(
+ PHPUIMessages.getString("Spelling.add.info"), new String[] { WordCorrectionProposal.getHtmlRepresentation(fWord) }); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+ */
+ public final IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return MessageFormat.format(PHPUIMessages
+ .getString("Spelling.add.label"), new String[] { fWord }); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return PHPUiImages.get(PHPUiImages.IMG_CORRECTION_ADD);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.java.IJavaCompletionProposal#getRelevance()
+ */
+ public int getRelevance() {
+ return Integer.MIN_VALUE;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+ */
+ public final Point getSelection(final IDocument document) {
+ return new Point(fContext.getSelectionOffset(), fContext
+ .getSelectionLength());
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/ChangeCaseProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/ChangeCaseProposal.java
new file mode 100644
index 0000000..57fde9b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/ChangeCaseProposal.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.util.Locale;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.text.java.IInvocationContext;
+
+/**
+ * Proposal to change the letter case of a word.
+ *
+ * @since 3.0
+ */
+public class ChangeCaseProposal extends WordCorrectionProposal {
+
+ /**
+ * Creates a new change case proposal.
+ *
+ * @param arguments
+ * The problem arguments associated with the spelling problem
+ * @param offset
+ * The offset in the document where to apply the proposal
+ * @param length
+ * The lenght in the document to apply the proposal
+ * @param context
+ * The invocation context for this proposal
+ * @param locale
+ * The locale to use for the case change
+ */
+ public ChangeCaseProposal(final String[] arguments, final int offset,
+ final int length, final IInvocationContext context,
+ final Locale locale) {
+ super(Character.isLowerCase(arguments[0].charAt(0)) ? Character
+ .toUpperCase(arguments[0].charAt(0))
+ + arguments[0].substring(1) : arguments[0], arguments, offset,
+ length, context, Integer.MAX_VALUE);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return PHPUIMessages.getString("Spelling.case.label"); //$NON-NLS-1$
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/HtmlTagDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/HtmlTagDictionary.java
new file mode 100644
index 0000000..617f537
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/HtmlTagDictionary.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.net.URL;
+
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.IHtmlTagConstants;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary;
+
+/**
+ * Dictionary for html tags.
+ *
+ * @since 3.0
+ */
+public class HtmlTagDictionary extends AbstractSpellDictionary implements
+ IHtmlTagConstants {
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName()
+ */
+ protected final URL getURL() {
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String)
+ */
+ public boolean isCorrect(final String word) {
+
+ if (word.charAt(0) == HTML_TAG_PREFIX)
+ return super.isCorrect(word);
+
+ return false;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL)
+ */
+ protected boolean load(final URL url) {
+
+ unload();
+
+ for (int index = 0; index < HTML_GENERAL_TAGS.length; index++) {
+
+ hashWord(HTML_TAG_PREFIX + HTML_GENERAL_TAGS[index]
+ + HTML_TAG_POSTFIX);
+ hashWord(HTML_CLOSE_PREFIX + HTML_GENERAL_TAGS[index]
+ + HTML_TAG_POSTFIX);
+ }
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/JavaDocTagDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/JavaDocTagDictionary.java
new file mode 100644
index 0000000..94ed16b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/JavaDocTagDictionary.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.net.URL;
+
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.IJavaDocTagConstants;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary;
+
+/**
+ * Dictionary for Javadoc tags.
+ *
+ * @since 3.0
+ */
+public class JavaDocTagDictionary extends AbstractSpellDictionary implements
+ IJavaDocTagConstants {
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName()
+ */
+ protected final URL getURL() {
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String)
+ */
+ public boolean isCorrect(final String word) {
+
+ if (word.charAt(0) == JAVADOC_TAG_PREFIX)
+ return super.isCorrect(word);
+
+ return false;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL)
+ */
+ protected boolean load(final URL url) {
+
+ unload();
+
+ for (int index = 0; index < JAVADOC_LINK_TAGS.length; index++)
+ hashWord(JAVADOC_LINK_TAGS[index]);
+
+ for (int index = 0; index < JAVADOC_ROOT_TAGS.length; index++)
+ hashWord(JAVADOC_ROOT_TAGS[index]);
+
+ for (int index = 0; index < JAVADOC_PARAM_TAGS.length; index++)
+ hashWord(JAVADOC_PARAM_TAGS[index]);
+
+ return true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellCheckEngine.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellCheckEngine.java
new file mode 100644
index 0000000..0b1f05f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellCheckEngine.java
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.DefaultSpellChecker;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.PersistentSpellDictionary;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * Spell check engine for Java source spell checking.
+ *
+ * @since 3.0
+ */
+public class SpellCheckEngine implements ISpellCheckEngine,
+ IPropertyChangeListener {
+
+ /** The dictionary location */
+ public static final String DICTIONARY_LOCATION = "dictionaries/"; //$NON-NLS-1$
+
+ /** The singleton spell checker instance */
+ private static ISpellChecker fChecker = null;
+
+ /** The singleton engine instance */
+ private static ISpellCheckEngine fEngine = null;
+
+ /**
+ * Returns the available locales for this spell check engine.
+ *
+ * @return The available locales for this engine
+ */
+ public static Set getAvailableLocales() {
+
+ URL url = null;
+ Locale locale = null;
+ InputStream stream = null;
+
+ final Set result = new HashSet();
+ try {
+
+ final URL location = getDictionaryLocation();
+ final Locale[] locales = Locale.getAvailableLocales();
+
+ for (int index = 0; index < locales.length; index++) {
+
+ locale = locales[index];
+ url = new URL(
+ location,
+ locale.toString().toLowerCase()
+ + "." + PHPUIMessages.getString("Spelling.dictionary.file.extension")); //$NON-NLS-1$ //$NON-NLS-2$
+
+ try {
+ stream = url.openStream();
+ if (stream != null) {
+ try {
+ result.add(locale);
+ } finally {
+ stream.close();
+ }
+ }
+ } catch (IOException exception) {
+ // Do nothing
+ }
+ }
+ } catch (MalformedURLException exception) {
+ // Do nothing
+ }
+ result.add(getDefaultLocale());
+
+ return result;
+ }
+
+ /**
+ * Returns the default locale for this engine.
+ *
+ * @return The default locale
+ */
+ public static Locale getDefaultLocale() {
+ return Locale.US;
+ }
+
+ /**
+ * Returns the dictionary location.
+ *
+ * @throws MalformedURLException
+ * if the URL could not be created
+ * @return The dictionary location, or null
iff the location
+ * is not known
+ */
+ public static URL getDictionaryLocation() throws MalformedURLException {
+
+ final WebUI plugin = WebUI.getDefault();
+ if (plugin != null)
+ return plugin.getBundle().getEntry("/" + DICTIONARY_LOCATION); //$NON-NLS-1$
+
+ return null;
+ }
+
+ /**
+ * Returns the singleton instance of the spell check engine.
+ *
+ * @return The singleton instance of the spell check engine
+ */
+ public static final synchronized ISpellCheckEngine getInstance() {
+
+ if (fEngine == null)
+ fEngine = new SpellCheckEngine();
+
+ return fEngine;
+ }
+
+ /** The registered locale insenitive dictionaries */
+ private final Set fGlobalDictionaries = new HashSet();
+
+ /** The current locale */
+ private Locale fLocale = null;
+
+ /** The registered locale sensitive dictionaries */
+ private final Map fLocaleDictionaries = new HashMap();
+
+ /** The preference store where to listen */
+ private IPreferenceStore fPreferences = null;
+
+ /** The user dictionary */
+ private ISpellDictionary fUserDictionary = null;
+
+ /**
+ * Creates a new spell check manager.
+ */
+ private SpellCheckEngine() {
+
+ fGlobalDictionaries.add(new TaskTagDictionary());
+ fGlobalDictionaries.add(new HtmlTagDictionary());
+ fGlobalDictionaries.add(new JavaDocTagDictionary());
+
+ try {
+
+ Locale locale = null;
+ final URL location = getDictionaryLocation();
+
+ for (final Iterator iterator = getAvailableLocales().iterator(); iterator
+ .hasNext();) {
+
+ locale = (Locale) iterator.next();
+ fLocaleDictionaries.put(locale, new SpellReconcileDictionary(
+ locale, location));
+ }
+
+ } catch (MalformedURLException exception) {
+ // Do nothing
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#createSpellChecker(java.util.Locale,org.eclipse.jface.preference.IPreferenceStore)
+ */
+ public final synchronized ISpellChecker createSpellChecker(
+ final Locale locale, final IPreferenceStore store) {
+
+ if (fLocale != null && fLocale.equals(locale))
+ return fChecker;
+
+ if (fChecker == null) {
+
+ fChecker = new DefaultSpellChecker(store);
+ store.addPropertyChangeListener(this);
+
+ fPreferences = store;
+
+ ISpellDictionary dictionary = null;
+ for (Iterator iterator = fGlobalDictionaries.iterator(); iterator
+ .hasNext();) {
+
+ dictionary = (ISpellDictionary) iterator.next();
+ fChecker.addDictionary(dictionary);
+ }
+ }
+
+ ISpellDictionary dictionary = null;
+ if (fLocale != null) {
+
+ dictionary = (ISpellDictionary) fLocaleDictionaries.get(fLocale);
+ if (dictionary != null) {
+
+ fChecker.removeDictionary(dictionary);
+ dictionary.unload();
+ }
+ }
+ fLocale = locale;
+
+ dictionary = (ISpellDictionary) fLocaleDictionaries.get(locale);
+ if (dictionary == null) {
+
+ if (!getDefaultLocale().equals(locale)) {
+
+ if (fPreferences != null)
+ fPreferences.removePropertyChangeListener(this);
+
+ fChecker = null;
+ fLocale = null;
+ }
+
+ } else
+ fChecker.addDictionary(dictionary);
+
+ if (fPreferences != null)
+ propertyChange(new PropertyChangeEvent(
+ this,
+ ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY,
+ null,
+ fPreferences
+ .getString(ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY)));
+
+ return fChecker;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#getLocale()
+ */
+ public final Locale getLocale() {
+ return fLocale;
+ }
+
+ /*
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public final void propertyChange(final PropertyChangeEvent event) {
+
+ if (fChecker != null
+ && event.getProperty().equals(
+ ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY)) {
+
+ if (fUserDictionary != null) {
+
+ fChecker.removeDictionary(fUserDictionary);
+ fUserDictionary = null;
+ }
+
+ final String file = (String) event.getNewValue();
+ if (file.length() > 0) {
+
+ try {
+
+ final URL url = new URL("file", null, file); //$NON-NLS-1$
+ InputStream stream = url.openStream();
+ if (stream != null) {
+ try {
+ fUserDictionary = new PersistentSpellDictionary(url);
+ fChecker.addDictionary(fUserDictionary);
+ } finally {
+ stream.close();
+ }
+ }
+ } catch (MalformedURLException exception) {
+ // Do nothing
+ } catch (IOException exception) {
+ // Do nothing
+ }
+ }
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary)
+ */
+ public synchronized final void registerDictionary(
+ final ISpellDictionary dictionary) {
+
+ fGlobalDictionaries.add(dictionary);
+
+ if (fChecker != null)
+ fChecker.addDictionary(dictionary);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(java.util.Locale,net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary)
+ */
+ public synchronized final void registerDictionary(final Locale locale,
+ final ISpellDictionary dictionary) {
+
+ fLocaleDictionaries.put(locale, dictionary);
+
+ if (fChecker != null && fLocale != null && fLocale.equals(locale))
+ fChecker.addDictionary(dictionary);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#unload()
+ */
+ public synchronized final void unload() {
+
+ ISpellDictionary dictionary = null;
+ for (final Iterator iterator = fGlobalDictionaries.iterator(); iterator
+ .hasNext();) {
+
+ dictionary = (ISpellDictionary) iterator.next();
+ dictionary.unload();
+ }
+
+ for (final Iterator iterator = fLocaleDictionaries.values().iterator(); iterator
+ .hasNext();) {
+
+ dictionary = (ISpellDictionary) iterator.next();
+ dictionary.unload();
+ }
+
+ if (fPreferences != null)
+ fPreferences.removePropertyChangeListener(this);
+
+ fUserDictionary = null;
+ fChecker = null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#unregisterDictionary(net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary)
+ */
+ public synchronized final void unregisterDictionary(
+ final ISpellDictionary dictionary) {
+
+ fGlobalDictionaries.remove(dictionary);
+ fLocaleDictionaries.values().remove(dictionary);
+
+ if (fChecker != null)
+ fChecker.removeDictionary(dictionary);
+
+ dictionary.unload();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellCheckIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellCheckIterator.java
new file mode 100644
index 0000000..022cabf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellCheckIterator.java
@@ -0,0 +1,391 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.text.BreakIterator;
+import java.util.LinkedList;
+import java.util.Locale;
+
+import net.sourceforge.phpdt.corext.refactoring.nls.NLSElement;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.IHtmlTagConstants;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.IJavaDocTagConstants;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.DefaultSpellChecker;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckIterator;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextUtilities;
+
+/**
+ * Iterator to spell-check javadoc comment regions.
+ *
+ * @since 3.0
+ */
+public class SpellCheckIterator implements ISpellCheckIterator,
+ IJavaDocTagConstants, IHtmlTagConstants {
+
+ /** The content of the region */
+ private final String fContent;
+
+ /** The line delimiter */
+ private final String fDelimiter;
+
+ /** The last token */
+ private String fLastToken = null;
+
+ /** The next break */
+ private int fNext = 1;
+
+ /** The offset of the region */
+ private final int fOffset;
+
+ /** The predecessor break */
+ private int fPredecessor;
+
+ /** The previous break */
+ private int fPrevious = 0;
+
+ /** The sentence breaks */
+ private final LinkedList fSentenceBreaks = new LinkedList();
+
+ /** Does the current word start a sentence? */
+ private boolean fStartsSentence = false;
+
+ /** The successor break */
+ private int fSuccessor;
+
+ /** The word iterator */
+ private final BreakIterator fWordIterator;
+
+ /**
+ * Creates a new spell check iterator.
+ *
+ * @param document
+ * The document containing the specified partition
+ * @param region
+ * The region to spell-check
+ * @param locale
+ * The locale to use for spell-checking
+ */
+ public SpellCheckIterator(final IDocument document, final IRegion region,
+ final Locale locale) {
+
+ fOffset = region.getOffset();
+ fWordIterator = BreakIterator.getWordInstance(locale);
+ fDelimiter = TextUtilities.getDefaultLineDelimiter(document);
+
+ String content;
+ try {
+
+ content = document.get(region.getOffset(), region.getLength());
+ if (content.startsWith(NLSElement.TAG_PREFIX))
+ content = ""; //$NON-NLS-1$
+
+ } catch (Exception exception) {
+ content = ""; //$NON-NLS-1$
+ }
+ fContent = content;
+
+ fWordIterator.setText(content);
+ fPredecessor = fWordIterator.first();
+ fSuccessor = fWordIterator.next();
+
+ final BreakIterator iterator = BreakIterator
+ .getSentenceInstance(locale);
+ iterator.setText(content);
+
+ int offset = iterator.current();
+ while (offset != BreakIterator.DONE) {
+
+ fSentenceBreaks.add(new Integer(offset));
+ offset = iterator.next();
+ }
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellCheckIterator#getBegin()
+ */
+ public final int getBegin() {
+ return fPrevious + fOffset;
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellCheckIterator#getEnd()
+ */
+ public final int getEnd() {
+ return fNext + fOffset - 1;
+ }
+
+ /*
+ * @see java.util.Iterator#hasNext()
+ */
+ public final boolean hasNext() {
+ return fSuccessor != BreakIterator.DONE;
+ }
+
+ /**
+ * Does the specified token consist of at least one letter and digits only?
+ *
+ * @param begin
+ * The begin index
+ * @param end
+ * The end index
+ * @return true
iff the token consists of digits and at least
+ * one letter only, false
otherwise
+ */
+ protected final boolean isAlphaNumeric(final int begin, final int end) {
+
+ char character = 0;
+
+ boolean letter = false;
+ for (int index = begin; index < end; index++) {
+
+ character = fContent.charAt(index);
+ if (Character.isLetter(character))
+ letter = true;
+
+ if (!Character.isLetterOrDigit(character))
+ return false;
+ }
+ return letter;
+ }
+
+ /**
+ * Was the last token a Javadoc tag tag?
+ *
+ * @param tags
+ * The javadoc tags to check
+ * @return true
iff the last token was a Javadoc tag,
+ * false
otherwise
+ */
+ protected final boolean isJavadocToken(final String[] tags) {
+
+ if (fLastToken != null) {
+
+ for (int index = 0; index < tags.length; index++) {
+
+ if (fLastToken.equals(tags[index]))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Is the current token a single letter token surrounded by non-whitespace
+ * characters?
+ *
+ * @param begin
+ * The begin index
+ * @return true
iff the token is a single letter token,
+ * false
otherwise
+ */
+ protected final boolean isSingleLetter(final int begin) {
+
+ if (begin > 0 && begin < fContent.length() - 1)
+ return Character.isWhitespace(fContent.charAt(begin - 1))
+ && Character.isLetter(fContent.charAt(begin))
+ && Character.isWhitespace(fContent.charAt(begin + 1));
+
+ return false;
+ }
+
+ /**
+ * Does the specified token look like an URL?
+ *
+ * @param begin
+ * The begin index
+ * @return true
iff this token look like an URL,
+ * false
otherwise
+ */
+ protected final boolean isUrlToken(final int begin) {
+
+ for (int index = 0; index < DefaultSpellChecker.URL_PREFIXES.length; index++) {
+
+ if (fContent.startsWith(DefaultSpellChecker.URL_PREFIXES[index],
+ begin))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Does the specified token consist of whitespace only?
+ *
+ * @param begin
+ * The begin index
+ * @param end
+ * The end index
+ * @return true
iff the token consists of whitespace only,
+ * false
otherwise
+ */
+ protected final boolean isWhitespace(final int begin, final int end) {
+
+ for (int index = begin; index < end; index++) {
+
+ if (!Character.isWhitespace(fContent.charAt(index)))
+ return false;
+ }
+ return true;
+ }
+
+ /*
+ * @see java.util.Iterator#next()
+ */
+ public final Object next() {
+
+ String token = nextToken();
+ while (token == null && fSuccessor != BreakIterator.DONE)
+ token = nextToken();
+
+ fLastToken = token;
+
+ return token;
+ }
+
+ /**
+ * Advances the end index to the next word break.
+ */
+ protected final void nextBreak() {
+
+ fNext = fSuccessor;
+ fPredecessor = fSuccessor;
+
+ fSuccessor = fWordIterator.next();
+ }
+
+ /**
+ * Returns the next sentence break.
+ *
+ * @return The next sentence break
+ */
+ protected final int nextSentence() {
+ return ((Integer) fSentenceBreaks.getFirst()).intValue();
+ }
+
+ /**
+ * Determines the next token to be spell-checked.
+ *
+ * @return The next token to be spell-checked, or null
iff
+ * the next token is not a candidate for spell-checking.
+ */
+ protected String nextToken() {
+
+ String token = null;
+
+ fPrevious = fPredecessor;
+ fStartsSentence = false;
+
+ nextBreak();
+
+ boolean update = false;
+ if (fNext - fPrevious > 0) {
+
+ if (fSuccessor != BreakIterator.DONE
+ && fContent.charAt(fPrevious) == JAVADOC_TAG_PREFIX) {
+
+ nextBreak();
+ if (Character.isLetter(fContent.charAt(fPrevious + 1))) {
+ update = true;
+ token = fContent.substring(fPrevious, fNext);
+ } else
+ fPredecessor = fNext;
+
+ } else if (fSuccessor != BreakIterator.DONE
+ && fContent.charAt(fPrevious) == HTML_TAG_PREFIX
+ && (Character.isLetter(fContent.charAt(fNext)) || fContent
+ .charAt(fNext) == '/')) {
+
+ if (fContent.startsWith(HTML_CLOSE_PREFIX, fPrevious))
+ nextBreak();
+
+ nextBreak();
+
+ if (fSuccessor != BreakIterator.DONE
+ && fContent.charAt(fNext) == HTML_TAG_POSTFIX) {
+
+ nextBreak();
+ if (fSuccessor != BreakIterator.DONE) {
+ update = true;
+ token = fContent.substring(fPrevious, fNext);
+ }
+ }
+ } else if (!isWhitespace(fPrevious, fNext)
+ && isAlphaNumeric(fPrevious, fNext)) {
+
+ if (isUrlToken(fPrevious))
+ skipTokens(fPrevious, ' ');
+ else if (isJavadocToken(JAVADOC_PARAM_TAGS))
+ fLastToken = null;
+ else if (isJavadocToken(JAVADOC_REFERENCE_TAGS)) {
+ fLastToken = null;
+ skipTokens(fPrevious, fDelimiter.charAt(0));
+ } else if (fNext - fPrevious > 1 || isSingleLetter(fPrevious))
+ token = fContent.substring(fPrevious, fNext);
+
+ update = true;
+ }
+ }
+
+ if (update && fSentenceBreaks.size() > 0) {
+
+ if (fPrevious >= nextSentence()) {
+
+ while (fSentenceBreaks.size() > 0
+ && fPrevious >= nextSentence())
+ fSentenceBreaks.removeFirst();
+
+ fStartsSentence = (fLastToken == null) || (token != null);
+ }
+ }
+ return token;
+ }
+
+ /*
+ * @see java.util.Iterator#remove()
+ */
+ public final void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Skip the tokens until the stop character is reached.
+ *
+ * @param begin
+ * The begin index
+ * @param stop
+ * The stop character
+ */
+ protected final void skipTokens(final int begin, final char stop) {
+
+ int end = begin;
+
+ while (end < fContent.length() && fContent.charAt(end) != stop)
+ end++;
+
+ if (end < fContent.length()) {
+
+ fNext = end;
+ fPredecessor = fNext;
+
+ fSuccessor = fWordIterator.following(fNext);
+ } else
+ fSuccessor = BreakIterator.DONE;
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellCheckIterator#startsSentence()
+ */
+ public final boolean startsSentence() {
+ return fStartsSentence;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellReconcileDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellReconcileDictionary.java
new file mode 100644
index 0000000..4e3530c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellReconcileDictionary.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.net.URL;
+import java.util.Locale;
+
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.IHtmlTagConstants;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.IJavaDocTagConstants;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.LocaleSensitiveSpellDictionary;
+
+/**
+ * Dictionary used by the spell reconciling strategy.
+ *
+ * @since 3.0
+ */
+public class SpellReconcileDictionary extends LocaleSensitiveSpellDictionary
+ implements IJavaDocTagConstants, IHtmlTagConstants {
+
+ /**
+ * Creates a new locale sensitive spell dictionary.
+ *
+ * @param locale
+ * The locale for this dictionary
+ * @param location
+ * The location of the locale sensitive dictionaries
+ */
+ public SpellReconcileDictionary(final Locale locale, final URL location) {
+ super(locale, location);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String)
+ */
+ public boolean isCorrect(final String word) {
+
+ final char character = word.charAt(0);
+ if (character != JAVADOC_TAG_PREFIX && character != HTML_TAG_PREFIX)
+ return super.isCorrect(word);
+
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellReconcileStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellReconcileStrategy.java
new file mode 100644
index 0000000..9074743
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/SpellReconcileStrategy.java
@@ -0,0 +1,413 @@
+/*****************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *****************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+
+import net.sourceforge.phpdt.core.IProblemRequestor;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEventListener;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Reconcile strategy to spell-check comments.
+ *
+ * @since 3.0
+ */
+public class SpellReconcileStrategy implements IReconcilingStrategy,
+ IReconcilingStrategyExtension, ISpellEventListener {
+
+ /**
+ * Spelling problem to be accepted by problem requestors.
+ */
+ public class SpellProblem implements IProblem {
+
+ /** The id of the problem */
+ public static final int Spelling = 0x80000000;
+
+ /** The end offset of the problem */
+ private int fEnd = 0;
+
+ /** The line number of the problem */
+ private int fLine = 1;
+
+ /** Was the word found in the dictionary? */
+ private boolean fMatch;
+
+ /** Does the word start a new sentence? */
+ private boolean fSentence = false;
+
+ /** The start offset of the problem */
+ private int fStart = 0;
+
+ /** The word which caused the problem */
+ private final String fWord;
+
+ /**
+ * Creates a new spelling problem
+ *
+ * @param word
+ * The word which caused the problem
+ */
+ protected SpellProblem(final String word) {
+ fWord = word;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#getArguments()
+ */
+ public String[] getArguments() {
+
+ String prefix = ""; //$NON-NLS-1$
+ String postfix = ""; //$NON-NLS-1$
+
+ try {
+
+ final IRegion line = fDocument
+ .getLineInformationOfOffset(fStart);
+
+ prefix = fDocument.get(line.getOffset(), fStart
+ - line.getOffset());
+ postfix = fDocument.get(fEnd + 1, line.getOffset()
+ + line.getLength() - fEnd);
+
+ } catch (BadLocationException exception) {
+ // Do nothing
+ }
+ return new String[] {
+ fWord,
+ prefix,
+ postfix,
+ fSentence ? Boolean.toString(true) : Boolean
+ .toString(false),
+ fMatch ? Boolean.toString(true) : Boolean.toString(false) };
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#getID()
+ */
+ public int getID() {
+ return Spelling;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#getMessage()
+ */
+ public String getMessage() {
+
+ if (fSentence && fMatch)
+ return MessageFormat
+ .format(
+ PHPUIMessages
+ .getString("Spelling.error.case.label"), new String[] { fWord }); //$NON-NLS-1$
+
+ return MessageFormat.format(PHPUIMessages
+ .getString("Spelling.error.label"), new String[] { fWord }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#getOriginatingFileName()
+ */
+ public char[] getOriginatingFileName() {
+ return fEditor.getEditorInput().getName().toCharArray();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#getSourceEnd()
+ */
+ public final int getSourceEnd() {
+ return fEnd;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#getSourceLineNumber()
+ */
+ public final int getSourceLineNumber() {
+ return fLine;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#getSourceStart()
+ */
+ public final int getSourceStart() {
+ return fStart;
+ }
+
+ /**
+ * Was the problem word found in the dictionary?
+ *
+ * @return true
iff the word was found,
+ * false
otherwise
+ */
+ public final boolean isDictionaryMatch() {
+ return fMatch;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#isError()
+ */
+ public final boolean isError() {
+ return false;
+ }
+
+ /**
+ * Does the problem word start a new sentence?
+ *
+ * @return true
iff it starts a new sentence,
+ * false
otherwise
+ */
+ public final boolean isSentenceStart() {
+ return fSentence;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#isWarning()
+ */
+ public final boolean isWarning() {
+ return true;
+ }
+
+ /**
+ * Sets whether the problem word was found in the dictionary.
+ *
+ * @param match
+ * true
iff the word was found,
+ * false
otherwise
+ */
+ public final void setDictionaryMatch(final boolean match) {
+ fMatch = match;
+ }
+
+ /**
+ * Sets whether the problem word starts a new sentence.
+ *
+ * @param sentence
+ * true
iff the word starts a new sentence,
+ * false
otherwise.
+ */
+ public final void setSentenceStart(final boolean sentence) {
+ fSentence = sentence;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#setSourceEnd(int)
+ */
+ public final void setSourceEnd(final int end) {
+ fEnd = end;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#setSourceLineNumber(int)
+ */
+ public final void setSourceLineNumber(final int line) {
+ fLine = line;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.core.compiler.IProblem#setSourceStart(int)
+ */
+ public final void setSourceStart(final int start) {
+ fStart = start;
+ }
+ }
+
+ /** The document to operate on */
+ private IDocument fDocument = null;
+
+ /** The text editor to operate on */
+ private final ITextEditor fEditor;
+
+ /** The current locale */
+ private Locale fLocale = SpellCheckEngine.getDefaultLocale();
+
+ /** The partitioning of the document */
+ private final String fPartitioning;
+
+ /** The preference store to use */
+ private final IPreferenceStore fPreferences;
+
+ /** The problem requestor */
+ private IProblemRequestor fRequestor;
+
+ /**
+ * Creates a new comment reconcile strategy.
+ *
+ * @param editor
+ * The text editor to operate on
+ * @param partitioning
+ * The partitioning of the document
+ * @param store
+ * The preference store to get the preferences from
+ */
+ public SpellReconcileStrategy(final ITextEditor editor,
+ final String partitioning, final IPreferenceStore store) {
+ fEditor = editor;
+ fPartitioning = partitioning;
+ fPreferences = store;
+
+ updateProblemRequestor();
+ }
+
+ /**
+ * Returns the current locale of the spell checking preferences.
+ *
+ * @return The current locale of the spell checking preferences
+ */
+ public Locale getLocale() {
+
+ final String locale = fPreferences
+ .getString(ISpellCheckPreferenceKeys.SPELLING_LOCALE);
+ if (locale.equals(fLocale.toString()))
+ return fLocale;
+
+ if (locale.length() >= 5)
+ return new Locale(locale.substring(0, 2), locale.substring(3, 5));
+
+ return SpellCheckEngine.getDefaultLocale();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEventListener#handle(net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent)
+ */
+ public void handle(final ISpellEvent event) {
+
+ if (fRequestor != null) {
+
+ final SpellProblem problem = new SpellProblem(event.getWord());
+
+ problem.setSourceStart(event.getBegin());
+ problem.setSourceEnd(event.getEnd());
+ problem.setSentenceStart(event.isStart());
+ problem.setDictionaryMatch(event.isMatch());
+
+ try {
+ problem.setSourceLineNumber(fDocument.getLineOfOffset(event
+ .getBegin()) + 1);
+ } catch (BadLocationException x) {
+ // Do nothing
+ }
+
+ fRequestor.acceptProblem(problem);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
+ */
+ public void initialReconcile() {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(final DirtyRegion dirtyRegion, final IRegion subRegion) {
+ reconcile(subRegion);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(final IRegion region) {
+
+ if (fPreferences
+ .getBoolean(ISpellCheckPreferenceKeys.SPELLING_CHECK_SPELLING)
+ && fRequestor != null) {
+
+ try {
+
+ fRequestor.beginReporting();
+
+ ITypedRegion partition = null;
+ final ITypedRegion[] partitions = TextUtilities
+ .computePartitioning(fDocument, fPartitioning, 0,
+ fDocument.getLength(), false);
+
+ final Locale locale = getLocale();
+ final ISpellCheckEngine engine = SpellCheckEngine.getInstance();
+
+ final ISpellChecker checker = engine.createSpellChecker(locale,
+ fPreferences);
+ if (checker != null) {
+ try {
+ checker.addListener(this);
+
+ for (int index = 0; index < partitions.length; index++) {
+ partition = partitions[index];
+ if (!partition.getType().equals(
+ IDocument.DEFAULT_CONTENT_TYPE)
+ && !partition
+ .getType()
+ .equals(
+ PHPDocumentPartitioner.PHP_SCRIPT_CODE))
+ checker.execute(new SpellCheckIterator(
+ fDocument, partition, locale));
+ }
+
+ } finally {
+ checker.removeListener(this);
+ }
+ }
+ } catch (BadLocationException exception) {
+ // Do nothing
+ } finally {
+ fRequestor.endReporting();
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
+ */
+ public final void setDocument(final IDocument document) {
+ fDocument = document;
+
+ updateProblemRequestor();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public final void setProgressMonitor(final IProgressMonitor monitor) {
+ // Do nothing
+ }
+
+ /**
+ * Update the problem requestor based on the current editor
+ *
+ * @since 3.0
+ */
+ private void updateProblemRequestor() {
+ final IAnnotationModel model = fEditor.getDocumentProvider()
+ .getAnnotationModel(fEditor.getEditorInput());
+ fRequestor = (model instanceof IProblemRequestor) ? (IProblemRequestor) model
+ : null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/TaskTagDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/TaskTagDictionary.java
new file mode 100644
index 0000000..867690b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/TaskTagDictionary.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.net.URL;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
+import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+
+/**
+ * Dictionary for task tags.
+ *
+ * @since 3.0
+ */
+public class TaskTagDictionary extends AbstractSpellDictionary implements
+ IPropertyChangeListener {
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName()
+ */
+ protected final URL getURL() {
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL)
+ */
+ protected boolean load(final URL url) {
+
+ final Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null) {
+
+ plugin.getPluginPreferences().addPropertyChangeListener(this);
+ return updateTaskTags();
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
+ */
+ public void propertyChange(final PropertyChangeEvent event) {
+
+ if (JavaCore.COMPILER_TASK_TAGS.equals(event.getProperty()))
+ updateTaskTags();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary#unload()
+ */
+ public void unload() {
+
+ final Plugin plugin = JavaCore.getPlugin();
+ if (plugin != null)
+ plugin.getPluginPreferences().removePropertyChangeListener(this);
+
+ super.unload();
+ }
+
+ /**
+ * Handles the compiler task tags property change event.
+ */
+ protected boolean updateTaskTags() {
+
+ final String tags = JavaCore.getOption(JavaCore.COMPILER_TASK_TAGS);
+ if (tags != null) {
+
+ unload();
+
+ final StringTokenizer tokenizer = new StringTokenizer(tags, ","); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens())
+ hashWord(tokenizer.nextToken());
+
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/WordCorrectionProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/WordCorrectionProposal.java
new file mode 100644
index 0000000..60aaeb0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/WordCorrectionProposal.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.text.MessageFormat;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.java.IInvocationContext;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.IHtmlTagConstants;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Proposal to correct the incorrectly spelled word.
+ *
+ * @since 3.0
+ */
+public class WordCorrectionProposal implements IPHPCompletionProposal,
+ IHtmlTagConstants {
+
+ /**
+ * Returns the html representation of the specified string.
+ *
+ * @param string
+ * The string to return the html representation for
+ * @return The html representation for the string
+ */
+ public static String getHtmlRepresentation(final String string) {
+
+ final int length = string.length();
+ final StringBuffer buffer = new StringBuffer(string);
+
+ for (int offset = length - 1; offset >= 0; offset--) {
+
+ for (int index = 0; index < HTML_ENTITY_CHARACTERS.length; index++) {
+
+ if (string.charAt(offset) == HTML_ENTITY_CHARACTERS[index]) {
+
+ buffer.replace(offset, offset + 1, String
+ .valueOf(HTML_ENTITY_CODES[index]));
+ break;
+ }
+ }
+ }
+ return buffer.toString();
+ }
+
+ /** The invocation context */
+ private final IInvocationContext fContext;
+
+ /** The length in the document */
+ private final int fLength;
+
+ /** The line where to apply the correction */
+ private final String fLine;
+
+ /** The offset in the document */
+ private final int fOffset;
+
+ /** The relevance of this proposal */
+ private final int fRelevance;
+
+ /** The word to complete */
+ private final String fWord;
+
+ /**
+ * Creates a new word correction proposal.
+ *
+ * @param word
+ * The corrected word
+ * @param arguments
+ * The problem arguments associated with the spelling problem
+ * @param offset
+ * The offset in the document where to apply the proposal
+ * @param length
+ * The lenght in the document to apply the proposal
+ * @param context
+ * The invocation context for this proposal
+ * @param relevance
+ * The relevance of this proposal
+ */
+ public WordCorrectionProposal(final String word, final String[] arguments,
+ final int offset, final int length,
+ final IInvocationContext context, final int relevance) {
+
+ fWord = Character.isUpperCase(arguments[0].charAt(0)) ? Character
+ .toUpperCase(word.charAt(0))
+ + word.substring(1) : word;
+
+ fOffset = offset;
+ fLength = length;
+ fContext = context;
+ fRelevance = relevance;
+
+ final StringBuffer buffer = new StringBuffer(80);
+
+ buffer.append("...
"); //$NON-NLS-1$
+ buffer.append(getHtmlRepresentation(arguments[1]));
+ buffer.append(""); //$NON-NLS-1$
+ buffer.append(getHtmlRepresentation(fWord));
+ buffer.append(""); //$NON-NLS-1$
+ buffer.append(getHtmlRepresentation(arguments[2]));
+ buffer.append("
..."); //$NON-NLS-1$
+
+ fLine = buffer.toString();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+ */
+ public final void apply(final IDocument document) {
+ try {
+ document.replace(fOffset, fLength, fWord);
+ } catch (BadLocationException exception) {
+ // Do nothing
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return fLine;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+ */
+ public final IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return MessageFormat.format(PHPUIMessages
+ .getString("Spelling.correct.label"), new String[] { fWord }); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return PHPUiImages.get(PHPUiImages.IMG_CORRECTION_RENAME);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.java.IJavaCompletionProposal#getRelevance()
+ */
+ public final int getRelevance() {
+ return fRelevance;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+ */
+ public final Point getSelection(final IDocument document) {
+
+ int offset = fContext.getSelectionOffset();
+ int length = fContext.getSelectionLength();
+
+ final int delta = fWord.length() - fLength;
+ if (offset <= fOffset && offset + length >= fOffset)
+ length += delta;
+ else if (offset > fOffset && offset + length > fOffset + fLength) {
+ offset += delta;
+ length -= delta;
+ } else
+ length += delta;
+
+ return new Point(offset, length);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/WordIgnoreProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/WordIgnoreProposal.java
new file mode 100644
index 0000000..47add64
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/WordIgnoreProposal.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling;
+
+import java.text.MessageFormat;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.java.IInvocationContext;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Proposal to ignore the word during the current editing session.
+ *
+ * @since 3.0
+ */
+public class WordIgnoreProposal implements IPHPCompletionProposal {
+
+ /** The invocation context */
+ private IInvocationContext fContext;
+
+ /** The word to ignore */
+ private String fWord;
+
+ /**
+ * Creates a new spell ignore proposal.
+ *
+ * @param word
+ * The word to ignore
+ * @param context
+ * The invocation context
+ */
+ public WordIgnoreProposal(final String word,
+ final IInvocationContext context) {
+ fWord = word;
+ fContext = context;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+ */
+ public final void apply(final IDocument document) {
+
+ final ISpellCheckEngine engine = SpellCheckEngine.getInstance();
+ final ISpellChecker checker = engine.createSpellChecker(engine
+ .getLocale(), PreferenceConstants.getPreferenceStore());
+
+ if (checker != null)
+ checker.ignoreWord(fWord);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return MessageFormat
+ .format(
+ PHPUIMessages.getString("Spelling.ignore.info"), new String[] { WordCorrectionProposal.getHtmlRepresentation(fWord) }); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+ */
+ public final IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return MessageFormat.format(PHPUIMessages
+ .getString("Spelling.ignore.label"), new String[] { fWord }); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return PHPUiImages.get(PHPUiImages.IMG_OBJS_NLS_NEVER_TRANSLATE);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.java.IJavaCompletionProposal#getRelevance()
+ */
+ public final int getRelevance() {
+ return Integer.MIN_VALUE + 1;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+ */
+ public final Point getSelection(final IDocument document) {
+ return new Point(fContext.getSelectionOffset(), fContext
+ .getSelectionLength());
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/AbstractSpellDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/AbstractSpellDictionary.java
new file mode 100644
index 0000000..8e0bab5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/AbstractSpellDictionary.java
@@ -0,0 +1,445 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Partial implementation of a spell dictionary.
+ *
+ * @since 3.0
+ */
+public abstract class AbstractSpellDictionary implements ISpellDictionary {
+
+ /** The bucket capacity */
+ protected static final int BUCKET_CAPACITY = 4;
+
+ /** The word buffer capacity */
+ protected static final int BUFFER_CAPACITY = 32;
+
+ /** The distance threshold */
+ protected static final int DISTANCE_THRESHOLD = 160;
+
+ /** The hash capacity */
+ protected static final int HASH_CAPACITY = 22 * 1024;
+
+ /** The phonetic distance algorithm */
+ private IPhoneticDistanceAlgorithm fDistanceAlgorithm = new DefaultPhoneticDistanceAlgorithm();
+
+ /** The mapping from phonetic hashes to word lists */
+ private final Map fHashBuckets = new HashMap(HASH_CAPACITY);
+
+ /** The phonetic hash provider */
+ private IPhoneticHashProvider fHashProvider = new DefaultPhoneticHashProvider();
+
+ /** Is the dictionary already loaded? */
+ private boolean fLoaded = false;
+
+ /**
+ * Returns all candidates with the same phonetic hash.
+ *
+ * @param hash
+ * The hash to retrieve the candidates of
+ * @return Array of candidates for the phonetic hash
+ */
+ protected final ArrayList getCandidates(final String hash) {
+
+ ArrayList list = (ArrayList) fHashBuckets.get(hash);
+ if (list == null)
+ list = new ArrayList(0);
+
+ return list;
+ }
+
+ /**
+ * Returns all candidates that have a phonetic hash within a bounded
+ * distance to the specified word.
+ *
+ * @param word
+ * The word to find the nearest matches for
+ * @param sentence
+ * true
iff the proposals start a new sentence,
+ * false
otherwise
+ * @param hashs
+ * Array of close hashes to find the matches
+ * @return Set of ranked words with bounded distance to the specified word
+ */
+ protected final HashSet getCandidates(final String word,
+ final boolean sentence, final ArrayList hashs) {
+
+ int distance = 0;
+ String hash = null;
+
+ String candidate = null;
+ List candidates = null;
+
+ final StringBuffer buffer = new StringBuffer(BUFFER_CAPACITY);
+ final HashSet result = new HashSet(BUCKET_CAPACITY * hashs.size());
+
+ for (int index = 0; index < hashs.size(); index++) {
+
+ hash = (String) hashs.get(index);
+ candidates = getCandidates(hash);
+
+ for (int offset = 0; offset < candidates.size(); offset++) {
+
+ candidate = (String) candidates.get(offset);
+ distance = fDistanceAlgorithm.getDistance(word, candidate);
+
+ if (distance < DISTANCE_THRESHOLD) {
+
+ buffer.setLength(0);
+ buffer.append(candidate);
+
+ if (sentence)
+ buffer.setCharAt(0, Character.toUpperCase(buffer
+ .charAt(0)));
+
+ result.add(new RankedWordProposal(buffer.toString(),
+ -distance));
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns all approximations that have a phonetic hash with smallest
+ * possible distance to the specified word.
+ *
+ * @param word
+ * The word to find the nearest matches for
+ * @param sentence
+ * true
iff the proposals start a new sentence,
+ * false
otherwise
+ * @param result
+ * Set of ranked words with smallest possible distance to the
+ * specified word
+ */
+ protected final void getCandidates(final String word,
+ final boolean sentence, final HashSet result) {
+
+ int distance = 0;
+ int minimum = Integer.MAX_VALUE;
+
+ String candidate = null;
+ StringBuffer buffer = new StringBuffer(BUFFER_CAPACITY);
+
+ final ArrayList candidates = getCandidates(fHashProvider.getHash(word));
+ final ArrayList matches = new ArrayList(candidates.size());
+
+ for (int index = 0; index < candidates.size(); index++) {
+
+ candidate = (String) candidates.get(index);
+ distance = fDistanceAlgorithm.getDistance(word, candidate);
+
+ if (distance <= minimum) {
+
+ buffer.setLength(0);
+ buffer.append(candidate);
+
+ if (sentence)
+ buffer
+ .setCharAt(0, Character.toUpperCase(buffer
+ .charAt(0)));
+
+ matches
+ .add(new RankedWordProposal(buffer.toString(),
+ -distance));
+ minimum = distance;
+ }
+ }
+
+ RankedWordProposal match = null;
+
+ for (int index = 0; index < matches.size(); index++) {
+
+ match = (RankedWordProposal) matches.get(index);
+ if (match.getRank() == minimum)
+ result.add(match);
+ }
+ }
+
+ /**
+ * Returns the used phonetic distance algorithm.
+ *
+ * @return The phonetic distance algorithm
+ */
+ protected final IPhoneticDistanceAlgorithm getDistanceAlgorithm() {
+ return fDistanceAlgorithm;
+ }
+
+ /**
+ * Returns the used phonetic hash provider.
+ *
+ * @return The phonetic hash provider
+ */
+ protected final IPhoneticHashProvider getHashProvider() {
+ return fHashProvider;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary#getProposals(java.lang.String,boolean)
+ */
+ public Set getProposals(final String word, final boolean sentence) {
+
+ try {
+
+ if (!fLoaded)
+ load(getURL());
+
+ } catch (MalformedURLException exception) {
+ // Do nothing
+ }
+
+ final String hash = fHashProvider.getHash(word);
+ final char[] mutators = fHashProvider.getMutators();
+
+ final ArrayList neighborhood = new ArrayList((word.length() + 1)
+ * (mutators.length + 2));
+ neighborhood.add(hash);
+
+ final HashSet candidates = getCandidates(word, sentence, neighborhood);
+ neighborhood.clear();
+
+ char previous = 0;
+ char next = 0;
+
+ char[] characters = word.toCharArray();
+ for (int index = 0; index < word.length() - 1; index++) {
+
+ next = characters[index];
+ previous = characters[index + 1];
+
+ characters[index] = previous;
+ characters[index + 1] = next;
+
+ neighborhood.add(fHashProvider.getHash(new String(characters)));
+
+ characters[index] = next;
+ characters[index + 1] = previous;
+ }
+
+ final String sentinel = word + " "; //$NON-NLS-1$
+
+ characters = sentinel.toCharArray();
+ int offset = characters.length - 1;
+
+ while (true) {
+
+ for (int index = 0; index < mutators.length; index++) {
+
+ characters[offset] = mutators[index];
+ neighborhood.add(fHashProvider.getHash(new String(characters)));
+ }
+
+ if (offset == 0)
+ break;
+
+ characters[offset] = characters[offset - 1];
+ --offset;
+ }
+
+ char mutated = 0;
+ characters = word.toCharArray();
+
+ for (int index = 0; index < word.length(); index++) {
+
+ mutated = characters[index];
+ for (int mutator = 0; mutator < mutators.length; mutator++) {
+
+ characters[index] = mutators[mutator];
+ neighborhood.add(fHashProvider.getHash(new String(characters)));
+ }
+ characters[index] = mutated;
+ }
+
+ characters = word.toCharArray();
+ final char[] deleted = new char[characters.length - 1];
+
+ for (int index = 0; index < deleted.length; index++)
+ deleted[index] = characters[index];
+
+ next = characters[characters.length - 1];
+ offset = deleted.length;
+
+ while (true) {
+
+ neighborhood.add(fHashProvider.getHash(new String(characters)));
+ if (offset == 0)
+ break;
+
+ previous = next;
+ next = deleted[offset - 1];
+
+ deleted[offset - 1] = previous;
+ --offset;
+ }
+
+ neighborhood.remove(hash);
+ final HashSet matches = getCandidates(word, sentence, neighborhood);
+
+ if (matches.size() == 0 && candidates.size() == 0)
+ getCandidates(word, sentence, candidates);
+
+ candidates.addAll(matches);
+
+ return candidates;
+ }
+
+ /**
+ * Returns the URL of the dictionary word list.
+ *
+ * @throws MalformedURLException
+ * if the URL could not be retrieved
+ * @return The URL of the dictionary word list
+ */
+ protected abstract URL getURL() throws MalformedURLException;
+
+ /**
+ * Hashes the word into the dictionary.
+ *
+ * @param word
+ * The word to hash in the dictionary
+ */
+ protected final void hashWord(final String word) {
+
+ final String hash = fHashProvider.getHash(word);
+ ArrayList bucket = (ArrayList) fHashBuckets.get(hash);
+
+ if (bucket == null) {
+
+ bucket = new ArrayList(BUCKET_CAPACITY);
+ fHashBuckets.put(hash, bucket);
+ }
+
+ bucket.add(word);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String)
+ */
+ public boolean isCorrect(final String word) {
+
+ try {
+
+ if (!fLoaded)
+ load(getURL());
+
+ } catch (MalformedURLException exception) {
+ // Do nothing
+ }
+
+ final ArrayList candidates = getCandidates(fHashProvider.getHash(word));
+
+ if (candidates.contains(word)
+ || candidates.contains(word.toLowerCase()))
+ return true;
+
+ return false;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary#isLoaded()
+ */
+ public final synchronized boolean isLoaded() {
+ return fLoaded || fHashBuckets.size() > 0;
+ }
+
+ /**
+ * Loads a dictionary word list from disk.
+ *
+ * @param url
+ * The URL of the word list to load
+ * @return true
iff the word list could be loaded,
+ * false
otherwise
+ */
+ protected synchronized boolean load(final URL url) {
+
+ if (url != null) {
+
+ try {
+
+ final InputStream stream = url.openStream();
+ if (stream != null) {
+
+ String word = null;
+
+ final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(stream));
+ while ((word = reader.readLine()) != null)
+ hashWord(word);
+
+ return fLoaded = true;
+ }
+ } catch (IOException exception) {
+ // Do nothing
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets the phonetic distance algorithm to use.
+ *
+ * @param algorithm
+ * The phonetic distance algorithm
+ */
+ protected final void setDistanceAlgorithm(
+ final IPhoneticDistanceAlgorithm algorithm) {
+ fDistanceAlgorithm = algorithm;
+ }
+
+ /**
+ * Sets the phonetic hash provider to use.
+ *
+ * @param provider
+ * The phonetic hash provider
+ */
+ protected final void setHashProvider(final IPhoneticHashProvider provider) {
+ fHashProvider = provider;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary#unload()
+ */
+ public synchronized void unload() {
+
+ fLoaded = false;
+ fHashBuckets.clear();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary#acceptsWords()
+ */
+ public boolean acceptsWords() {
+ return false;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary#addWord(java.lang.String)
+ */
+ public void addWord(final String word) {
+ // Do nothing
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultPhoneticDistanceAlgorithm.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultPhoneticDistanceAlgorithm.java
new file mode 100644
index 0000000..cb95f37
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultPhoneticDistanceAlgorithm.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+/**
+ * Default phonetic distance algorithm for english words.
+ *
+ * This algorithm implements the Levenshtein text edit distance.
+ *
+ *
+ * @since 3.0
+ */
+public final class DefaultPhoneticDistanceAlgorithm implements
+ IPhoneticDistanceAlgorithm {
+
+ /** The change case cost */
+ public static final int COST_CASE = 10;
+
+ /** The insert character cost */
+ public static final int COST_INSERT = 95;
+
+ /** The remove character cost */
+ public static final int COST_REMOVE = 95;
+
+ /** The substitute characters cost */
+ public static final int COST_SUBSTITUTE = 100;
+
+ /** The swap characters cost */
+ public static final int COST_SWAP = 90;
+
+ /*
+ * @see org.eclipse.spelling.done.IPhoneticDistanceAlgorithm#getDistance(java.lang.String,java.lang.String)
+ */
+ public final int getDistance(final String from, final String to) {
+
+ final char[] first = (" " + from).toCharArray(); //$NON-NLS-1$
+ final char[] second = (" " + to).toCharArray(); //$NON-NLS-1$
+
+ final int rows = first.length;
+ final int columns = second.length;
+
+ final int[][] metric = new int[rows][columns];
+ for (int column = 1; column < columns; column++)
+ metric[0][column] = metric[0][column - 1] + COST_REMOVE;
+
+ for (int row = 1; row < rows; row++)
+ metric[row][0] = metric[row - 1][0] + COST_INSERT;
+
+ char source, target;
+
+ int swap = Integer.MAX_VALUE;
+ int change = Integer.MAX_VALUE;
+
+ int minimum, diagonal, insert, remove;
+ for (int row = 1; row < rows; row++) {
+
+ source = first[row];
+ for (int column = 1; column < columns; column++) {
+
+ target = second[column];
+ diagonal = metric[row - 1][column - 1];
+
+ if (source == target) {
+ metric[row][column] = diagonal;
+ continue;
+ }
+
+ change = Integer.MAX_VALUE;
+ if (Character.toLowerCase(source) == Character
+ .toLowerCase(target))
+ change = COST_CASE + diagonal;
+
+ swap = Integer.MAX_VALUE;
+ if (row != 1 && column != 1 && source == second[column - 1]
+ && first[row - 1] == target)
+ swap = COST_SWAP + metric[row - 2][column - 2];
+
+ minimum = COST_SUBSTITUTE + diagonal;
+ if (swap < minimum)
+ minimum = swap;
+
+ remove = metric[row][column - 1];
+ if (COST_REMOVE + remove < minimum)
+ minimum = COST_REMOVE + remove;
+
+ insert = metric[row - 1][column];
+ if (COST_INSERT + insert < minimum)
+ minimum = COST_INSERT + insert;
+ if (change < minimum)
+ minimum = change;
+
+ metric[row][column] = minimum;
+ }
+ }
+ return metric[rows - 1][columns - 1];
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultPhoneticHashProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultPhoneticHashProvider.java
new file mode 100644
index 0000000..2229bcf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultPhoneticHashProvider.java
@@ -0,0 +1,852 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+/**
+ * Default phonetic hash provider for english languages.
+ *
+ * This algorithm uses an adapted version double metaphone algorithm by Lawrence
+ * Philips.
+ *
+ *
+ * @since 3.0
+ */
+public final class DefaultPhoneticHashProvider implements IPhoneticHashProvider {
+
+ private static final String[] meta01 = { "ACH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta02 = { "BACHER", "MACHER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta03 = { "CAESAR", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta04 = { "CHIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta05 = { "CH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta06 = { "CHAE", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta07 = { "HARAC", "HARIS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta08 = { "HOR", "HYM", "HIA", "HEM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ private static final String[] meta09 = { "CHORE", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta10 = { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta11 = { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta12 = { "ORCHES", "ARCHIT", "ORCHID", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta13 = { "T", "S", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta14 = { "A", "O", "U", "E", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ private static final String[] meta15 = {
+ "L", "R", "N", "M", "B", "H", "F", "V", "W", " ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$
+
+ private static final String[] meta16 = { "MC", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta17 = { "CZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta18 = { "WICZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta19 = { "CIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta20 = { "CC", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta21 = { "I", "E", "H", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta22 = { "HU", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta23 = { "UCCEE", "UCCES", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta24 = { "CK", "CG", "CQ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta25 = { "CI", "CE", "CY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta26 = { "GN", "KN", "PN", "WR", "PS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+
+ private static final String[] meta27 = { " C", " Q", " G", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta28 = { "C", "K", "Q", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta29 = { "CE", "CI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta30 = { "DG", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta31 = { "I", "E", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta32 = { "DT", "DD", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta33 = { "B", "H", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta34 = { "B", "H", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta35 = { "B", "H", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta36 = { "C", "G", "L", "R", "T", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+
+ private static final String[] meta37 = { "EY", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta38 = { "LI", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta39 = {
+ "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$
+
+ private static final String[] meta40 = { "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta41 = { "DANGER", "RANGER", "MANGER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta42 = { "E", "I", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta43 = { "RGY", "OGY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta44 = { "E", "I", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta45 = { "AGGI", "OGGI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta46 = { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta47 = { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta48 = { "ET", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta49 = { "C", "X", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta50 = { "JOSE", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta51 = { "SAN ", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta52 = { "SAN ", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta53 = { "JOSE", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta54 = {
+ "L", "T", "K", "S", "N", "M", "B", "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
+
+ private static final String[] meta55 = { "S", "K", "L", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta56 = { "ILLO", "ILLA", "ALLE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta57 = { "AS", "OS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta58 = { "A", "O", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta59 = { "ALLE", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta60 = { "UMB", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta61 = { "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta62 = { "P", "B", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta63 = { "IE", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta64 = { "ME", "MA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta65 = { "ISL", "YSL", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta66 = { "SUGAR", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta67 = { "SH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta68 = { "HEIM", "HOEK", "HOLM", "HOLZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ private static final String[] meta69 = { "SIO", "SIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta70 = { "SIAN", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta71 = { "M", "N", "L", "W", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ private static final String[] meta72 = { "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta73 = { "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta74 = { "SC", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta75 = {
+ "OO", "ER", "EN", "UY", "ED", "EM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+
+ private static final String[] meta76 = { "ER", "EN", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta77 = { "I", "E", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ private static final String[] meta78 = { "AI", "OI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta79 = { "S", "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta80 = { "TION", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta81 = { "TIA", "TCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta82 = { "TH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta83 = { "TTH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta84 = { "OM", "AM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta85 = { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta86 = { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta87 = { "T", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta88 = { "WR", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta89 = { "WH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta90 = {
+ "EWSKI", "EWSKY", "OWSKI", "OWSKY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ private static final String[] meta91 = { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String[] meta92 = { "WICZ", "WITZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta93 = { "IAU", "EAU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta94 = { "AU", "OU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private static final String[] meta95 = { "W", "K", "CZ", "WITZ" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ /** The mutator characters */
+ private static final char[] MUTATOR_CHARACTERS = { 'A', 'B', 'X', 'S', 'K',
+ 'J', 'T', 'F', 'H', 'L', 'M', 'N', 'P', 'R', '0' };
+
+ /** The vowel characters */
+ private static final char[] VOWEL_CHARACTERS = new char[] { 'A', 'E', 'I',
+ 'O', 'U', 'Y' };
+
+ /**
+ * Test whether the specified string contains one of the candidates in the
+ * list.
+ *
+ * @param candidates
+ * Array of candidates to check
+ * @param token
+ * The token to check for occurrences of the candidates
+ * @param offset
+ * The offset where to begin checking in the string
+ * @param length
+ * The length of the range in the string to check
+ * @return true
iff the string contains one of the
+ * candidates, false
otherwise.
+ */
+ protected static final boolean hasOneOf(final String[] candidates,
+ final char[] token, final int offset, final int length) {
+
+ if (offset < 0 || offset >= token.length || candidates.length == 0)
+ return false;
+
+ final String checkable = new String(token, offset, length);
+ for (int index = 0; index < candidates.length; index++) {
+
+ if (candidates[index].equals(checkable))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Test whether the specified token contains one of the candidates in the
+ * list.
+ *
+ * @param candidates
+ * Array of candidates to check
+ * @param token
+ * The token to check for occurrences of the candidates
+ * @return true
iff the string contains one of the
+ * candidates, false
otherwise.
+ */
+ protected static final boolean hasOneOf(final String[] candidates,
+ final String token) {
+
+ for (int index = 0; index < candidates.length; index++) {
+
+ if (token.indexOf(candidates[index]) >= 0)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Tests whether the specified token contains a vowel at the specified
+ * offset.
+ *
+ * @param token
+ * The token to check for a vowel
+ * @param offset
+ * The offset where to begin checking in the token
+ * @param length
+ * The length of the range in the token to check
+ * @return true
iff the token contains a vowel,
+ * false
otherwise.
+ */
+ protected static final boolean hasVowel(final char[] token,
+ final int offset, final int length) {
+
+ if (offset >= 0 && offset < length) {
+
+ final char character = token[offset];
+ for (int index = 0; index < VOWEL_CHARACTERS.length; index++) {
+
+ if (VOWEL_CHARACTERS[index] == character)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.IPhoneticHasher#getHash(java.lang.String)
+ */
+ public final String getHash(final String word) {
+
+ final String input = word.toUpperCase() + " "; //$NON-NLS-1$
+ final char[] hashable = input.toCharArray();
+
+ final boolean has95 = hasOneOf(meta95, input);
+ final StringBuffer buffer = new StringBuffer(hashable.length);
+
+ int offset = 0;
+ if (hasOneOf(meta26, hashable, 0, 2))
+ offset += 1;
+
+ if (hashable[0] == 'X') {
+ buffer.append('S');
+ offset += 1;
+ }
+
+ while (offset < hashable.length) {
+
+ switch (hashable[offset]) {
+ case 'A':
+ case 'E':
+ case 'I':
+ case 'O':
+ case 'U':
+ case 'Y':
+ if (offset == 0)
+ buffer.append('A');
+ offset += 1;
+ break;
+ case 'B':
+ buffer.append('P');
+ if (hashable[offset + 1] == 'B')
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ case 'C':
+ if ((offset > 1)
+ && !hasVowel(hashable, offset - 2, hashable.length)
+ && hasOneOf(meta01, hashable, (offset - 1), 3)
+ && (hashable[offset + 2] != 'I')
+ && (hashable[offset + 2] != 'E')
+ || hasOneOf(meta02, hashable, (offset - 2), 6)) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ if ((offset == 0) && hasOneOf(meta03, hashable, offset, 6)) {
+ buffer.append('S');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta04, hashable, offset, 4)) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta05, hashable, offset, 2)) {
+ if ((offset > 0) && hasOneOf(meta06, hashable, offset, 4)) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ if ((offset == 0)
+ && hasOneOf(meta07, hashable, (offset + 1), 5)
+ || hasOneOf(meta08, hashable, offset + 1, 3)
+ && !hasOneOf(meta09, hashable, 0, 5)) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta10, hashable, 0, 4)
+ || hasOneOf(meta11, hashable, 0, 3)
+ || hasOneOf(meta12, hashable, offset - 2, 6)
+ || hasOneOf(meta13, hashable, offset + 2, 1)
+ || (hasOneOf(meta14, hashable, offset - 1, 1) || (offset == 0))
+ && hasOneOf(meta15, hashable, offset + 2, 1)) {
+ buffer.append('K');
+ } else {
+ if (offset > 0) {
+ if (hasOneOf(meta16, hashable, 0, 2))
+ buffer.append('K');
+ else
+ buffer.append('X');
+ } else {
+ buffer.append('X');
+ }
+ }
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta17, hashable, offset, 2)
+ && !hasOneOf(meta18, hashable, offset, 4)) {
+ buffer.append('S');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta19, hashable, offset, 2)) {
+ buffer.append('X');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta20, hashable, offset, 2)
+ && !((offset == 1) && hashable[0] == 'M')) {
+ if (hasOneOf(meta21, hashable, offset + 2, 1)
+ && !hasOneOf(meta22, hashable, offset + 2, 2)) {
+ if (((offset == 1) && (hashable[offset - 1] == 'A'))
+ || hasOneOf(meta23, hashable, (offset - 1), 5))
+ buffer.append("KS"); //$NON-NLS-1$
+ else
+ buffer.append('X');
+ offset += 3;
+ break;
+ } else {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ }
+ if (hasOneOf(meta24, hashable, offset, 2)) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ } else if (hasOneOf(meta25, hashable, offset, 2)) {
+ buffer.append('S');
+ offset += 2;
+ break;
+ }
+ buffer.append('K');
+ if (hasOneOf(meta27, hashable, offset + 1, 2))
+ offset += 3;
+ else if (hasOneOf(meta28, hashable, offset + 1, 1)
+ && !hasOneOf(meta29, hashable, offset + 1, 2))
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ case '\u00C7':
+ buffer.append('S');
+ offset += 1;
+ break;
+ case 'D':
+ if (hasOneOf(meta30, hashable, offset, 2)) {
+ if (hasOneOf(meta31, hashable, offset + 2, 1)) {
+ buffer.append('J');
+ offset += 3;
+ break;
+ } else {
+ buffer.append("TK"); //$NON-NLS-1$
+ offset += 2;
+ break;
+ }
+ }
+ buffer.append('T');
+ if (hasOneOf(meta32, hashable, offset, 2)) {
+ offset += 2;
+ } else {
+ offset += 1;
+ }
+ break;
+ case 'F':
+ if (hashable[offset + 1] == 'F')
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('F');
+ break;
+ case 'G':
+ if (hashable[offset + 1] == 'H') {
+ if ((offset > 0)
+ && !hasVowel(hashable, offset - 1, hashable.length)) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ if (offset < 3) {
+ if (offset == 0) {
+ if (hashable[offset + 2] == 'I')
+ buffer.append('J');
+ else
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ }
+ if ((offset > 1)
+ && hasOneOf(meta33, hashable, offset - 2, 1)
+ || ((offset > 2) && hasOneOf(meta34, hashable,
+ offset - 3, 1))
+ || ((offset > 3) && hasOneOf(meta35, hashable,
+ offset - 4, 1))) {
+ offset += 2;
+ break;
+ } else {
+ if ((offset > 2) && (hashable[offset - 1] == 'U')
+ && hasOneOf(meta36, hashable, offset - 3, 1)) {
+ buffer.append('F');
+ } else {
+ if ((offset > 0) && (hashable[offset - 1] != 'I'))
+ buffer.append('K');
+ }
+ offset += 2;
+ break;
+ }
+ }
+ if (hashable[offset + 1] == 'N') {
+ if ((offset == 1) && hasVowel(hashable, 0, hashable.length)
+ && !has95) {
+ buffer.append("KN"); //$NON-NLS-1$
+ } else {
+ if (!hasOneOf(meta37, hashable, offset + 2, 2)
+ && (hashable[offset + 1] != 'Y') && !has95) {
+ buffer.append("N"); //$NON-NLS-1$
+ } else {
+ buffer.append("KN"); //$NON-NLS-1$
+ }
+ }
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta38, hashable, offset + 1, 2) && !has95) {
+ buffer.append("KL"); //$NON-NLS-1$
+ offset += 2;
+ break;
+ }
+ if ((offset == 0)
+ && ((hashable[offset + 1] == 'Y') || hasOneOf(meta39,
+ hashable, offset + 1, 2))) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ if ((hasOneOf(meta40, hashable, offset + 1, 2) || (hashable[offset + 1] == 'Y'))
+ && !hasOneOf(meta41, hashable, 0, 6)
+ && !hasOneOf(meta42, hashable, offset - 1, 1)
+ && !hasOneOf(meta43, hashable, offset - 1, 3)) {
+ buffer.append('K');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta44, hashable, offset + 1, 1)
+ || hasOneOf(meta45, hashable, offset - 1, 4)) {
+ if (hasOneOf(meta46, hashable, 0, 4)
+ || hasOneOf(meta47, hashable, 0, 3)
+ || hasOneOf(meta48, hashable, offset + 1, 2)) {
+ buffer.append('K');
+ } else {
+ buffer.append('J');
+ }
+ offset += 2;
+ break;
+ }
+ if (hashable[offset + 1] == 'G')
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('K');
+ break;
+ case 'H':
+ if (((offset == 0) || hasVowel(hashable, offset - 1,
+ hashable.length))
+ && hasVowel(hashable, offset + 1, hashable.length)) {
+ buffer.append('H');
+ offset += 2;
+ } else {
+ offset += 1;
+ }
+ break;
+ case 'J':
+ if (hasOneOf(meta50, hashable, offset, 4)
+ || hasOneOf(meta51, hashable, 0, 4)) {
+ if ((offset == 0) && (hashable[offset + 4] == ' ')
+ || hasOneOf(meta52, hashable, 0, 4)) {
+ buffer.append('H');
+ } else {
+ buffer.append('J');
+ }
+ offset += 1;
+ break;
+ }
+ if ((offset == 0) && !hasOneOf(meta53, hashable, offset, 4)) {
+ buffer.append('J');
+ } else {
+ if (hasVowel(hashable, offset - 1, hashable.length)
+ && !has95
+ && ((hashable[offset + 1] == 'A') || hashable[offset + 1] == 'O')) {
+ buffer.append('J');
+ } else {
+ if (offset == (hashable.length - 1)) {
+ buffer.append('J');
+ } else {
+ if (!hasOneOf(meta54, hashable, offset + 1, 1)
+ && !hasOneOf(meta55, hashable, offset - 1,
+ 1)) {
+ buffer.append('J');
+ }
+ }
+ }
+ }
+ if (hashable[offset + 1] == 'J')
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ case 'K':
+ if (hashable[offset + 1] == 'K')
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('K');
+ break;
+ case 'L':
+ if (hashable[offset + 1] == 'L') {
+ if (((offset == (hashable.length - 3)) && hasOneOf(meta56,
+ hashable, offset - 1, 4))
+ || ((hasOneOf(meta57, hashable,
+ (hashable.length - 1) - 1, 2) || hasOneOf(
+ meta58, hashable, hashable.length - 1, 1)) && hasOneOf(
+ meta59, hashable, offset - 1, 4))) {
+ buffer.append('L');
+ offset += 2;
+ break;
+ }
+ offset += 2;
+ } else
+ offset += 1;
+ buffer.append('L');
+ break;
+ case 'M':
+ if ((hasOneOf(meta60, hashable, offset - 1, 3) && (((offset + 1) == (hashable.length - 1)) || hasOneOf(
+ meta61, hashable, offset + 2, 2)))
+ || (hashable[offset + 1] == 'M'))
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('M');
+ break;
+ case 'N':
+ if (hashable[offset + 1] == 'N')
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('N');
+ break;
+ case '\u00D1':
+ offset += 1;
+ buffer.append('N');
+ break;
+ case 'P':
+ if (hashable[offset + 1] == 'N') {
+ buffer.append('F');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta62, hashable, offset + 1, 1))
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('P');
+ break;
+ case 'Q':
+ if (hashable[offset + 1] == 'Q')
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('K');
+ break;
+ case 'R':
+ if (!((offset == (hashable.length - 1)) && !has95
+ && hasOneOf(meta63, hashable, offset - 2, 2) && !hasOneOf(
+ meta64, hashable, offset - 4, 2)))
+ buffer.append('R');
+ if (hashable[offset + 1] == 'R')
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ case 'S':
+ if (hasOneOf(meta65, hashable, offset - 1, 3)) {
+ offset += 1;
+ break;
+ }
+ if ((offset == 0) && hasOneOf(meta66, hashable, offset, 5)) {
+ buffer.append('X');
+ offset += 1;
+ break;
+ }
+ if (hasOneOf(meta67, hashable, offset, 2)) {
+ if (hasOneOf(meta68, hashable, offset + 1, 4))
+ buffer.append('S');
+ else
+ buffer.append('X');
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta69, hashable, offset, 3)
+ || hasOneOf(meta70, hashable, offset, 4)) {
+ buffer.append('S');
+ offset += 3;
+ break;
+ }
+ if (((offset == 0) && hasOneOf(meta71, hashable, offset + 1, 1))
+ || hasOneOf(meta72, hashable, offset + 1, 1)) {
+ buffer.append('S');
+ if (hasOneOf(meta73, hashable, offset + 1, 1))
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ }
+ if (hasOneOf(meta74, hashable, offset, 2)) {
+ if (hashable[offset + 2] == 'H')
+ if (hasOneOf(meta75, hashable, offset + 3, 2)) {
+ if (hasOneOf(meta76, hashable, offset + 3, 2)) {
+ buffer.append("X"); //$NON-NLS-1$
+ } else {
+ buffer.append("SK"); //$NON-NLS-1$
+ }
+ offset += 3;
+ break;
+ } else {
+ buffer.append('X');
+ offset += 3;
+ break;
+ }
+ if (hasOneOf(meta77, hashable, offset + 2, 1)) {
+ buffer.append('S');
+ offset += 3;
+ break;
+ }
+ buffer.append("SK"); //$NON-NLS-1$
+ offset += 3;
+ break;
+ }
+ if (!((offset == (hashable.length - 1)) && hasOneOf(meta78,
+ hashable, offset - 2, 2)))
+ buffer.append('S');
+ if (hasOneOf(meta79, hashable, offset + 1, 1))
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ case 'T':
+ if (hasOneOf(meta80, hashable, offset, 4)) {
+ buffer.append('X');
+ offset += 3;
+ break;
+ }
+ if (hasOneOf(meta81, hashable, offset, 3)) {
+ buffer.append('X');
+ offset += 3;
+ break;
+ }
+ if (hasOneOf(meta82, hashable, offset, 2)
+ || hasOneOf(meta83, hashable, offset, 3)) {
+ if (hasOneOf(meta84, hashable, (offset + 2), 2)
+ || hasOneOf(meta85, hashable, 0, 4)
+ || hasOneOf(meta86, hashable, 0, 3)) {
+ buffer.append('T');
+ } else {
+ buffer.append('0');
+ }
+ offset += 2;
+ break;
+ }
+ if (hasOneOf(meta87, hashable, offset + 1, 1)) {
+ offset += 2;
+ } else
+ offset += 1;
+ buffer.append('T');
+ break;
+ case 'V':
+ if (hashable[offset + 1] == 'V')
+ offset += 2;
+ else
+ offset += 1;
+ buffer.append('F');
+ break;
+ case 'W':
+ if (hasOneOf(meta88, hashable, offset, 2)) {
+ buffer.append('R');
+ offset += 2;
+ break;
+ }
+ if ((offset == 0)
+ && (hasVowel(hashable, offset + 1, hashable.length) || hasOneOf(
+ meta89, hashable, offset, 2))) {
+ buffer.append('A');
+ }
+ if (((offset == (hashable.length - 1)) && hasVowel(hashable,
+ offset - 1, hashable.length))
+ || hasOneOf(meta90, hashable, offset - 1, 5)
+ || hasOneOf(meta91, hashable, 0, 3)) {
+ buffer.append('F');
+ offset += 1;
+ break;
+ }
+ if (hasOneOf(meta92, hashable, offset, 4)) {
+ buffer.append("TS"); //$NON-NLS-1$
+ offset += 4;
+ break;
+ }
+ offset += 1;
+ break;
+ case 'X':
+ if (!((offset == (hashable.length - 1)) && (hasOneOf(meta93,
+ hashable, offset - 3, 3) || hasOneOf(meta94, hashable,
+ offset - 2, 2))))
+ buffer.append("KS"); //$NON-NLS-1$
+ if (hasOneOf(meta49, hashable, offset + 1, 1))
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ case 'Z':
+ if (hashable[offset + 1] == 'H') {
+ buffer.append('J');
+ offset += 2;
+ break;
+ } else {
+ buffer.append('S');
+ }
+ if (hashable[offset + 1] == 'Z')
+ offset += 2;
+ else
+ offset += 1;
+ break;
+ default:
+ offset += 1;
+ }
+ }
+ return buffer.toString();
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.IPhoneticHasher#getMutators()
+ */
+ public final char[] getMutators() {
+ return MUTATOR_CHARACTERS;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultSpellChecker.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultSpellChecker.java
new file mode 100644
index 0000000..2b4da35
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/DefaultSpellChecker.java
@@ -0,0 +1,366 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Default spell checker for standard text.
+ *
+ * @since 3.0
+ */
+public class DefaultSpellChecker implements ISpellChecker {
+
+ /** Array of url prefixes */
+ public static final String[] URL_PREFIXES = new String[] {
+ "http://", "https://", "www.", "ftp://", "ftps://", "news://", "mailto://" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+
+ /**
+ * Does this word contain digits?
+ *
+ * @param word
+ * The word to check
+ * @return true
iff this word contains digits,
+ * false>
otherwise
+ */
+ protected static boolean isDigits(final String word) {
+
+ for (int index = 0; index < word.length(); index++) {
+
+ if (Character.isDigit(word.charAt(index)))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Does this word contain mixed-case letters?
+ *
+ * @param word
+ * The word to check
+ * @param sentence
+ * true
iff the specified word starts a new
+ * sentence, false
otherwise
+ * @return true
iff the contains mixed-case letters,
+ * false
otherwise
+ */
+ protected static boolean isMixedCase(final String word,
+ final boolean sentence) {
+
+ final int length = word.length();
+ boolean upper = Character.isUpperCase(word.charAt(0));
+
+ if (sentence && upper && (length > 1))
+ upper = Character.isUpperCase(word.charAt(1));
+
+ if (upper) {
+
+ for (int index = length - 1; index > 0; index--) {
+ if (Character.isLowerCase(word.charAt(index)))
+ return true;
+ }
+ } else {
+
+ for (int index = length - 1; index > 0; index--) {
+ if (Character.isUpperCase(word.charAt(index)))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Does this word contain upper-case letters only?
+ *
+ * @param word
+ * The word to check
+ * @return true
iff this word only contains upper-case
+ * letters, false
otherwise
+ */
+ protected static boolean isUpperCase(final String word) {
+
+ for (int index = word.length() - 1; index >= 0; index--) {
+
+ if (Character.isLowerCase(word.charAt(index)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Does this word look like an URL?
+ *
+ * @param word
+ * The word to check
+ * @return true
iff this word looks like an URL,
+ * false
otherwise
+ */
+ protected static boolean isUrl(final String word) {
+
+ for (int index = 0; index < URL_PREFIXES.length; index++) {
+
+ if (word.startsWith(URL_PREFIXES[index]))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * The dictionaries to use for spell-checking. Synchronized to avoid
+ * concurrent modifications.
+ */
+ private final Set fDictionaries = Collections
+ .synchronizedSet(new HashSet());
+
+ /**
+ * The words to be ignored. Synchronized to avoid concurrent modifications.
+ */
+ private final Set fIgnored = Collections.synchronizedSet(new HashSet());
+
+ /**
+ * The spell event listeners. Synchronized to avoid concurrent
+ * modifications.
+ */
+ private final Set fListeners = Collections.synchronizedSet(new HashSet());
+
+ /**
+ * The preference store. Assumes the IPreferenceStore
+ * implementation is thread safe.
+ */
+ private final IPreferenceStore fPreferences;
+
+ /**
+ * Creates a new default spell-checker.
+ *
+ * @param store
+ * The preference store for this spell-checker
+ */
+ public DefaultSpellChecker(final IPreferenceStore store) {
+ fPreferences = store;
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellChecker#addDictionary(org.eclipse.spelling.done.ISpellDictionary)
+ */
+ public final void addDictionary(final ISpellDictionary dictionary) {
+ // synchronizing is necessary as this is a write access
+ fDictionaries.add(dictionary);
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellChecker#addListener(org.eclipse.spelling.done.ISpellEventListener)
+ */
+ public final void addListener(final ISpellEventListener listener) {
+ // synchronizing is necessary as this is a write access
+ fListeners.add(listener);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellChecker#acceptsWords()
+ */
+ public boolean acceptsWords() {
+ // synchronizing might not be needed here since acceptWords is
+ // a read-only access and only called in the same thread as
+ // the modifing methods add/checkWord (?)
+ Set copy;
+ synchronized (fDictionaries) {
+ copy = new HashSet(fDictionaries);
+ }
+
+ ISpellDictionary dictionary = null;
+ for (final Iterator iterator = copy.iterator(); iterator.hasNext();) {
+
+ dictionary = (ISpellDictionary) iterator.next();
+ if (dictionary.acceptsWords())
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker#addWord(java.lang.String)
+ */
+ public void addWord(final String word) {
+ // synchronizing is necessary as this is a write access
+ Set copy;
+ synchronized (fDictionaries) {
+ copy = new HashSet(fDictionaries);
+ }
+
+ final String addable = word.toLowerCase();
+ fIgnored.add(addable);
+
+ ISpellDictionary dictionary = null;
+ for (final Iterator iterator = copy.iterator(); iterator.hasNext();) {
+
+ dictionary = (ISpellDictionary) iterator.next();
+ dictionary.addWord(addable);
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellChecker#checkWord(java.lang.String)
+ */
+ public final void checkWord(final String word) {
+ // synchronizing is necessary as this is a write access
+ fIgnored.remove(word.toLowerCase());
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellChecker#execute(org.eclipse.spelling.ISpellCheckTokenizer)
+ */
+ public void execute(final ISpellCheckIterator iterator) {
+
+ final boolean ignoreDigits = fPreferences
+ .getBoolean(ISpellCheckPreferenceKeys.SPELLING_IGNORE_DIGITS);
+ final boolean ignoreMixed = fPreferences
+ .getBoolean(ISpellCheckPreferenceKeys.SPELLING_IGNORE_MIXED);
+ final boolean ignoreSentence = fPreferences
+ .getBoolean(ISpellCheckPreferenceKeys.SPELLING_IGNORE_SENTENCE);
+ final boolean ignoreUpper = fPreferences
+ .getBoolean(ISpellCheckPreferenceKeys.SPELLING_IGNORE_UPPER);
+ final boolean ignoreURLS = fPreferences
+ .getBoolean(ISpellCheckPreferenceKeys.SPELLING_IGNORE_URLS);
+
+ String word = null;
+ boolean starts = false;
+
+ while (iterator.hasNext()) {
+
+ word = (String) iterator.next();
+ if (word != null) {
+
+ // synchronizing is necessary as this is called inside the
+ // reconciler
+ if (!fIgnored.contains(word)) {
+
+ starts = iterator.startsSentence();
+ if (!isCorrect(word)) {
+
+ boolean isMixed = isMixedCase(word, true);
+ boolean isUpper = isUpperCase(word);
+ boolean isDigits = isDigits(word);
+ boolean isURL = isUrl(word);
+
+ if (!ignoreMixed && isMixed || !ignoreUpper && isUpper
+ || !ignoreDigits && isDigits || !ignoreURLS
+ && isURL
+ || !(isMixed || isUpper || isDigits || isURL))
+ fireEvent(new SpellEvent(this, word, iterator
+ .getBegin(), iterator.getEnd(), starts,
+ false));
+
+ } else {
+
+ if (!ignoreSentence && starts
+ && Character.isLowerCase(word.charAt(0)))
+ fireEvent(new SpellEvent(this, word, iterator
+ .getBegin(), iterator.getEnd(), true, true));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Fires the specified event.
+ *
+ * @param event
+ * Event to fire
+ */
+ protected final void fireEvent(final ISpellEvent event) {
+ // synchronizing is necessary as this is called from execute
+ Set copy;
+ synchronized (fListeners) {
+ copy = new HashSet(fListeners);
+ }
+ for (final Iterator iterator = copy.iterator(); iterator.hasNext();) {
+ ((ISpellEventListener) iterator.next()).handle(event);
+ }
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellChecker#getProposals(java.lang.String,boolean)
+ */
+ public Set getProposals(final String word, final boolean sentence) {
+
+ // synchronizing might not be needed here since getProposals is
+ // a read-only access and only called in the same thread as
+ // the modifing methods add/removeDictionary (?)
+ Set copy;
+ synchronized (fDictionaries) {
+ copy = new HashSet(fDictionaries);
+ }
+
+ ISpellDictionary dictionary = null;
+ final HashSet proposals = new HashSet();
+
+ for (final Iterator iterator = copy.iterator(); iterator.hasNext();) {
+
+ dictionary = (ISpellDictionary) iterator.next();
+ proposals.addAll(dictionary.getProposals(word, sentence));
+ }
+ return proposals;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker#ignoreWord(java.lang.String)
+ */
+ public final void ignoreWord(final String word) {
+ // synchronizing is necessary as this is a write access
+ fIgnored.add(word.toLowerCase());
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker#isCorrect(java.lang.String)
+ */
+ public final boolean isCorrect(final String word) {
+ // synchronizing is necessary as this is called from execute
+ Set copy;
+ synchronized (fDictionaries) {
+ copy = new HashSet(fDictionaries);
+ }
+
+ if (fIgnored.contains(word.toLowerCase()))
+ return true;
+
+ ISpellDictionary dictionary = null;
+ for (final Iterator iterator = copy.iterator(); iterator.hasNext();) {
+
+ dictionary = (ISpellDictionary) iterator.next();
+ if (dictionary.isCorrect(word))
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellChecker#removeDictionary(org.eclipse.spelling.done.ISpellDictionary)
+ */
+ public final void removeDictionary(final ISpellDictionary dictionary) {
+ // synchronizing is necessary as this is a write access
+ fDictionaries.remove(dictionary);
+ }
+
+ /*
+ * @see org.eclipse.spelling.done.ISpellChecker#removeListener(org.eclipse.spelling.done.ISpellEventListener)
+ */
+ public final void removeListener(final ISpellEventListener listener) {
+ // synchronizing is necessary as this is a write access
+ fListeners.remove(listener);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/IPhoneticDistanceAlgorithm.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/IPhoneticDistanceAlgorithm.java
new file mode 100644
index 0000000..9dc335e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/IPhoneticDistanceAlgorithm.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+/**
+ * Interface of algorithms to compute the phonetic distance between two words.
+ *
+ * @since 3.0
+ */
+public interface IPhoneticDistanceAlgorithm {
+
+ /**
+ * Returns the non-negative phonetic distance between two words
+ *
+ * @param from
+ * The first word
+ * @param to
+ * The second word
+ * @return The non-negative phonetic distance between the words.
+ */
+ public int getDistance(String from, String to);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/IPhoneticHashProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/IPhoneticHashProvider.java
new file mode 100644
index 0000000..ddc9b82
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/IPhoneticHashProvider.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+/**
+ * Interface of hashers to compute the phonetic hash for a word.
+ *
+ * @since 3.0
+ */
+public interface IPhoneticHashProvider {
+
+ /**
+ * Returns the phonetic hash for the word.
+ *
+ * @param word
+ * The word to get the phonetic hash for
+ * @return The phonetic hash for the word
+ */
+ public String getHash(String word);
+
+ /**
+ * Returns an array of characters to compute possible mutations.
+ *
+ * @return Array of possible mutator characters
+ */
+ public char[] getMutators();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckEngine.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckEngine.java
new file mode 100644
index 0000000..b857bd7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckEngine.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.util.Locale;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Interface for spell-check engines.
+ *
+ * @since 3.0
+ */
+public interface ISpellCheckEngine {
+
+ /**
+ * Creates a configured instance of a spell-checker that uses the
+ * appropriate dictionaries.
+ *
+ * @param locale
+ * The locale to get the spell checker for
+ * @param store
+ * The preference store for the spell-checker
+ * @return A configured instance of a spell checker, or null
+ * iff no dictionary could be found for that locale
+ */
+ ISpellChecker createSpellChecker(Locale locale, IPreferenceStore store);
+
+ /**
+ * Returns the current locale of the spell check engine.
+ *
+ * @return The current locale of the engine
+ */
+ Locale getLocale();
+
+ /**
+ * Registers a dictionary for all locales available on the platform.
+ *
+ * This call is equivalent to calling
+ * registerDictionary(Locale,ISpellDictionary)
for each of
+ * the locales returned by Locale.getAvailableLocales()
.
+ *
+ *
+ * @param dictionary
+ * The dictionary to register
+ */
+ void registerDictionary(ISpellDictionary dictionary);
+
+ /**
+ * Registers a dictionary tuned for the specified locale with this engine.
+ *
+ * @param locale
+ * The locale to register the dictionary with
+ * @param dictionary
+ * The dictionary to register
+ */
+ void registerDictionary(Locale locale, ISpellDictionary dictionary);
+
+ /**
+ * Unloads the spell check engine and its associated components.
+ *
+ * All registered dictionaries are unloaded and the engine unregisters for
+ * preference changes. After a new call to
+ * getSpellChecker(Locale)
, it registers again for
+ * preference changes. The dictionaries perform lazy loading, that is to say
+ * on the next query they reload their associated word lists.
+ */
+ void unload();
+
+ /**
+ * Unregisters a dictionary previously registered either by a call to
+ * registerDictionary(Locale,ISpellDictionary)
or
+ * registerDictionary(ISpellDictionary)
. If the dictionary
+ * was not registered before, nothing happens.
+ *
+ * @param dictionary
+ * The dictionary to unregister
+ */
+ void unregisterDictionary(ISpellDictionary dictionary);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckIterator.java
new file mode 100644
index 0000000..6f1ec96
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckIterator.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.util.Iterator;
+
+/**
+ * Interface for iterators used for spell-checking.
+ *
+ * @since 3.0
+ */
+public interface ISpellCheckIterator extends Iterator {
+
+ /**
+ * Returns the begin index (inclusive) of the current word.
+ *
+ * @return The begin index of the current word
+ */
+ public int getBegin();
+
+ /**
+ * Returns the end index (exclusive) of the current word.
+ *
+ * @return The end index of the current word
+ */
+ public int getEnd();
+
+ /**
+ * Does the current word start a new sentence?
+ *
+ * @return true iff the current word starts a new sentence, false
otherwise
+ */
+ public boolean startsSentence();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckPreferenceKeys.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckPreferenceKeys.java
new file mode 100644
index 0000000..b11c817
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellCheckPreferenceKeys.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+/**
+ * Preference keys for the comment spell-checker.
+ *
+ * @since 3.0
+ */
+public interface ISpellCheckPreferenceKeys {
+
+ /**
+ * A named preference that controls whether spell-checking should be
+ * enabled.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String SPELLING_CHECK_SPELLING = "spelling_check_spelling"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether words containing digits should
+ * be skipped during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String SPELLING_IGNORE_DIGITS = "spelling_ignore_digits"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether mixed case words should be
+ * skipped during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String SPELLING_IGNORE_MIXED = "spelling_ignore_mixed"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether sentence capitalization should
+ * be ignored during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String SPELLING_IGNORE_SENTENCE = "spelling_ignore_sentence"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether upper case words should be
+ * skipped during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String SPELLING_IGNORE_UPPER = "spelling_ignore_upper"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether urls should be ignored during
+ * spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String SPELLING_IGNORE_URLS = "spelling_ignore_urls"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the locale used for spell-checking.
+ *
+ * Value is of type String
.
+ *
+ */
+ public final static String SPELLING_LOCALE = "spelling_locale"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the number of proposals offered during
+ * spell-checking.
+ *
+ * Value is of type Integer
.
+ *
+ */
+ public final static String SPELLING_PROPOSAL_THRESHOLD = "spelling_proposal_threshold"; //$NON-NLS-1$
+
+ /**
+ * A named preference that specifies the workspace user dictionary.
+ *
+ * Value is of type String
.
+ *
+ */
+ public final static String SPELLING_USER_DICTIONARY = "spelling_user_dictionary"; //$NON-NLS-1$
+
+ /**
+ * A named preference that specifies whether spelling dictionaries are
+ * available to content assist.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String SPELLING_ENABLE_CONTENTASSIST = "spelling_enable_contentassist"; //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellChecker.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellChecker.java
new file mode 100644
index 0000000..13a9a92
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellChecker.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.util.Set;
+
+/**
+ * Interface for spell-checkers.
+ *
+ * @since 3.0
+ */
+public interface ISpellChecker {
+
+ /**
+ * Adds a dictionary to the list of active dictionaries.
+ *
+ * @param dictionary
+ * The dictionary to add
+ */
+ public void addDictionary(ISpellDictionary dictionary);
+
+ /**
+ * Adds a spell event listener to the active listeners.
+ *
+ * @param listener
+ * The listener to add
+ */
+ public void addListener(ISpellEventListener listener);
+
+ /**
+ * Returns whether this spell checker accepts word additions.
+ *
+ * @return true
if word additions are accepted,
+ * false
otherwise
+ */
+ public boolean acceptsWords();
+
+ /**
+ * Adds the specified word to the set of correct words.
+ *
+ * @param word
+ * The word to add to the set of correct words
+ */
+ public void addWord(String word);
+
+ /**
+ * Checks the specified word until calling ignoreWord(String)
.
+ *
+ * @param word
+ * The word to check
+ */
+ public void checkWord(String word);
+
+ /**
+ * Checks the spelling with the spell-check iterator. Implementations must
+ * be thread safe as this may be called inside a reconciler thread.
+ *
+ * @param iterator
+ * The iterator to use for spell-checking
+ */
+ public void execute(ISpellCheckIterator iterator);
+
+ /**
+ * Returns the ranked proposals for a word.
+ *
+ * @param word
+ * The word to retrieve the proposals for
+ * @param sentence
+ * true
iff the proposals should start a sentence,
+ * false
otherwise
+ * @return Set of ranked proposals for the word
+ */
+ public Set getProposals(String word, boolean sentence);
+
+ /**
+ * Ignores the specified word until calling checkWord(String)
.
+ *
+ * @param word
+ * The word to ignore
+ */
+ public void ignoreWord(String word);
+
+ /**
+ * Is the specified word correctly spelled? Implementations must be thread
+ * safe as this may be called from within a reconciler thread.
+ *
+ * @param word
+ * The word to check its spelling
+ * @return true
iff the word is correctly spelled,
+ * false
otherwise
+ */
+ public boolean isCorrect(String word);
+
+ /**
+ * Remove a dictionary from the list of active dictionaries.
+ *
+ * @param dictionary
+ * The dictionary to remove
+ */
+ public void removeDictionary(ISpellDictionary dictionary);
+
+ /**
+ * Removes a spell event listener from the active listeners.
+ *
+ * @param listener
+ * The listener to remove
+ */
+ public void removeListener(ISpellEventListener listener);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellDictionary.java
new file mode 100644
index 0000000..213b548
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellDictionary.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.util.Set;
+
+/**
+ * Interface of dictionaries to use for spell-checking.
+ *
+ * @since 3.0
+ */
+public interface ISpellDictionary {
+
+ /**
+ * Returns whether this dictionary accepts new words.
+ *
+ * @return true
if this dictionary accepts new words,
+ * false
otherwise
+ */
+ public boolean acceptsWords();
+
+ /**
+ * Externalizes the specified word.
+ *
+ * @param word
+ * The word to externalize in the dictionary
+ */
+ public void addWord(String word);
+
+ /**
+ * Returns the ranked word proposals for an incorrectly spelled word.
+ *
+ * @param word
+ * The word to retrieve the proposals for
+ * @param sentence
+ * true
iff the proposals start a new sentence,
+ * false
otherwise
+ * @return Array of ranked word proposals
+ */
+ public Set getProposals(String word, boolean sentence);
+
+ /**
+ * Is the specified word correctly spelled?
+ *
+ * @param word
+ * The word to spell-check
+ * @return true
iff this word is correctly spelled,
+ * false
otherwise.
+ */
+ public boolean isCorrect(String word);
+
+ /**
+ * Is the dictionary loaded?
+ *
+ * @return true
iff it is loaded, false
+ * otherwise
+ */
+ public boolean isLoaded();
+
+ /**
+ * Empties the dictionary.
+ */
+ public void unload();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellEvent.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellEvent.java
new file mode 100644
index 0000000..ccbd107
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellEvent.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.util.Set;
+
+/**
+ * Event fired by spell-checkers.
+ *
+ * @since 3.0
+ */
+public interface ISpellEvent {
+
+ /**
+ * Returns the begin index of the incorrectly spelled word.
+ *
+ * @return The begin index of the word
+ */
+ public int getBegin();
+
+ /**
+ * Returns the end index of the incorrectly spelled word.
+ *
+ * @return The end index of the word
+ */
+ public int getEnd();
+
+ /**
+ * Returns the proposals for the incorrectly spelled word.
+ *
+ * @return Array of proposals for the word
+ */
+ public Set getProposals();
+
+ /**
+ * Returns the incorrectly spelled word.
+ *
+ * @return The incorrect word
+ */
+ public String getWord();
+
+ /**
+ * Was the incorrectly spelled word found in the dictionary?
+ *
+ * @return true
iff the word was found, false
+ * otherwise
+ */
+ public boolean isMatch();
+
+ /**
+ * Does the incorrectly spelled word start a new sentence?
+ *
+ * @return true iff the word starts a new sentence, false
otherwise
+ */
+ public boolean isStart();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellEventListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellEventListener.java
new file mode 100644
index 0000000..bd38687
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/ISpellEventListener.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+/**
+ * Interface for spell event listeners.
+ *
+ * @since 3.0
+ */
+public interface ISpellEventListener {
+
+ /**
+ * Handles a spell event.
+ *
+ * @param event
+ * Event to handle
+ */
+ public void handle(ISpellEvent event);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/LocaleSensitiveSpellDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/LocaleSensitiveSpellDictionary.java
new file mode 100644
index 0000000..a80ba1a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/LocaleSensitiveSpellDictionary.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Locale;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+
+/**
+ * Platform wide read-only locale sensitive dictionary for spell-checking.
+ *
+ * @since 3.0
+ */
+public class LocaleSensitiveSpellDictionary extends AbstractSpellDictionary {
+
+ /** The locale of this dictionary */
+ private final Locale fLocale;
+
+ /** The location of the dictionaries */
+ private final URL fLocation;
+
+ /**
+ * Creates a new locale sensitive spell dictionary.
+ *
+ * @param locale
+ * The locale for this dictionary
+ * @param location
+ * The location of the locale sensitive dictionaries
+ */
+ public LocaleSensitiveSpellDictionary(final Locale locale,
+ final URL location) {
+ fLocation = location;
+ fLocale = locale;
+ }
+
+ /**
+ * Returns the locale of this dictionary.
+ *
+ * @return The locale of this dictionary
+ */
+ public final Locale getLocale() {
+ return fLocale;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL()
+ */
+ protected final URL getURL() throws MalformedURLException {
+ return new URL(
+ fLocation,
+ fLocale.toString().toLowerCase()
+ + "." + PHPUIMessages.getString("Spelling.dictionary.file.extension")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/PersistentSpellDictionary.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/PersistentSpellDictionary.java
new file mode 100644
index 0000000..20cb55c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/PersistentSpellDictionary.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Persistent modifiable word-list based dictionary.
+ *
+ * @since 3.0
+ */
+public class PersistentSpellDictionary extends AbstractSpellDictionary {
+
+ /** The word list location */
+ private final URL fLocation;
+
+ /**
+ * Creates a new persistent spell dictionary.
+ *
+ * @param url
+ * The URL of the word list for this dictionary
+ */
+ public PersistentSpellDictionary(final URL url) {
+ fLocation = url;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.text.spelling.engine.AbstractSpellDictionary#acceptsWords()
+ */
+ public boolean acceptsWords() {
+ return true;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary#addWord(java.lang.String)
+ */
+ public void addWord(final String word) {
+
+ if (!isCorrect(word)) {
+
+ hashWord(word);
+ try {
+
+ final FileWriter writer = new FileWriter(fLocation.getPath(),
+ true);
+ writer.write(word);
+ writer.write("\n"); //$NON-NLS-1$
+ writer.close();
+
+ } catch (IOException exception) {
+ // Do nothing
+ }
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL()
+ */
+ protected final URL getURL() {
+ return fLocation;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/RankedWordProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/RankedWordProposal.java
new file mode 100644
index 0000000..282d05f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/RankedWordProposal.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+/**
+ * Ranked word proposal for quick fix and content assist.
+ *
+ * @since 3.0
+ */
+public class RankedWordProposal implements Comparable {
+
+ /** The word rank */
+ private int fRank;
+
+ /** The word text */
+ private final String fText;
+
+ /**
+ * Creates a new ranked word proposal.
+ *
+ * @param text
+ * The text of this proposal
+ * @param rank
+ * The rank of this proposal
+ */
+ public RankedWordProposal(final String text, final int rank) {
+ fText = text;
+ fRank = rank;
+ }
+
+ /*
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public final int compareTo(Object object) {
+
+ final RankedWordProposal word = (RankedWordProposal) object;
+ final int rank = word.getRank();
+
+ if (fRank < rank)
+ return -1;
+
+ if (fRank > rank)
+ return 1;
+
+ return 0;
+ }
+
+ /*
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public final boolean equals(Object object) {
+
+ if (object instanceof RankedWordProposal)
+ return object.hashCode() == hashCode();
+
+ return false;
+ }
+
+ /**
+ * Returns the rank of the word
+ *
+ * @return The rank of the word
+ */
+ public final int getRank() {
+ return fRank;
+ }
+
+ /**
+ * Returns the text of this word.
+ *
+ * @return The text of this word
+ */
+ public final String getText() {
+ return fText;
+ }
+
+ /*
+ * @see java.lang.Object#hashCode()
+ */
+ public final int hashCode() {
+ return fText.hashCode();
+ }
+
+ /**
+ * Sets the rank of the word.
+ *
+ * @param rank
+ * The rank to set
+ */
+ public final void setRank(final int rank) {
+ fRank = rank;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/SpellEvent.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/SpellEvent.java
new file mode 100644
index 0000000..da9d671
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/SpellEvent.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.spelling.engine;
+
+import java.util.Set;
+
+/**
+ * Spell event fired for words detected by a spell-check iterator.
+ *
+ * @since 3.0
+ */
+public class SpellEvent implements ISpellEvent {
+
+ /** The begin index of the word in the spell-checkable medium */
+ private final int fBegin;
+
+ /** The spell-checker that causes the event */
+ private final ISpellChecker fChecker;
+
+ /** The end index of the word in the spell-checkable medium */
+ private final int fEnd;
+
+ /** Was the word found in the dictionary? */
+ private final boolean fMatch;
+
+ /** Does the word start a new sentence? */
+ private final boolean fSentence;
+
+ /** The word that causes the spell event */
+ private final String fWord;
+
+ /**
+ * Creates a new spell event.
+ *
+ * @param checker
+ * The spell-checker that causes the event
+ * @param word
+ * The word that causes the event
+ * @param begin
+ * The begin index of the word in the spell-checkable medium
+ * @param end
+ * The end index of the word in the spell-checkable medium
+ * @param sentence
+ * true
iff the word starts a new sentence,
+ * false
otherwise
+ * @param match
+ * true
iff the word was found in the dictionary,
+ * false
otherwise
+ */
+ protected SpellEvent(final ISpellChecker checker, final String word,
+ final int begin, final int end, final boolean sentence,
+ final boolean match) {
+ fChecker = checker;
+ fEnd = end;
+ fBegin = begin;
+ fWord = word;
+ fSentence = sentence;
+ fMatch = match;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent#getBegin()
+ */
+ public final int getBegin() {
+ return fBegin;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent#getEnd()
+ */
+ public final int getEnd() {
+ return fEnd;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent#getProposals()
+ */
+ public final Set getProposals() {
+ return fChecker.getProposals(fWord, fSentence);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent#getWord()
+ */
+ public final String getWord() {
+ return fWord;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent#isMatch()
+ */
+ public final boolean isMatch() {
+ return fMatch;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent#isStart()
+ */
+ public final boolean isStart() {
+ return fSentence;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/package.html b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/package.html
new file mode 100644
index 0000000..6ecebe0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/engine/package.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+ Package-level Javadoc
+
+
+Provides the core functionality for spell-checking documents
+
+Package Specification
+This package provides the interfaces for the notions of dictionary, edit distance, phonetic hash,
+spell event and spell-check iterator. For most of these interfaces a default implementation
+for english languages is provided. These implementations can be reused in custom dictionaries or
+spell-check iterators, or replaced by more specialized algorithms for a particular group of languages.
+
+Spell Check Engine
+The central point to access the spell-checker functionality is the interface ISpellCheckEngine.
+Implementations of this interface provide support for life-cycle management, registering and unregistering
+dictionaries, changing the locale of the engine and creating a spell-checker for a specific language.
+
+The following steps are needed to obtain a spell-checker for a specific language:
+
+- Create an instance of ISpellCheckEngine. In this package, no default implementation is provided,
+since the management of the dictionary registering and loading is application dependent. Usually, instances
+of ISpellCheckEngine are implemented as singletons.
+- Create the appropriate dictionaries that should be used during the spell-check process. All dictionaries that
+can be registered with ISpellCheckEngine must implement the interface ISpellCheckDictionary.
+For this interface, an abstract implementation is provided in the class AbstractSpellDictionary.
+Depending on the language of the words contained in this dictionary, custom algorithms for the phonetic hash
+ (IPhoneticHashProvider) and the edit distance (IPhoneticDistanceAlgorithm) should be implemented
+ and registered with the dictionary.
+ - Instances of spell-checkers can now be created by calling createSpellChecker(Locale), where the locale
+ denotes the language that the spell-checker should use while executing.
+
+When requesting a new spell-checker with a different locale via createSpellChecker(Locale), the spell-checker is
+reconfigured with the new dictionaries. More concretely, the old dictionary is unregistered and a new one registered for the
+desired locale is associated with the spell-checker. If no such dictionary is available, no spell-checker is returned and
+the locale of the engine is reset to its default locale.
+
+Dictionaries
+Dictionaries are the data structures to hold word lists for a particular language. All implementations of dictionaries must
+implement the interface ISpellDictionary. It provides support for life-cycle management as well as the facility to query
+words from the list, add words to the list and get correction proposals for incorrectly spelt words.
+
+This package provides a default implementation of a dictionary (AbstractSpellDictionary) that uses algorithms
+convenient for english languages.
+Every dictionary needs two kinds of algorithms to be plugged in:
+
+- An edit distance algorithm: Edit distance algorithms implement the interface IPhoneticDistanceAlgorithm. The algorithm
+is used to determine the similarity between two words. This package provides a default implementation for languages using the latin alphabet (DefaultPhoneticDistanceAlgorithm).
+The default algorithm uses the Levenshtein text edit distance.
+- A hash algorithm: Phonetic hash providers implement the interface IPhoneticHashProvider. The purpose of
+phonetic hashes is to have a representation of words which allows comparing it to other, similar words. This package provides a default
+implementation which is convenient for slavic and english languages. It uses the double metaphone algorithm by published
+Lawrence Philips.
+
+By plugging in custom implementations of one or both of these algorithms the abstract implementation AbstractSpellDictionary can
+be customized to specified languages and alphabets.
+
+Spell Check Iterators
+Instances of ISpellChecker are usually language-, locale- and medium independent implementations and therefore need an input provider. The
+interface ISpellCheckIterator serves this purpose by abstracting the tokenizing of text media to a simple iteration. The actual spell-check process
+is launched by calling ISpellChecker#execute(ISpellCheckIterator). This method uses the indicated spell-check iterator to determine the
+words that are to be spell-checked. This package provides no default implementation of a spell-check iterator.
+
+Event Handling
+To communicate the results of a spell-check pass, spell-checkers fire spell events that inform listeners about the status
+of a particular word being spell-checked. Instances that are interested in receiving spell events must implement
+the interface ISpellEventListener and register with the spell-checker before the spell-check process starts.
+A spell event contains the following information:
+
+- The word being spell-checked
+- The begin index of the current word in the text medium
+- The end index in the text medium
+- A flag whether this word was found in one of the registered dictionaries
+- A flag that indicates whether this word starts a new sentence
+- The set of proposals if the word was not correctly spelt. This information is lazily computed.
+
+Spell event listeners are free to handle the events in any way. However, listeners are not allowed to block during
+the event handling unless the spell-checking process happens in another thread.
+
+
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/package.html b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/package.html
new file mode 100644
index 0000000..f880e28
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/spelling/package.html
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+ Package-level Javadoc
+
+
+Provides facilities for spell-checking of comments and strings in Java source code.
+
+Package Specification
+The content of this package extends the base functionality of the spell-checking engine.
+
+It contains a spell-check engine specialized in Javadoc comments.
+Several dictionaries with Java specific content like Javadoc keywords, HTML tags and Task tags
+are provided.
+Additionally, the engine contributes correction proposals to the QuickFix processor.
+For non Java specific content the engine also contributes
+word completion proposals to the content assist processor.
+
+Spell-check engine
+SpellCheckEngine is the default implementation of the interface ISpellCheckEngine.
+It provides a facade for dealing with the setup of a spell-checker. This class provides methods
+to retrieve the available dictionaries and is responsible for the registration of those with the spell-checker.
+SpellCheckEngine also has support for life-cycle management. Single dictionaries can be temporarily
+unloaded from memory or unregistered.
+To contribute own dictionaries use the methods to register locale sensitive or insensitive dictionaries. A dictionary can
+be associated to a specified locale, but can also be available for spell-checking arbitrary text in arbitrary languages.
+The actual spell-checker for a specified language can then be obtained by calling createSpellChecker(Locale).
+This is the central point to working with the spell-checker. When requesting a spell-checker for a specified locale, the
+engine looks up the corresponding dictionary and registers it with the spell-checker. Note that the dictionaries
+are lazily loaded and can be further optimized by prefiltering the queried words.
+
+Note: Locale sensitive dictionaries must be located in the "dictionaries/" subdirectory of the JDT UI plugin install
+location. The dictionaries are newline-separated word lists having the filename "language_country.dictionary", where "language" and "country" are
+the lowercase ISO-3166 language and country codes, respectively. The default dictionary is "en_us.dictionary". For correct
+behavior of the spell-check engine, at least the default dictionary must be installed. The default dictionary corresponds to the default locale
+of the spell-check engine.
+
+Dictionaries
+This implementation for a Javadoc comment spell-checker provides the following read-only
+dictionaries:
+
+- A dictionary for Javadoc tags: This dictionary contains the most commonly used Javadoc tags. When
+spell-checking Javadoc comments, this dictionary contributes correction proposals to the QuickFix processor to correct misspelt Javadoc tags.
+- A dictionary for HTML tags: This dictionary contains the most commonly used HTML tags for writing Javadoc comments. When spell-checking
+Javadoc- or multiline comments, this dictionary contributes correction proposals to the QuickFix processor as well as
+word completion proposals to the Content Assist processor.
+- A dictionary for Task tags: This dictionary reflects the currently available Java Task tags. When spell-checking arbitrary text in Java files,
+this dictionary contributes proposals both to the QuickFix processor and the Content Assist processor.
+
+
+QuickFix processor
+The comment spell-checker also contributes a quickfix processor as an extension. This implementation of a quickfix processor
+contributes the following correction proposals:
+
+- Proposals for correct spelling: A number of words considered most similar to the incorrectly spelt word.
+- The proposal to correct the sentence capitalization: This proposal is offered on incorrectly spelt words at the beginning of a sentence.
+
- The proposal to add the unrecognized word to the locale-insensitive dictionaries
+- The proposal to ignore the word during the current editing session
+
+
+Content Assist processor
+The last contribution of the spell-checker is the support for word completion. The spell-checker provides a custom
+content assist processor to produce word completion proposals.
+Word completion works on all non Java code content types and delivers a number of proposals based on the current
+caret position.
+
+
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/AbstractProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/AbstractProposal.java
new file mode 100644
index 0000000..e79994e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/AbstractProposal.java
@@ -0,0 +1,101 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import java.util.WeakHashMap;
+
+import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
+
+
+/**
+ * A PHP identifier proposal.
+ */
+public abstract class AbstractProposal implements IPHPCompletionProposal {
+ protected IRegion fSelectedRegion; // initialized by apply()
+
+ protected final ITextViewer fViewer;
+
+ protected ContextInformation fContextInfo;
+
+ public AbstractProposal(ITextViewer viewer) {
+ fContextInfo = null;
+ fViewer = viewer;
+ }
+
+ protected static String textToHTML(String string) {
+ StringBuffer buffer = new StringBuffer(string.length());
+ buffer.append(""); //$NON-NLS-1$
+
+ for (int i = 0; i != string.length(); i++) {
+ char ch = string.charAt(i);
+
+ switch (ch) {
+ case '&':
+ buffer.append("&"); //$NON-NLS-1$
+ break;
+
+ case '<':
+ buffer.append("<"); //$NON-NLS-1$
+ break;
+
+ case '>':
+ buffer.append(">"); //$NON-NLS-1$
+ break;
+
+ case '\t':
+ buffer.append(" "); //$NON-NLS-1$
+ break;
+
+ case '\n':
+ buffer.append("
"); //$NON-NLS-1$
+ break;
+
+ default:
+ buffer.append(ch);
+ break;
+ }
+ }
+
+ buffer.append("
"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+
+ /*
+ * @see ICompletionProposal#getSelection(IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return new Point(fSelectedRegion.getOffset(), fSelectedRegion
+ .getLength());
+ }
+
+ protected void handleException(CoreException e) {
+ WebUI.log(e);
+ }
+
+ protected void openErrorDialog(BadLocationException e) {
+ Shell shell = fViewer.getTextWidget().getShell();
+ MessageDialog.openError(shell, TemplateMessages
+ .getString("TemplateEvaluator.error.title"), e.getMessage()); //$NON-NLS-1$
+ }
+
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/BuiltInEngine.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/BuiltInEngine.java
new file mode 100644
index 0000000..22cface
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/BuiltInEngine.java
@@ -0,0 +1,126 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContextType;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContextType;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPElement;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPFunction;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.swt.graphics.Point;
+
+public class BuiltInEngine {
+
+ /** The context type. */
+ private JavaContextType fContextType;
+
+ /** The result proposals. */
+ private ArrayList fProposals = new ArrayList();
+
+ /**
+ * Creates the template engine for a particular context type. See
+ * TemplateContext
for supported context types.
+ */
+ public BuiltInEngine(JavaContextType contextType) {
+ // Assert.isNotNull(contextType);
+ fContextType = contextType;
+ }
+
+ /**
+ * Empties the collector.
+ *
+ * @param viewer
+ * the text viewer
+ * @param unit
+ * the compilation unit (may be null
)
+ */
+ public void reset() {
+ fProposals.clear();
+ }
+
+ /**
+ * Returns the array of matching templates.
+ */
+ public IPHPCompletionProposal[] getResults() {
+ return (IPHPCompletionProposal[]) fProposals
+ .toArray(new IPHPCompletionProposal[fProposals.size()]);
+ }
+
+ /**
+ * Inspects the context of the compilation unit around
+ * completionPosition
and feeds the collector with proposals.
+ *
+ * @param viewer
+ * the text viewer
+ * @param completionPosition
+ * the context position in the document of the text viewer
+ * @param compilationUnit
+ * the compilation unit (may be null
)
+ */
+ public void complete(ITextViewer viewer, int completionPosition,
+ ArrayList identifiers, ICompilationUnit compilationUnit)
+ // hrows JavaModelException
+ {
+ IDocument document = viewer.getDocument();
+
+ // prohibit recursion
+ // if (LinkedPositionManager.hasActiveManager(document))
+ // return;
+
+ if (!(fContextType instanceof CompilationUnitContextType))
+ return;
+ Point selection = viewer.getSelectedRange();
+ // remember selected text
+ String selectedText = null;
+ if (selection.y != 0) {
+ try {
+ selectedText = document.get(selection.x, selection.y);
+ } catch (BadLocationException e) {
+ }
+ }
+
+ // ((CompilationUnitContextType)
+ // fContextType).setContextParameters(document, completionPosition,
+ // selection.y); //mpilationUnit);
+ // JavaContext context = (JavaContext) fContextType.createContext();
+ JavaContext context = (JavaContext) fContextType.createContext(
+ document, completionPosition, selection.y, compilationUnit);
+ context.setVariable("selection", selectedText); //$NON-NLS-1$
+ int start = context.getStart();
+ int end = context.getEnd();
+ IRegion region = new Region(start, end - start);
+
+ // Template[] templates= Templates.getInstance().getTemplates();
+ String identifier = null;
+ int maxProposals = WebUI.MAX_PROPOSALS;
+ PHPElement element = null;
+ for (int i = 0; i != identifiers.size(); i++) {
+ element = (PHPElement) identifiers.get(i);
+ if (element instanceof PHPFunction) {
+ identifier = ((PHPFunction) element).getName();
+ if (context.canEvaluate(identifier)) {
+ if (maxProposals-- < 0) {
+ return;
+ }
+ fProposals.add(new BuiltInProposal(identifier,
+ (PHPFunction) element, context, region, viewer));
+ }
+ }
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/BuiltInProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/BuiltInProposal.java
new file mode 100644
index 0000000..f05e19d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/BuiltInProposal.java
@@ -0,0 +1,180 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPFunction;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.swt.graphics.Image;
+
+// import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+// import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+// import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+
+/**
+ * A PHP identifier proposal.
+ */
+public class BuiltInProposal extends AbstractProposal {
+ private final TemplateContext fContext;
+
+ private final PHPFunction fFunction;
+
+ private final IRegion fRegion;
+
+ private final String fBuiltinFunctionName;
+
+ /**
+ * Creates a template proposal with a template and its context.
+ *
+ * @param template
+ * the template
+ * @param context
+ * the context in which the template was requested.
+ * @param image
+ * the icon of the proposal.
+ */
+ public BuiltInProposal(String functionName, PHPFunction function,
+ TemplateContext context, IRegion region, ITextViewer viewer) {
+ super(viewer);
+ fBuiltinFunctionName = functionName;
+ fFunction = function;
+ fContext = context;
+ // fViewer = viewer;
+ fRegion = region;
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public void apply(IDocument document) {
+ try {
+ // if (fTemplateBuffer == null)
+ // fTemplateBuffer= fContext.evaluate(fTemplate);
+
+ int start = fRegion.getOffset();
+ int end = fRegion.getOffset() + fRegion.getLength();
+
+ // insert template string
+ // String templateString = fTemplate; //
+ // fTemplateBuffer.getString();
+ document.replace(start, end - start, fBuiltinFunctionName + "()");
+
+ // translate positions
+ LinkedPositionManager manager = new LinkedPositionManager(document);
+ // TemplatePosition[] variables= fTemplateBuffer.getVariables();
+ // for (int i= 0; i != variables.length; i++) {
+ // TemplatePosition variable= variables[i];
+ //
+ // if (variable.isResolved())
+ // continue;
+ //
+ // int[] offsets= variable.getOffsets();
+ // int length= variable.getLength();
+ //
+ // for (int j= 0; j != offsets.length; j++)
+ // manager.addPosition(offsets[j] + start, length);
+ // }
+
+ LinkedPositionUI editor = new LinkedPositionUI(fViewer, manager);
+ editor.setFinalCaretOffset(fBuiltinFunctionName.length() + start
+ + 1);
+ // editor.setFinalCaretOffset(getCaretOffset(fTemplateBuffer) +
+ // start);
+ editor.enter();
+
+ fSelectedRegion = editor.getSelectedRegion();
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ openErrorDialog(e);
+
+ }
+ // catch (CoreException e) {
+ // handleException(e);
+ // }
+ }
+
+ public String getAdditionalProposalInfo() {
+ return fFunction.getHoverText();
+ }
+
+ public IContextInformation getContextInformation() {
+ if (fContextInfo == null) {
+ String contextInfoString = fFunction.getHoverText();
+ if (contextInfoString != null && contextInfoString.length() > 0) {
+ // extract the parameter context information for the function:
+ int i0 = contextInfoString.indexOf('(');
+ int newline = contextInfoString.indexOf('\n');
+ if (i0 >= 0 && (i0 < newline || newline < 0)) {
+ int i1 = contextInfoString.indexOf(')', i0 + 1);
+ if (i1 > 0) {
+ fContextInfo = new ContextInformation(null,
+ contextInfoString.substring(i0 + 1, i1));
+ } else {
+ fContextInfo = new ContextInformation(null,
+ contextInfoString);
+ }
+ } else {
+ fContextInfo = new ContextInformation(null,
+ contextInfoString);
+ }
+ }
+ }
+ return fContextInfo;
+ }
+
+ /*
+ * @see ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return fBuiltinFunctionName
+ + TemplateMessages.getString("TemplateProposal.delimiter") + fFunction.getUsage(); // $NON-NLS-1$
+ // //$NON-NLS-1$
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return PHPUiImages.get(PHPUiImages.IMG_BUILTIN);
+ }
+
+ /*
+ * @see IJavaCompletionProposal#getRelevance()
+ */
+ public int getRelevance() {
+
+ if (fContext instanceof JavaContext) {
+ JavaContext context = (JavaContext) fContext;
+ switch (context.getCharacterBeforeStart()) {
+ // high relevance after whitespace
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ return 50;
+
+ default:
+ return 0;
+ }
+ } else {
+ return 50;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationEngine.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationEngine.java
new file mode 100644
index 0000000..f393c18
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationEngine.java
@@ -0,0 +1,298 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.SortedMap;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContextType;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContextType;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.swt.graphics.Point;
+
+public class DeclarationEngine {
+
+ /** The context type. */
+ private JavaContextType fContextType;
+
+ /** The result proposals. */
+ private ArrayList fProposals = new ArrayList();
+
+ /** Token determines last which declarations are allowed for proposal */
+ private int fLastSignificantToken;
+
+ private IProject fProject;
+
+ // private IFile fFile;
+ private String fFileName;
+
+ /**
+ * Creates the template engine for a particular context type. See
+ * TemplateContext
for supported context types.
+ */
+ public DeclarationEngine(IProject project, JavaContextType contextType,
+ int lastSignificantToken, IFile file) {
+ // Assert.isNotNull(contextType);
+ fProject = project;
+ fContextType = contextType;
+
+ fLastSignificantToken = lastSignificantToken;
+ // fFile = file;
+ if (file != null) {
+ fFileName = file.getProjectRelativePath().toString();
+ } else {
+ fFileName = "";
+ }
+ }
+
+ /**
+ * Empties the collector.
+ *
+ * @param viewer
+ * the text viewer
+ * @param unit
+ * the compilation unit (may be null
)
+ */
+ public void reset() {
+ fProposals.clear();
+ }
+
+ /**
+ * Returns the array of matching templates.
+ */
+ public IPHPCompletionProposal[] getResults() {
+ return (IPHPCompletionProposal[]) fProposals
+ .toArray(new IPHPCompletionProposal[fProposals.size()]);
+ }
+
+ /**
+ * Inspects the context of the compilation unit around
+ * completionPosition
and feeds the collector with proposals.
+ *
+ * @param viewer
+ * the text viewer
+ * @param completionPosition
+ * the context position in the document of the text viewer
+ * @param compilationUnit
+ * the compilation unit (may be null
)
+ */
+ public void completeObject(ITextViewer viewer, int completionPosition,
+ SortedMap map, ICompilationUnit compilationUnit) {
+ IDocument document = viewer.getDocument();
+
+ if (!(fContextType instanceof CompilationUnitContextType))
+ return;
+
+ Point selection = viewer.getSelectedRange();
+
+ // remember selected text
+ String selectedText = null;
+
+ if (selection.y != 0) {
+ try {
+ selectedText = document.get(selection.x, selection.y);
+ } catch (BadLocationException e) {
+ }
+ }
+
+ JavaContext context = (JavaContext) fContextType.createContext(
+ document, completionPosition, selection.y, compilationUnit);
+ context.setVariable("selection", selectedText); //$NON-NLS-1$
+
+ int start = context.getStart();
+ int end = context.getEnd();
+ String prefix = context.getKey();
+ IRegion region = new Region(start, end - start);
+
+ String identifier = null;
+
+ SortedMap subMap = map.subMap(prefix, prefix + '\255');
+ Iterator iter = subMap.keySet().iterator();
+ PHPIdentifierLocation location;
+ ArrayList list;
+ int maxProposals = PHPeclipsePlugin.MAX_PROPOSALS;
+ while (iter.hasNext()) {
+ identifier = (String) iter.next();
+ if (context.canEvaluate(identifier)) {
+ list = (ArrayList) subMap.get(identifier);
+ for (int i = 0; i < list.size(); i++) {
+ location = (PHPIdentifierLocation) list.get(i);
+ int type = location.getType();
+ switch (fLastSignificantToken) {
+ case ITerminalSymbols.TokenNameMINUS_GREATER:
+ if (type != PHPIdentifierLocation.METHOD
+ && type != PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ break;
+ case ITerminalSymbols.TokenNameVariable:
+ if (type != PHPIdentifierLocation.METHOD
+ && type != PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ // check all filenames of the subclasses
+ // if (fFileName.equals(location.getFilename())) {
+ // continue; // for loop
+ // }
+ break;
+ case ITerminalSymbols.TokenNamethis_PHP_COMPLETION:
+ if (type != PHPIdentifierLocation.METHOD
+ && type != PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ // check all filenames of the subclasses
+ // if (!fFileName.equals(location.getFilename())) {
+ // continue; // for loop
+ // }
+ break;
+ case ITerminalSymbols.TokenNamenew:
+ if (type != PHPIdentifierLocation.CLASS
+ && type != PHPIdentifierLocation.CONSTRUCTOR) {
+ continue; // for loop
+ }
+ break;
+ default:
+ if (type == PHPIdentifierLocation.METHOD
+ || type == PHPIdentifierLocation.CONSTRUCTOR
+ || type == PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ }
+ if (maxProposals-- < 0) {
+ return;
+ }
+ fProposals.add(new DeclarationProposal(fProject,
+ identifier, location, context, region, viewer));
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Inspects the context of the compilation unit around
+ * completionPosition
and feeds the collector with proposals.
+ *
+ * @param viewer
+ * the text viewer
+ * @param completionPosition
+ * the context position in the document of the text viewer
+ * @param compilationUnit
+ * the compilation unit (may be null
)
+ */
+ public void complete(ITextViewer viewer, int completionPosition,
+ SortedMap map, ICompilationUnit compilationUnit) {
+ IDocument document = viewer.getDocument();
+
+ if (!(fContextType instanceof CompilationUnitContextType))
+ return;
+
+ Point selection = viewer.getSelectedRange();
+
+ // remember selected text
+ String selectedText = null;
+
+ if (selection.y != 0) {
+ try {
+ selectedText = document.get(selection.x, selection.y);
+ } catch (BadLocationException e) {
+ }
+ }
+
+ // ((CompilationUnitContextType)
+ // fContextType).setContextParameters(document, completionPosition,
+ // selection.y);
+
+ // CompilationUnitContext context = (CompilationUnitContext)
+ // fContextType.createContext();
+ JavaContext context = (JavaContext) fContextType.createContext(
+ document, completionPosition, selection.y, compilationUnit);
+ context.setVariable("selection", selectedText); //$NON-NLS-1$
+
+ int start = context.getStart();
+ int end = context.getEnd();
+ String prefix = context.getKey();
+ IRegion region = new Region(start, end - start);
+
+ String identifier = null;
+
+ SortedMap subMap = map.subMap(prefix, prefix + '\255');
+ Iterator iter = subMap.keySet().iterator();
+ PHPIdentifierLocation location;
+ ArrayList list;
+ int maxProposals = PHPeclipsePlugin.MAX_PROPOSALS;
+ while (iter.hasNext()) {
+ identifier = (String) iter.next();
+ if (context.canEvaluate(identifier)) {
+ list = (ArrayList) subMap.get(identifier);
+ for (int i = 0; i < list.size(); i++) {
+ location = (PHPIdentifierLocation) list.get(i);
+ int type = location.getType();
+ switch (fLastSignificantToken) {
+ case ITerminalSymbols.TokenNameMINUS_GREATER:
+ if (type != PHPIdentifierLocation.METHOD
+ && type != PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ break;
+ case ITerminalSymbols.TokenNameVariable:
+ if (type != PHPIdentifierLocation.METHOD
+ && type != PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ // check all filenames of the subclasses
+ if (fFileName.equals(location.getFilename())) {
+ continue; // for loop
+ }
+ break;
+ case ITerminalSymbols.TokenNamethis_PHP_COMPLETION:
+ if (type != PHPIdentifierLocation.METHOD
+ && type != PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ // check all filenames of the subclasses
+ if (!fFileName.equals(location.getFilename())) {
+ continue; // for loop
+ }
+ break;
+ case ITerminalSymbols.TokenNamenew:
+ if (type != PHPIdentifierLocation.CLASS
+ && type != PHPIdentifierLocation.CONSTRUCTOR) {
+ continue; // for loop
+ }
+ break;
+ default:
+ if (type == PHPIdentifierLocation.METHOD
+ || type == PHPIdentifierLocation.CONSTRUCTOR
+ || type == PHPIdentifierLocation.VARIABLE) {
+ continue; // for loop
+ }
+ }
+ if (maxProposals-- < 0) {
+ return;
+ }
+ fProposals.add(new DeclarationProposal(fProject,
+ identifier, location, context, region, viewer));
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationProposal.java
new file mode 100644
index 0000000..d08d6e8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationProposal.java
@@ -0,0 +1,287 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import net.sourceforge.phpdt.internal.corext.phpdoc.PHPDocUtil;
+import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.swt.graphics.Image;
+
+// import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+// import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+// import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+
+/**
+ * A PHP identifier proposal.
+ */
+public class DeclarationProposal extends AbstractProposal { // implements
+ // IPHPCompletionProposal
+ // {
+ private IProject fProject;
+
+ private final TemplateContext fContext;
+
+ private final PHPIdentifierLocation fLocation;
+
+ String fInfo;
+
+ // private TemplateBuffer fTemplateBuffer;
+ // private String fOldText;
+ // private final Image fImage_fun;
+ // private final Image fImage_var;
+ private final IRegion fRegion;
+
+ // private IRegion fSelectedRegion; // initialized by apply()
+
+ private final String fIdentifierName;
+
+ // private final ITextViewer fViewer;
+
+ /**
+ * Creates a template proposal with a template and its context.
+ *
+ * @param template
+ * the template
+ * @param context
+ * the context in which the template was requested.
+ * @param image
+ * the icon of the proposal.
+ */
+ public DeclarationProposal(IProject project, String identifierName,
+ PHPIdentifierLocation location, TemplateContext context,
+ IRegion region, ITextViewer viewer) {
+ super(viewer);
+ // Image image_fun,
+ // Image image_var) {
+ fProject = project;
+ fIdentifierName = identifierName;
+ fLocation = location;
+ fContext = context;
+ fRegion = region;
+ fInfo = null;
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public void apply(IDocument document) {
+ try {
+ // if (fTemplateBuffer == null)
+ // fTemplateBuffer= fContext.evaluate(fTemplate);
+
+ int start = fRegion.getOffset();
+ int end = fRegion.getOffset() + fRegion.getLength();
+
+ switch (fLocation.getType()) {
+ case PHPIdentifierLocation.FUNCTION:
+ document.replace(start, end - start, fIdentifierName + "()");
+ break;
+ case PHPIdentifierLocation.CONSTRUCTOR:
+ document.replace(start, end - start, fIdentifierName + "()");
+ break;
+ case PHPIdentifierLocation.METHOD:
+ document.replace(start, end - start, fIdentifierName + "()");
+ break;
+
+ default:
+ document.replace(start, end - start, fIdentifierName);
+ }
+
+ // translate positions
+ LinkedPositionManager manager = new LinkedPositionManager(document);
+ // TemplatePosition[] variables= fTemplateBuffer.getVariables();
+ // for (int i= 0; i != variables.length; i++) {
+ // TemplatePosition variable= variables[i];
+ //
+ // if (variable.isResolved())
+ // continue;
+ //
+ // int[] offsets= variable.getOffsets();
+ // int length= variable.getLength();
+ //
+ // for (int j= 0; j != offsets.length; j++)
+ // manager.addPosition(offsets[j] + start, length);
+ // }
+
+ LinkedPositionUI editor = new LinkedPositionUI(fViewer, manager);
+ switch (fLocation.getType()) {
+ case PHPIdentifierLocation.FUNCTION:
+ editor
+ .setFinalCaretOffset(fIdentifierName.length() + start
+ + 1);
+ break;
+ case PHPIdentifierLocation.CONSTRUCTOR:
+ editor
+ .setFinalCaretOffset(fIdentifierName.length() + start
+ + 1);
+ break;
+ case PHPIdentifierLocation.METHOD:
+ editor
+ .setFinalCaretOffset(fIdentifierName.length() + start
+ + 1);
+ break;
+
+ default:
+ editor.setFinalCaretOffset(fIdentifierName.length() + start);
+ }
+ editor.enter();
+
+ fSelectedRegion = editor.getSelectedRegion();
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ openErrorDialog(e);
+
+ }
+ // catch (CoreException e) {
+ // handleException(e);
+ // }
+ }
+
+ /*
+ * @see ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ if (fInfo == null) {
+ fInfo = computeProposalInfo();
+ }
+ return fInfo;
+ }
+
+ private String computeProposalInfo() {
+ StringBuffer hoverInfoBuffer = new StringBuffer();
+ // String workspaceLocation =
+ // PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
+ String workspaceLocation;
+ if (fProject != null) {
+ workspaceLocation = fProject.getLocation().toString() + '/';
+ } else {
+ // should never happen?
+ workspaceLocation = WebUI.getWorkspace().getRoot()
+ .getFullPath().toString();
+ }
+ String filename = workspaceLocation + fLocation.getFilename();
+ PHPDocUtil.appendPHPDoc(hoverInfoBuffer, filename, fLocation);
+ return hoverInfoBuffer.toString();
+ }
+
+ public IContextInformation getContextInformation() {
+ if (fContextInfo == null) {
+ if (fLocation != null) {
+ fInfo = fLocation.getUsage();
+ if (fInfo != null) {
+ // extract the parameter context information for the
+ // function:
+ int i0 = fInfo.indexOf('(');
+ int newline = fInfo.indexOf('\n');
+ if (i0 >= 0 && (i0 < newline || newline < 0)) {
+ int i1 = fInfo.indexOf(')', i0 + 1);
+ if (i1 > 0) {
+
+ fContextInfo = new ContextInformation(null, fInfo
+ .substring(i0 + 1, i1));
+ } else {
+ fContextInfo = new ContextInformation(null, fInfo);
+ }
+ } else {
+ fContextInfo = new ContextInformation(null, fInfo);
+ }
+ }
+ }
+ }
+ return fContextInfo;
+ }
+
+ /*
+ * @see ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ String workspaceLocation;
+ String workspaceName;
+ if (fProject != null) {
+ workspaceLocation = fProject.getFullPath().toString() + '/';
+ workspaceName = fProject.getName().toString() + '/';
+ } else {
+ // should never happen?
+ workspaceLocation = WebUI.getWorkspace().getRoot()
+ .getFullPath().toString();
+ workspaceName = workspaceLocation;
+ }
+ String filename = fLocation.getFilename();
+ String usage = PHPDocUtil.getUsage(workspaceLocation + filename, fLocation);
+ String result = fIdentifierName
+ + TemplateMessages.getString("TemplateProposal.delimiter");
+ if (usage.length() > 0) {
+ result += usage
+ + TemplateMessages.getString("TemplateProposal.delimiter");
+ }
+ result += workspaceName + filename;
+ return result;
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ switch (fLocation.getType()) {
+ case PHPIdentifierLocation.FUNCTION:
+ return PHPUiImages.get(PHPUiImages.IMG_FUN);
+ case PHPIdentifierLocation.CLASS:
+ return PHPUiImages.get(PHPUiImages.IMG_CLASS);
+ case PHPIdentifierLocation.CONSTRUCTOR:
+ return PHPUiImages.get(PHPUiImages.IMG_CLASS);
+ case PHPIdentifierLocation.METHOD:
+ return PHPUiImages.get(PHPUiImages.IMG_FUN);
+ case PHPIdentifierLocation.DEFINE:
+ return PHPUiImages.get(PHPUiImages.IMG_DEFINE);
+ case PHPIdentifierLocation.VARIABLE:
+ return PHPUiImages.get(PHPUiImages.IMG_VAR);
+ case PHPIdentifierLocation.GLOBAL_VARIABLE:
+ return PHPUiImages.get(PHPUiImages.IMG_VAR);
+ }
+ return PHPUiImages.get(PHPUiImages.IMG_FUN);
+ }
+
+ /*
+ * @see IJavaCompletionProposal#getRelevance()
+ */
+ public int getRelevance() {
+
+ if (fContext instanceof JavaContext) {
+ JavaContext context = (JavaContext) fContext;
+ switch (context.getCharacterBeforeStart()) {
+ // high relevance after whitespace
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ return 80;
+ case '>': // ->
+ case ':': // ::
+ return 85;
+ default:
+ return 0;
+ }
+ } else {
+ return 80;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/IdentifierEngine.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/IdentifierEngine.java
new file mode 100644
index 0000000..58d82e9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/IdentifierEngine.java
@@ -0,0 +1,122 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContextType;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContextType;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.swt.graphics.Point;
+
+public class IdentifierEngine {
+
+ /** The context type. */
+ private JavaContextType fContextType;
+
+ /** The result proposals. */
+ private ArrayList fProposals = new ArrayList();
+
+ /**
+ * Creates the template engine for a particular context type. See
+ * TemplateContext
for supported context types.
+ */
+ public IdentifierEngine(JavaContextType contextType) {
+ // Assert.isNotNull(contextType);
+ fContextType = contextType;
+ }
+
+ /**
+ * Empties the collector.
+ *
+ * @param viewer
+ * the text viewer
+ * @param unit
+ * the compilation unit (may be null
)
+ */
+ public void reset() {
+ fProposals.clear();
+ }
+
+ /**
+ * Returns the array of matching templates.
+ */
+ public IPHPCompletionProposal[] getResults() {
+ return (IPHPCompletionProposal[]) fProposals
+ .toArray(new IPHPCompletionProposal[fProposals.size()]);
+ }
+
+ /**
+ * Inspects the context of the compilation unit around
+ * completionPosition
and feeds the collector with proposals.
+ *
+ * @param viewer
+ * the text viewer
+ * @param completionPosition
+ * the context position in the document of the text viewer
+ * @param compilationUnit
+ * the compilation unit (may be null
)
+ */
+ public void complete(ITextViewer viewer, int completionPosition,
+ Object[] identifiers, ICompilationUnit compilationUnit)
+ // hrows JavaModelException
+ {
+ IDocument document = viewer.getDocument();
+
+ if (!(fContextType instanceof CompilationUnitContextType))
+ return;
+
+ Point selection = viewer.getSelectedRange();
+ // remember selected text
+ String selectedText = null;
+ if (selection.y != 0) {
+ try {
+ selectedText = document.get(selection.x, selection.y);
+ } catch (BadLocationException e) {
+ }
+ }
+
+ // ((CompilationUnitContextType)
+ // fContextType).setContextParameters(document, completionPosition,
+ // selection.y); //mpilationUnit);
+
+ // JavaContext context = (JavaContext) fContextType.createContext();
+ JavaContext context = (JavaContext) fContextType.createContext(
+ document, completionPosition, selection.y, compilationUnit);
+ context.setVariable("selection", selectedText); //$NON-NLS-1$
+
+ int start = context.getStart();
+ int end = context.getEnd();
+ IRegion region = new Region(start, end - start);
+
+ // Template[] templates= Templates.getInstance().getTemplates();
+ String identifier = null;
+ int maxProposals = WebUI.MAX_PROPOSALS;
+
+ for (int i = 0; i != identifiers.length; i++) {
+ identifier = (String) identifiers[i];
+ if (context.canEvaluate(identifier)) {
+ if (maxProposals-- < 0) {
+ return;
+ }
+ fProposals.add(new IdentifierProposal(identifier, context,
+ region, viewer, PHPUiImages.get(PHPUiImages.IMG_FUN),
+ PHPUiImages.get(PHPUiImages.IMG_VAR)));
+ }
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/IdentifierProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/IdentifierProposal.java
new file mode 100644
index 0000000..3f27aad
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/IdentifierProposal.java
@@ -0,0 +1,94 @@
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * A PHP identifier proposal.
+ */
+public class IdentifierProposal extends AbstractProposal {
+ private final TemplateContext fContext;
+
+ private final Image fImage_fun;
+
+ private final Image fImage_var;
+
+ private final IRegion fRegion;
+
+ private final String fTemplate;
+
+ public IdentifierProposal(String template, TemplateContext context,
+ IRegion region, ITextViewer viewer, Image image_fun, Image image_var) {
+ super(viewer);
+ fTemplate = template;
+ fContext = context;
+
+ fImage_fun = image_fun;
+ fImage_var = image_var;
+ fRegion = region;
+ }
+
+ public void apply(IDocument document) {
+ try {
+ int start = fRegion.getOffset();
+ int end = fRegion.getOffset() + fRegion.getLength();
+ document.replace(start, end - start, fTemplate);
+ // translate positions
+ LinkedPositionManager manager = new LinkedPositionManager(document);
+
+ LinkedPositionUI editor = new LinkedPositionUI(fViewer, manager);
+ editor.setFinalCaretOffset(fTemplate.length() + start);
+ editor.enter();
+ fSelectedRegion = editor.getSelectedRegion();
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ openErrorDialog(e);
+ }
+ }
+
+ public String getAdditionalProposalInfo() {
+ return textToHTML(fTemplate);
+ }
+
+ public String getDisplayString() {
+ return fTemplate
+ + TemplateMessages.getString("TemplateProposal.delimiter")
+ + fTemplate; // $NON-NLS-1$
+ }
+
+ public Image getImage() {
+ if (fTemplate.charAt(0) == '$') {
+ return fImage_var;
+ }
+ return fImage_fun;
+ }
+
+ public int getRelevance() {
+ if (fContext instanceof JavaContext) {
+ JavaContext context = (JavaContext) fContext;
+ switch (context.getCharacterBeforeStart()) {
+ // high relevance after whitespace
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ return 50;
+ default:
+ return 0;
+ }
+ } else {
+ return 50;
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/LocalVariableProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/LocalVariableProposal.java
new file mode 100644
index 0000000..0d67c8a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/LocalVariableProposal.java
@@ -0,0 +1,144 @@
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * A PHP local identifier proposal.
+ */
+public class LocalVariableProposal extends AbstractProposal {
+
+ private final String fIdentifierName;
+
+ private final IRegion fRegion;
+
+ private final int fRelevance;
+
+ /**
+ * Creates a template proposal with a template and its context.
+ *
+ * @param template
+ * the template
+ * @param image
+ * the icon of the proposal.
+ */
+ public LocalVariableProposal(String identifierName, IRegion region,
+ ITextViewer viewer) {
+ this(identifierName, region, viewer, 99);
+ }
+
+ public LocalVariableProposal(String identifierName, IRegion region,
+ ITextViewer viewer, int relevance) {
+ super(viewer);
+ fIdentifierName = identifierName;
+ fRegion = region;
+ fRelevance = relevance;
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public void apply(IDocument document) {
+ try {
+ // if (fTemplateBuffer == null)
+ // fTemplateBuffer= fContext.evaluate(fTemplate);
+
+ int start = fRegion.getOffset();
+ int end = fRegion.getOffset() + fRegion.getLength();
+
+ document.replace(start, end - start, fIdentifierName);
+
+ // translate positions
+ LinkedPositionManager manager = new LinkedPositionManager(document);
+
+ LinkedPositionUI editor = new LinkedPositionUI(fViewer, manager);
+ editor.setFinalCaretOffset(fIdentifierName.length() + start);
+ editor.enter();
+
+ fSelectedRegion = editor.getSelectedRegion();
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ openErrorDialog(e);
+
+ }
+ // catch (CoreException e) {
+ // handleException(e);
+ // }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof LocalVariableProposal) {
+ return fIdentifierName
+ .equals(((LocalVariableProposal) obj).fIdentifierName);
+ }
+ return false;
+ }
+
+ /*
+ * @see ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ StringBuffer hoverInfoBuffer = new StringBuffer();
+ if (fRelevance > 95) {
+ hoverInfoBuffer.append("function source variable -");
+ } else {
+ hoverInfoBuffer.append("editor source variable -");
+ }
+ hoverInfoBuffer.append(fIdentifierName);
+ return hoverInfoBuffer.toString();
+ }
+
+ /*
+ * @see ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * @see ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return fIdentifierName; // $NON-NLS-1$ //$NON-NLS-1$
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return PHPUiImages.get(PHPUiImages.IMG_VAR);
+ }
+
+ /*
+ * @see IJavaCompletionProposal#getRelevance()
+ */
+ public int getRelevance() {
+ return fRelevance;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return fIdentifierName.hashCode();
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/SQLProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/SQLProposal.java
new file mode 100644
index 0000000..a7af0d6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/SQLProposal.java
@@ -0,0 +1,142 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * A PHP identifier proposal.
+ */
+public class SQLProposal extends AbstractProposal {
+ private final TemplateContext fContext;
+
+ private final Image fImage_var;
+
+ private final IRegion fRegion;
+
+ private final String fColumnName;
+
+ private final String fTableName;
+
+ private int fRelevance;
+
+ /**
+ * Creates a template proposal with a template and its context.
+ *
+ * @param template
+ * the template
+ * @param context
+ * the context in which the template was requested.
+ * @param image
+ * the icon of the proposal.
+ */
+ public SQLProposal(String tableName, TemplateContext context,
+ IRegion region, ITextViewer viewer, Image image_var) {
+ super(viewer);
+ fTableName = tableName;
+ fColumnName = null;
+ fContext = context;
+ fImage_var = image_var;
+ fRegion = region;
+ fRelevance = 0;
+ }
+
+ public SQLProposal(String tableName, String columnName,
+ TemplateContext context, IRegion region, ITextViewer viewer,
+ Image image_var) {
+ super(viewer);
+ fTableName = tableName;
+ fColumnName = columnName;
+ fContext = context;
+ fImage_var = image_var;
+ fRegion = region;
+ fRelevance = 0;
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public void apply(IDocument document) {
+ try {
+ int start = fRegion.getOffset();
+ int end = fRegion.getOffset() + fRegion.getLength();
+ String resultString = fTableName;
+ if (fColumnName != null) {
+ resultString = fColumnName;
+ }
+ // insert template string
+ document.replace(start, end - start, resultString);
+ // translate positions
+ LinkedPositionManager manager = new LinkedPositionManager(document);
+ LinkedPositionUI editor = new LinkedPositionUI(fViewer, manager);
+ editor.setFinalCaretOffset(resultString.length() + start);
+ editor.enter();
+ fSelectedRegion = editor.getSelectedRegion();
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ openErrorDialog(e);
+ }
+ }
+
+ /*
+ * @see ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ if (fColumnName == null) {
+ return textToHTML(fTableName);
+ }
+ return fColumnName + " (Table: " + fTableName + ")";
+ }
+
+ /*
+ * @see ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * @see ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ if (fColumnName == null) {
+ return fTableName;
+ }
+ return fColumnName + " (Table: " + fTableName + ")"; // $NON-NLS-1$
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return fImage_var;
+ }
+
+ /*
+ * @see IJavaCompletionProposal#getRelevance()
+ */
+ public int getRelevance() {
+ return fRelevance;
+ }
+
+ /**
+ * @param relevance
+ * The relevance to set.
+ */
+ public void setRelevance(int relevance) {
+ fRelevance = relevance;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/InclusivePositionUpdater.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/InclusivePositionUpdater.java
new file mode 100644
index 0000000..dcd7b5f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/InclusivePositionUpdater.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.Position;
+
+/**
+ * Position updater that takes any change in [position.offset, position.offset +
+ * position.length] as belonging to the position.
+ *
+ * @since 3.0
+ */
+class InclusivePositionUpdater implements IPositionUpdater {
+
+ /** The position category. */
+ private final String fCategory;
+
+ /**
+ * Creates a new updater for the given category
.
+ *
+ * @param category
+ * the new category.
+ */
+ public InclusivePositionUpdater(String category) {
+ fCategory = category;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IPositionUpdater#update(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void update(DocumentEvent event) {
+
+ int eventOffset = event.getOffset();
+ int eventOldLength = event.getLength();
+ int eventNewLength = event.getText() == null ? 0 : event.getText()
+ .length();
+ int deltaLength = eventNewLength - eventOldLength;
+
+ try {
+ Position[] positions = event.getDocument().getPositions(fCategory);
+
+ for (int i = 0; i != positions.length; i++) {
+
+ Position position = positions[i];
+
+ if (position.isDeleted())
+ continue;
+
+ int offset = position.getOffset();
+ int length = position.getLength();
+ int end = offset + length;
+
+ if (offset > eventOffset + eventOldLength)
+ // position comes way
+ // after change - shift
+ position.setOffset(offset + deltaLength);
+ else if (end < eventOffset) {
+ // position comes way before change -
+ // leave alone
+ } else if (offset <= eventOffset
+ && end >= eventOffset + eventOldLength) {
+ // event completely internal to the position - adjust length
+ position.setLength(length + deltaLength);
+ } else if (offset < eventOffset) {
+ // event extends over end of position - adjust length
+ int newEnd = eventOffset + eventNewLength;
+ position.setLength(newEnd - offset);
+ } else if (end > eventOffset + eventOldLength) {
+ // event extends from before position into it - adjust
+ // offset
+ // and length
+ // offset becomes end of event, length ajusted acordingly
+ // we want to recycle the overlapping part
+ position.setOffset(eventOffset);
+ int deleted = eventOffset + eventOldLength - offset;
+ position.setLength(length - deleted + eventNewLength);
+ } else {
+ // event consumes the position - delete it
+ position.delete();
+ }
+ }
+ } catch (BadPositionCategoryException e) {
+ // ignore and return
+ }
+ }
+
+ /**
+ * Returns the position category.
+ *
+ * @return the position category
+ */
+ public String getCategory() {
+ return fCategory;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/MultiVariable.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/MultiVariable.java
new file mode 100644
index 0000000..4ed0899
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/MultiVariable.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.templates.TemplateVariable;
+
+/**
+ *
+ */
+public class MultiVariable extends TemplateVariable {
+ private final Map fValueMap = new HashMap();
+
+ private Object fSet;
+
+ private Object fDefaultKey = null;
+
+ public MultiVariable(String type, String defaultValue, int[] offsets) {
+ super(type, defaultValue, offsets);
+ fValueMap.put(fDefaultKey, new String[] { defaultValue });
+ fSet = getDefaultValue();
+ }
+
+ /**
+ * Sets the values of this variable under a specific set.
+ *
+ * @param set
+ * the set identifier for which the values are valid
+ * @param values
+ * the possible values of this variable
+ */
+ public void setValues(Object set, String[] values) {
+ Assert.isNotNull(set);
+ Assert.isTrue(values.length > 0);
+ fValueMap.put(set, values);
+ if (fDefaultKey == null) {
+ fDefaultKey = set;
+ fSet = getDefaultValue();
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.templates.TemplateVariable#setValues(java.lang.String[])
+ */
+ public void setValues(String[] values) {
+ if (fValueMap != null) {
+ Assert.isNotNull(values);
+ Assert.isTrue(values.length > 0);
+ fValueMap.put(fDefaultKey, values);
+ fSet = getDefaultValue();
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.templates.TemplateVariable#getValues()
+ */
+ public String[] getValues() {
+ return (String[]) fValueMap.get(fDefaultKey);
+ }
+
+ /**
+ * Returns the choices for the set identified by set
.
+ *
+ * @param set
+ * the set identifier
+ * @return the choices for this variable and the given set, or
+ * null
if the set is not defined.
+ */
+ public String[] getValues(Object set) {
+ return (String[]) fValueMap.get(set);
+ }
+
+ /**
+ * @return
+ */
+ public Object getSet() {
+ return fSet;
+ }
+
+ public void setSet(Object set) {
+ fSet = set;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/MultiVariableGuess.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/MultiVariableGuess.java
new file mode 100644
index 0000000..1f0ebc2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/MultiVariableGuess.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+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.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Global state for templates. Selecting a proposal for the master template
+ * variable will cause the value (and the proposals) for the slave variables to
+ * change.
+ *
+ * @see MultiVariable
+ */
+public class MultiVariableGuess {
+
+ /**
+ * Implementation of the ICompletionProposal
interface and
+ * extension.
+ */
+ class Proposal implements ICompletionProposal,
+ ICompletionProposalExtension2 {
+
+ /** The string to be displayed in the completion proposal popup */
+ private String fDisplayString;
+
+ /** The replacement string */
+ String fReplacementString;
+
+ /** The replacement offset */
+ private int fReplacementOffset;
+
+ /** The replacement length */
+ private int fReplacementLength;
+
+ /** The cursor position after this proposal has been applied */
+ private int fCursorPosition;
+
+ /** The image to be displayed in the completion proposal popup */
+ private Image fImage;
+
+ /** The context information of this proposal */
+ private IContextInformation fContextInformation;
+
+ /** The additional info of this proposal */
+ private String fAdditionalProposalInfo;
+
+ /**
+ * Creates a new completion proposal based on the provided information.
+ * The replacement string is considered being the display string too.
+ * All remaining fields are set to null
.
+ *
+ * @param replacementString
+ * the actual string to be inserted into the document
+ * @param replacementOffset
+ * the offset of the text to be replaced
+ * @param replacementLength
+ * the length of the text to be replaced
+ * @param cursorPosition
+ * the position of the cursor following the insert relative
+ * to replacementOffset
+ */
+ public Proposal(String replacementString, int replacementOffset,
+ int replacementLength, int cursorPosition) {
+ this(replacementString, replacementOffset, replacementLength,
+ cursorPosition, null, null, null, null);
+ }
+
+ /**
+ * Creates a new completion proposal. All fields are initialized based
+ * on the provided information.
+ *
+ * @param replacementString
+ * the actual string to be inserted into the document
+ * @param replacementOffset
+ * the offset of the text to be replaced
+ * @param replacementLength
+ * the length of the text to be replaced
+ * @param cursorPosition
+ * the position of the cursor following the insert relative
+ * to replacementOffset
+ * @param image
+ * the image to display for this proposal
+ * @param displayString
+ * the string to be displayed for the proposal
+ * @param contextInformation
+ * the context information associated with this proposal
+ * @param additionalProposalInfo
+ * the additional information associated with this proposal
+ */
+ public Proposal(String replacementString, int replacementOffset,
+ int replacementLength, int cursorPosition, Image image,
+ String displayString, IContextInformation contextInformation,
+ String additionalProposalInfo) {
+ Assert.isNotNull(replacementString);
+ Assert.isTrue(replacementOffset >= 0);
+ Assert.isTrue(replacementLength >= 0);
+ Assert.isTrue(cursorPosition >= 0);
+
+ fReplacementString = replacementString;
+ fReplacementOffset = replacementOffset;
+ fReplacementLength = replacementLength;
+ fCursorPosition = cursorPosition;
+ fImage = image;
+ fDisplayString = displayString;
+ fContextInformation = contextInformation;
+ fAdditionalProposalInfo = additionalProposalInfo;
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public void apply(IDocument document) {
+ try {
+ document.replace(fReplacementOffset, fReplacementLength,
+ fReplacementString);
+ } catch (BadLocationException x) {
+ // ignore
+ }
+ }
+
+ /*
+ * @see ICompletionProposal#getSelection(IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return new Point(fReplacementOffset + fCursorPosition, 0);
+ }
+
+ /*
+ * @see ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return fContextInformation;
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return fImage;
+ }
+
+ /*
+ * @see ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ if (fDisplayString != null)
+ return fDisplayString;
+ return fReplacementString;
+ }
+
+ /*
+ * @see ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return fAdditionalProposalInfo;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+ * char, int, int)
+ */
+ public void apply(ITextViewer viewer, char trigger, int stateMask,
+ int offset) {
+ apply(viewer.getDocument());
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+ * boolean)
+ */
+ public void selected(ITextViewer viewer, boolean smartToggle) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+ */
+ public void unselected(ITextViewer viewer) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+ * int, org.eclipse.jface.text.DocumentEvent)
+ */
+ public boolean validate(IDocument document, int offset,
+ DocumentEvent event) {
+ try {
+ String content = document.get(fReplacementOffset,
+ fReplacementLength);
+ if (content.startsWith(fReplacementString))
+ return true;
+ } catch (BadLocationException e) {
+ // ignore concurrently modified document
+ }
+ return false;
+ }
+ }
+
+ private final List fSlaves = new ArrayList();
+
+ private MultiVariable fMaster;
+
+ /**
+ * @param mv
+ */
+ public MultiVariableGuess(MultiVariable mv) {
+ fMaster = mv;
+ }
+
+ /**
+ * @param variable
+ * @return
+ */
+ public ICompletionProposal[] getProposals(MultiVariable variable,
+ int offset, int length) {
+ if (variable.equals(fMaster)) {
+ String[] choices = variable.getValues();
+
+ ICompletionProposal[] ret = new ICompletionProposal[choices.length];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = new Proposal(choices[i], offset, length, offset
+ + length) {
+
+ /*
+ * @see org.eclipse.jface.text.link.MultiVariableGuess.Proposal#apply(org.eclipse.jface.text.IDocument)
+ */
+ public void apply(IDocument document) {
+ super.apply(document);
+
+ try {
+ Object old = fMaster.getSet();
+ fMaster.setSet(fReplacementString);
+ if (!fReplacementString.equals(old)) {
+ for (Iterator it = fSlaves.iterator(); it
+ .hasNext();) {
+ VariablePosition pos = (VariablePosition) it
+ .next();
+ String[] values = pos.getVariable()
+ .getValues(fReplacementString);
+ if (values != null)
+ document.replace(pos.getOffset(), pos
+ .getLength(), values[0]);
+ }
+ }
+ } catch (BadLocationException e) {
+ // ignore and continue
+ }
+
+ }
+ };
+ }
+
+ return ret;
+
+ } else {
+
+ String[] choices = variable.getValues(fMaster.getSet());
+
+ if (choices == null || choices.length < 2)
+ return null;
+
+ ICompletionProposal[] ret = new ICompletionProposal[choices.length];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = new Proposal(choices[i], offset, length, offset
+ + length);
+ }
+
+ return ret;
+ }
+ }
+
+ /**
+ * @param position
+ */
+ public void addSlave(VariablePosition position) {
+ fSlaves.add(position);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/PositionBasedCompletionProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/PositionBasedCompletionProposal.java
new file mode 100644
index 0000000..b2396fb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/PositionBasedCompletionProposal.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * An enhanced implementation of the ICompletionProposal
+ * interface implementing all the extension interfaces. It uses a position to
+ * track its replacement offset and length. The position must be set up
+ * externally.
+ */
+public class PositionBasedCompletionProposal implements ICompletionProposal,
+ ICompletionProposalExtension, ICompletionProposalExtension2 {
+
+ /** The string to be displayed in the completion proposal popup */
+ private String fDisplayString;
+
+ /** The replacement string */
+ private String fReplacementString;
+
+ /** The replacement position. */
+ private Position fReplacementPosition;
+
+ /** The cursor position after this proposal has been applied */
+ private int fCursorPosition;
+
+ /** The image to be displayed in the completion proposal popup */
+ private Image fImage;
+
+ /** The context information of this proposal */
+ private IContextInformation fContextInformation;
+
+ /** The additional info of this proposal */
+ private String fAdditionalProposalInfo;
+
+ /**
+ * Creates a new completion proposal based on the provided information. The
+ * replacement string is considered being the display string too. All
+ * remaining fields are set to null
.
+ *
+ * @param replacementString
+ * the actual string to be inserted into the document
+ * @param replacementPosition
+ * the position of the text to be replaced
+ * @param cursorPosition
+ * the position of the cursor following the insert relative to
+ * replacementOffset
+ */
+ public PositionBasedCompletionProposal(String replacementString,
+ Position replacementPosition, int cursorPosition) {
+ this(replacementString, replacementPosition, cursorPosition, null,
+ null, null, null);
+ }
+
+ /**
+ * Creates a new completion proposal. All fields are initialized based on
+ * the provided information.
+ *
+ * @param replacementString
+ * the actual string to be inserted into the document
+ * @param replacementPosition
+ * the position of the text to be replaced
+ * @param cursorPosition
+ * the position of the cursor following the insert relative to
+ * replacementOffset
+ * @param image
+ * the image to display for this proposal
+ * @param displayString
+ * the string to be displayed for the proposal
+ * @param contextInformation
+ * the context information associated with this proposal
+ * @param additionalProposalInfo
+ * the additional information associated with this proposal
+ */
+ public PositionBasedCompletionProposal(String replacementString,
+ Position replacementPosition, int cursorPosition, Image image,
+ String displayString, IContextInformation contextInformation,
+ String additionalProposalInfo) {
+ Assert.isNotNull(replacementString);
+ Assert.isTrue(replacementPosition != null);
+
+ fReplacementString = replacementString;
+ fReplacementPosition = replacementPosition;
+ fCursorPosition = cursorPosition;
+ fImage = image;
+ fDisplayString = displayString;
+ fContextInformation = contextInformation;
+ fAdditionalProposalInfo = additionalProposalInfo;
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public void apply(IDocument document) {
+ try {
+ document.replace(fReplacementPosition.getOffset(),
+ fReplacementPosition.getLength(), fReplacementString);
+ } catch (BadLocationException x) {
+ // ignore
+ }
+ }
+
+ /*
+ * @see ICompletionProposal#getSelection(IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return new Point(fReplacementPosition.getOffset() + fCursorPosition, 0);
+ }
+
+ /*
+ * @see ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return fContextInformation;
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return fImage;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ if (fDisplayString != null)
+ return fDisplayString;
+ return fReplacementString;
+ }
+
+ /*
+ * @see ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return fAdditionalProposalInfo;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+ * char, int, int)
+ */
+ public void apply(ITextViewer viewer, char trigger, int stateMask,
+ int offset) {
+ apply(viewer.getDocument());
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+ * boolean)
+ */
+ public void selected(ITextViewer viewer, boolean smartToggle) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+ */
+ public void unselected(ITextViewer viewer) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+ * int, org.eclipse.jface.text.DocumentEvent)
+ */
+ public boolean validate(IDocument document, int offset, DocumentEvent event) {
+ try {
+ String content = document.get(fReplacementPosition.getOffset(),
+ fReplacementPosition.getLength());
+ if (content.startsWith(fReplacementString))
+ return true;
+ } catch (BadLocationException e) {
+ // ignore concurrently modified document
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#apply(org.eclipse.jface.text.IDocument,
+ * char, int)
+ */
+ public void apply(IDocument document, char trigger, int offset) {
+ // not called any more
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#isValidFor(org.eclipse.jface.text.IDocument,
+ * int)
+ */
+ public boolean isValidFor(IDocument document, int offset) {
+ // not called any more
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#getTriggerCharacters()
+ */
+ public char[] getTriggerCharacters() {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#getContextInformationPosition()
+ */
+ public int getContextInformationPosition() {
+ return fReplacementPosition.getOffset();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateContentAssistMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateContentAssistMessages.java
new file mode 100644
index 0000000..c675e0a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateContentAssistMessages.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+class TemplateContentAssistMessages {
+
+ private static final String RESOURCE_BUNDLE = TemplateContentAssistMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private TemplateContentAssistMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateContentAssistMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateContentAssistMessages.properties
new file mode 100644
index 0000000..3664fd8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateContentAssistMessages.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2000, 2004 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+# template proposal
+TemplateProposal.delimiter=\ -
+
+# template evaluator
+TemplateEvaluator.error.title=Template Evaluation Error
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateEngine.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateEngine.java
new file mode 100644
index 0000000..7d6d35d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateEngine.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.internal.corext.Assert;
+import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContext;
+import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContextType;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.swt.graphics.Point;
+
+public class TemplateEngine {
+
+ private static final String $_LINE_SELECTION = "${" + GlobalTemplateVariables.LineSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final String $_WORD_SELECTION = "${" + GlobalTemplateVariables.WordSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ /** The context type. */
+ private TemplateContextType fContextType;
+
+ /** The result proposals. */
+ private ArrayList fProposals = new ArrayList();
+
+ /**
+ * Creates the template engine for a particular context type. See
+ * TemplateContext
for supported context types.
+ */
+ public TemplateEngine(TemplateContextType contextType) {
+ Assert.isNotNull(contextType);
+ fContextType = contextType;
+ }
+
+ /**
+ * Empties the collector.
+ */
+ public void reset() {
+ fProposals.clear();
+ }
+
+ /**
+ * Returns the array of matching templates.
+ */
+ public TemplateProposal[] getResults() {
+ return (TemplateProposal[]) fProposals
+ .toArray(new TemplateProposal[fProposals.size()]);
+ }
+
+ /**
+ * Inspects the context of the compilation unit around
+ * completionPosition
and feeds the collector with proposals.
+ *
+ * @param viewer
+ * the text viewer
+ * @param completionPosition
+ * the context position in the document of the text viewer
+ * @param compilationUnit
+ * the compilation unit (may be null
)
+ */
+ public void complete(ITextViewer viewer, int completionPosition,
+ ICompilationUnit compilationUnit) {
+ IDocument document = viewer.getDocument();
+
+ if (!(fContextType instanceof CompilationUnitContextType))
+ return;
+
+ Point selection = viewer.getSelectedRange();
+
+ // remember selected text
+ String selectedText = null;
+ if (selection.y != 0) {
+ try {
+ selectedText = document.get(selection.x, selection.y);
+ } catch (BadLocationException e) {
+ }
+ }
+
+ CompilationUnitContext context = ((CompilationUnitContextType) fContextType)
+ .createContext(document, completionPosition, selection.y,
+ compilationUnit);
+ context.setVariable("selection", selectedText); //$NON-NLS-1$
+ int start = context.getStart();
+ int end = context.getEnd();
+ IRegion region = new Region(start, end - start);
+
+ Template[] templates = WebUI.getDefault().getTemplateStore()
+ .getTemplates();
+
+ if (selection.y == 0) {
+ for (int i = 0; i != templates.length; i++)
+ if (context.canEvaluate(templates[i]))
+ fProposals.add(new TemplateProposal(templates[i], context,
+ region, PHPUiImages
+ .get(PHPUiImages.IMG_OBJS_TEMPLATE)));
+
+ } else {
+
+ if (context.getKey().length() == 0)
+ context.setForceEvaluation(true);
+
+ boolean multipleLinesSelected = areMultipleLinesSelected(viewer);
+
+ for (int i = 0; i != templates.length; i++) {
+ Template template = templates[i];
+ if (context.canEvaluate(template)
+ && template.getContextTypeId().equals(
+ context.getContextType().getId())
+ && (!multipleLinesSelected
+ && template.getPattern().indexOf(
+ $_WORD_SELECTION) != -1 || (multipleLinesSelected && template
+ .getPattern().indexOf($_LINE_SELECTION) != -1))) {
+ fProposals.add(new TemplateProposal(templates[i], context,
+ region, PHPUiImages
+ .get(PHPUiImages.IMG_OBJS_TEMPLATE)));
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true
if one line is completely selected or if
+ * multiple lines are selected. Being completely selected means that all
+ * characters except the new line characters are selected.
+ *
+ * @return true
if one or multiple lines are selected
+ * @since 2.1
+ */
+ private boolean areMultipleLinesSelected(ITextViewer viewer) {
+ if (viewer == null)
+ return false;
+
+ Point s = viewer.getSelectedRange();
+ if (s.y == 0)
+ return false;
+
+ try {
+
+ IDocument document = viewer.getDocument();
+ int startLine = document.getLineOfOffset(s.x);
+ int endLine = document.getLineOfOffset(s.x + s.y);
+ IRegion line = document.getLineInformation(startLine);
+ return startLine != endLine
+ || (s.x == line.getOffset() && s.y == line.getLength());
+
+ } catch (BadLocationException x) {
+ return false;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateInformationControlCreator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateInformationControlCreator.java
new file mode 100644
index 0000000..522ac13
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateInformationControlCreator.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import net.sourceforge.phpdt.internal.ui.text.java.hover.SourceViewerInformationControl;
+
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IInformationControlCreatorExtension;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Shell;
+
+final public class TemplateInformationControlCreator implements
+ IInformationControlCreator, IInformationControlCreatorExtension {
+
+ private SourceViewerInformationControl fControl;
+
+ public TemplateInformationControlCreator() {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
+ */
+ public IInformationControl createInformationControl(Shell parent) {
+ fControl = new SourceViewerInformationControl(parent);
+ fControl.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ fControl = null;
+ }
+ });
+ return fControl;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReuse(org.eclipse.jface.text.IInformationControl)
+ */
+ public boolean canReuse(IInformationControl control) {
+ return fControl == control && fControl != null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReplace(org.eclipse.jface.text.IInformationControlCreator)
+ */
+ public boolean canReplace(IInformationControlCreator creator) {
+ return (creator != null && getClass() == creator.getClass());
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateProposal.java
new file mode 100644
index 0000000..01366dd
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/TemplateProposal.java
@@ -0,0 +1,477 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContext;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.EditorHighlightingSynchronizer;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension3;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.link.ILinkedModeListener;
+import org.eclipse.jface.text.link.LinkedModeModel;
+import org.eclipse.jface.text.link.LinkedModeUI;
+import org.eclipse.jface.text.link.LinkedPosition;
+import org.eclipse.jface.text.link.LinkedPositionGroup;
+import org.eclipse.jface.text.link.ProposalPosition;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+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.TemplateVariable;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
+
+/**
+ * A template proposal.
+ */
+public class TemplateProposal implements IPHPCompletionProposal,
+ ICompletionProposalExtension2, ICompletionProposalExtension3 {
+
+ private final Template fTemplate;
+
+ private final TemplateContext fContext;
+
+ private final Image fImage;
+
+ private IRegion fRegion;
+
+ private int fRelevance;
+
+ private IRegion fSelectedRegion; // initialized by apply()
+
+ private String fDisplayString;
+
+ /**
+ * Creates a template proposal with a template and its context.
+ *
+ * @param template
+ * the template
+ * @param context
+ * the context in which the template was requested
+ * @param region
+ * the region this proposal applies to
+ * @param image
+ * the icon of the proposal
+ */
+ public TemplateProposal(Template template, TemplateContext context,
+ IRegion region, Image image) {
+ Assert.isNotNull(template);
+ Assert.isNotNull(context);
+ Assert.isNotNull(region);
+
+ fTemplate = template;
+ fContext = context;
+ fImage = image;
+ fRegion = region;
+
+ fDisplayString = null;
+
+ if (context instanceof JavaContext) {
+ switch (((JavaContext) context).getCharacterBeforeStart()) {
+ // high relevance after whitespace
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ fRelevance = 90;
+ break;
+ default:
+ fRelevance = 0;
+ }
+ } else {
+ fRelevance = 90;
+ }
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public final void apply(IDocument document) {
+ // not called anymore
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+ * char, int, int)
+ */
+ public void apply(ITextViewer viewer, char trigger, int stateMask,
+ int offset) {
+
+ try {
+
+ fContext.setReadOnly(false);
+ TemplateBuffer templateBuffer;
+ try {
+ templateBuffer = fContext.evaluate(fTemplate);
+ } catch (TemplateException e1) {
+ fSelectedRegion = fRegion;
+ return;
+ }
+
+ int start = getReplaceOffset();
+ int end = getReplaceEndOffset();
+ end = Math.max(end, offset);
+
+ // insert template string
+ IDocument document = viewer.getDocument();
+ String templateString = templateBuffer.getString();
+ document.replace(start, end - start, templateString);
+
+ // translate positions
+ LinkedModeModel model = new LinkedModeModel();
+ TemplateVariable[] variables = templateBuffer.getVariables();
+
+ MultiVariableGuess guess = fContext instanceof CompilationUnitContext ? ((CompilationUnitContext) fContext)
+ .getMultiVariableGuess()
+ : null;
+
+ boolean hasPositions = false;
+ for (int i = 0; i != variables.length; i++) {
+ TemplateVariable variable = variables[i];
+
+ if (variable.isUnambiguous())
+ continue;
+
+ LinkedPositionGroup group = new LinkedPositionGroup();
+
+ int[] offsets = variable.getOffsets();
+ int length = variable.getLength();
+
+ LinkedPosition first;
+ if (guess != null && variable instanceof MultiVariable) {
+ first = new VariablePosition(document, offsets[0] + start,
+ length, guess, (MultiVariable) variable);
+ guess.addSlave((VariablePosition) first);
+ } else {
+ String[] values = variable.getValues();
+ ICompletionProposal[] proposals = new ICompletionProposal[values.length];
+ for (int j = 0; j < values.length; j++) {
+ ensurePositionCategoryInstalled(document, model);
+ Position pos = new Position(offsets[0] + start, length);
+ document.addPosition(getCategory(), pos);
+ proposals[j] = new PositionBasedCompletionProposal(
+ values[j], pos, length);
+ }
+
+ if (proposals.length > 1)
+ first = new ProposalPosition(document, offsets[0]
+ + start, length, proposals);
+ else
+ first = new LinkedPosition(document,
+ offsets[0] + start, length);
+ }
+
+ for (int j = 0; j != offsets.length; j++)
+ if (j == 0)
+ group.addPosition(first);
+ else
+ group.addPosition(new LinkedPosition(document,
+ offsets[j] + start, length));
+
+ model.addGroup(group);
+ hasPositions = true;
+ }
+
+ if (hasPositions) {
+ model.forceInstall();
+ PHPEditor editor = getJavaEditor();
+ if (editor != null) {
+ model
+ .addLinkingListener(new EditorHighlightingSynchronizer(
+ editor));
+ }
+
+ LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
+ ui.setExitPosition(viewer, getCaretOffset(templateBuffer)
+ + start, 0, Integer.MAX_VALUE);
+ ui.enter();
+
+ fSelectedRegion = ui.getSelectedRegion();
+ } else
+ fSelectedRegion = new Region(getCaretOffset(templateBuffer)
+ + start, 0);
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+ openErrorDialog(viewer.getTextWidget().getShell(), e);
+ fSelectedRegion = fRegion;
+ } catch (BadPositionCategoryException e) {
+ WebUI.log(e);
+ openErrorDialog(viewer.getTextWidget().getShell(), e);
+ fSelectedRegion = fRegion;
+ }
+
+ }
+
+ /**
+ * Returns the currently active java editor, or null
if it
+ * cannot be determined.
+ *
+ * @return the currently active java editor, or null
+ */
+ private PHPEditor getJavaEditor() {
+ IEditorPart part = WebUI.getActivePage().getActiveEditor();
+ if (part instanceof PHPEditor)
+ return (PHPEditor) part;
+ else
+ return null;
+ }
+
+ /**
+ * Returns the offset of the range in the document that will be replaced by
+ * applying this template.
+ *
+ * @return the offset of the range in the document that will be replaced by
+ * applying this template
+ */
+ private int getReplaceOffset() {
+ int start;
+ if (fContext instanceof DocumentTemplateContext) {
+ DocumentTemplateContext docContext = (DocumentTemplateContext) fContext;
+ start = docContext.getStart();
+ } else {
+ start = fRegion.getOffset();
+ }
+ return start;
+ }
+
+ /**
+ * Returns the end offset of the range in the document that will be replaced
+ * by applying this template.
+ *
+ * @return the end offset of the range in the document that will be replaced
+ * by applying this template
+ */
+ private int getReplaceEndOffset() {
+ int end;
+ if (fContext instanceof DocumentTemplateContext) {
+ DocumentTemplateContext docContext = (DocumentTemplateContext) fContext;
+ end = docContext.getEnd();
+ } else {
+ end = fRegion.getOffset() + fRegion.getLength();
+ }
+ return end;
+ }
+
+ private void ensurePositionCategoryInstalled(final IDocument document,
+ LinkedModeModel model) {
+ if (!document.containsPositionCategory(getCategory())) {
+ document.addPositionCategory(getCategory());
+ final InclusivePositionUpdater updater = new InclusivePositionUpdater(
+ getCategory());
+ document.addPositionUpdater(updater);
+
+ model.addLinkingListener(new ILinkedModeListener() {
+
+ /*
+ * @see org.eclipse.jface.text.link.ILinkedModeListener#left(org.eclipse.jface.text.link.LinkedModeModel,
+ * int)
+ */
+ public void left(LinkedModeModel environment, int flags) {
+ try {
+ document.removePositionCategory(getCategory());
+ } catch (BadPositionCategoryException e) {
+ // ignore
+ }
+ document.removePositionUpdater(updater);
+ }
+
+ public void suspend(LinkedModeModel environment) {
+ }
+
+ public void resume(LinkedModeModel environment, int flags) {
+ }
+ });
+ }
+ }
+
+ private String getCategory() {
+ return "TemplateProposalCategory_" + toString(); //$NON-NLS-1$
+ }
+
+ private int getCaretOffset(TemplateBuffer buffer) {
+
+ TemplateVariable[] variables = buffer.getVariables();
+ for (int i = 0; i != variables.length; i++) {
+ TemplateVariable variable = variables[i];
+ if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME))
+ return variable.getOffsets()[0];
+ }
+
+ return buffer.getString().length();
+ }
+
+ /*
+ * @see ICompletionProposal#getSelection(IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return new Point(fSelectedRegion.getOffset(), fSelectedRegion
+ .getLength());
+ }
+
+ /*
+ * @see ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ try {
+ fContext.setReadOnly(true);
+ TemplateBuffer templateBuffer;
+ try {
+ templateBuffer = fContext.evaluate(fTemplate);
+ } catch (TemplateException e1) {
+ return null;
+ }
+
+ return templateBuffer.getString();
+
+ } catch (BadLocationException e) {
+ handleException(WebUI.getActiveWorkbenchShell(),
+ new CoreException(new Status(IStatus.ERROR,
+ WebUI.getPluginId(), IStatus.OK, "", e))); //$NON-NLS-1$
+ return null;
+ }
+ }
+
+ /*
+ * @see ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ if (fDisplayString == null) {
+ fDisplayString = fTemplate.getName()
+ + TemplateContentAssistMessages
+ .getString("TemplateProposal.delimiter") + fTemplate.getDescription(); //$NON-NLS-1$
+ }
+ return fDisplayString;
+ }
+
+ public void setDisplayString(String displayString) {
+ fDisplayString = displayString;
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return fImage;
+ }
+
+ /*
+ * @see ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+ private void openErrorDialog(Shell shell, Exception e) {
+ MessageDialog.openError(shell, TemplateContentAssistMessages
+ .getString("TemplateEvaluator.error.title"), e.getMessage()); //$NON-NLS-1$
+ }
+
+ private void handleException(Shell shell, CoreException e) {
+ ExceptionHandler.handle(e, shell, TemplateContentAssistMessages
+ .getString("TemplateEvaluator.error.title"), null); //$NON-NLS-1$
+ }
+
+ /*
+ * @see IJavaCompletionProposal#getRelevance()
+ */
+ public int getRelevance() {
+ return fRelevance;
+ }
+
+ public void setRelevance(int relevance) {
+ fRelevance = relevance;
+ }
+
+ public Template getTemplate() {
+ return fTemplate;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getInformationControlCreator()
+ */
+ public IInformationControlCreator getInformationControlCreator() {
+ return new TemplateInformationControlCreator();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+ * boolean)
+ */
+ public void selected(ITextViewer viewer, boolean smartToggle) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+ */
+ public void unselected(ITextViewer viewer) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+ * int, org.eclipse.jface.text.DocumentEvent)
+ */
+ public boolean validate(IDocument document, int offset, DocumentEvent event) {
+ try {
+ int replaceOffset = getReplaceOffset();
+ if (offset >= replaceOffset) {
+ String content = document.get(replaceOffset, offset
+ - replaceOffset);
+ return fTemplate.getName().startsWith(content);
+ }
+ } catch (BadLocationException e) {
+ // concurrent modification - ignore
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getReplacementString()
+ */
+ public CharSequence getPrefixCompletionText(IDocument document,
+ int completionOffset) {
+ return fTemplate.getName();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getReplacementOffset()
+ */
+ public int getPrefixCompletionStart(IDocument document, int completionOffset) {
+ return getReplaceOffset();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/VariablePosition.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/VariablePosition.java
new file mode 100644
index 0000000..6bf87f2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/contentassist/VariablePosition.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.link.LinkedPositionGroup;
+import org.eclipse.jface.text.link.ProposalPosition;
+
+/**
+ *
+ */
+public class VariablePosition extends ProposalPosition {
+
+ private MultiVariableGuess fGuess;
+
+ private MultiVariable fVariable;
+
+ public VariablePosition(IDocument document, int offset, int length,
+ MultiVariableGuess guess, MultiVariable variable) {
+ this(document, offset, length, LinkedPositionGroup.NO_STOP, guess,
+ variable);
+ }
+
+ public VariablePosition(IDocument document, int offset, int length,
+ int sequence, MultiVariableGuess guess, MultiVariable variable) {
+ super(document, offset, length, sequence, null);
+ Assert.isNotNull(guess);
+ Assert.isNotNull(variable);
+ fVariable = variable;
+ fGuess = guess;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.link.ProposalPosition#equals(java.lang.Object)
+ */
+ public boolean equals(Object o) {
+ if (o instanceof VariablePosition && super.equals(o)) {
+ return fGuess.equals(((VariablePosition) o).fGuess);
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.link.ProposalPosition#hashCode()
+ */
+ public int hashCode() {
+ return super.hashCode() | fGuess.hashCode();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.link.ProposalPosition#getChoices()
+ */
+ public ICompletionProposal[] getChoices() {
+ return fGuess.getProposals(fVariable, offset, length);
+ }
+
+ /**
+ * @return
+ */
+ public MultiVariable getVariable() {
+ return fVariable;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplatePreferencesMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplatePreferencesMessages.java
new file mode 100644
index 0000000..29a9740
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplatePreferencesMessages.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.preferences;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+class TemplatePreferencesMessages {
+
+ private static final String RESOURCE_BUNDLE = TemplatePreferencesMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private TemplatePreferencesMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplatePreferencesMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplatePreferencesMessages.properties
new file mode 100644
index 0000000..4cfe7bd
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplatePreferencesMessages.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2000, 2004 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+TemplateVariableProposal.error.title=Error applying template variable proposal
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplateVariableProcessor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplateVariableProcessor.java
new file mode 100644
index 0000000..ea9665c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplateVariableProcessor.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.preferences;
+
+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.
+ */
+ public void setContextType(TemplateContextType contextType) {
+ fContextType = contextType;
+ }
+
+ /**
+ * Gets 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);
+ String prefix = (string.length() >= 2) ? string.substring(2) : null;
+
+ int offset = start;
+ int length = end - start;
+
+ for (Iterator iterator = fContextType.resolvers(); iterator.hasNext();) {
+ TemplateVariableResolver variable = (TemplateVariableResolver) iterator
+ .next();
+
+ if (prefix == null || variable.getType().startsWith(prefix))
+ proposals.add(new TemplateVariableProposal(variable, offset,
+ length, viewer));
+ }
+
+ 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 >= 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/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplateVariableProposal.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplateVariableProposal.java
new file mode 100644
index 0000000..54ec6b3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/template/preferences/TemplateVariableProposal.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.template.preferences;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+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;
+
+/**
+ * A proposal for insertion of template variables.
+ */
+public class TemplateVariableProposal implements ICompletionProposal {
+
+ private TemplateVariableResolver fVariable;
+
+ private int fOffset;
+
+ private int fLength;
+
+ private ITextViewer fViewer;
+
+ private Point fSelection;
+
+ /**
+ * 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
+ */
+ public TemplateVariableProposal(TemplateVariableResolver variable,
+ int offset, int length, ITextViewer viewer) {
+ fVariable = variable;
+ fOffset = offset;
+ fLength = length;
+ fViewer = viewer;
+ }
+
+ /*
+ * @see ICompletionProposal#apply(IDocument)
+ */
+ public void apply(IDocument document) {
+
+ try {
+ String variable = fVariable.getType().equals("dollar") ? "$$" : "${" + fVariable.getType() + '}'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ document.replace(fOffset, fLength, variable);
+ fSelection = new Point(fOffset + variable.length(), 0);
+
+ } catch (BadLocationException e) {
+ WebUI.log(e);
+
+ Shell shell = fViewer.getTextWidget().getShell();
+ MessageDialog
+ .openError(
+ shell,
+ TemplatePreferencesMessages
+ .getString("TemplateVariableProposal.error.title"), e.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * @see ICompletionProposal#getSelection(IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return fSelection;
+ }
+
+ /*
+ * @see ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return null;
+ }
+
+ /*
+ * @see ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return fVariable.getType() + " - " + fVariable.getDescription(); //$NON-NLS-1$
+ }
+
+ /*
+ * @see ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return null;
+ }
+
+ /*
+ * @see ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/DirectorySelector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/DirectorySelector.java
new file mode 100644
index 0000000..8a686f7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/DirectorySelector.java
@@ -0,0 +1,38 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.io.File;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+
+public class DirectorySelector extends ResourceSelector {
+
+ public DirectorySelector(Composite parent) {
+ super(parent);
+ }
+
+ protected void handleBrowseSelected() {
+ DirectoryDialog dialog = new DirectoryDialog(getShell());
+ dialog.setMessage(browseDialogMessage);
+ String currentWorkingDir = textField.getText();
+ if (!currentWorkingDir.trim().equals("")) {
+ File path = new File(currentWorkingDir);
+ if (path.exists()) {
+ dialog.setFilterPath(currentWorkingDir);
+ }
+ }
+
+ String selectedDirectory = dialog.open();
+ if (selectedDirectory != null) {
+ textField.setText(selectedDirectory);
+ }
+ }
+
+ protected String validateResourceSelection() {
+ String directory = textField.getText();
+ File directoryFile = new File(directory);
+ if (directoryFile.exists() && directoryFile.isDirectory())
+ return directory;
+ return EMPTY_STRING;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/ExceptionHandler.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/ExceptionHandler.java
new file mode 100644
index 0000000..a5807a9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/ExceptionHandler.java
@@ -0,0 +1,86 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Shell;
+
+public class ExceptionHandler {
+ private static ExceptionHandler fgInstance = new ExceptionHandler();
+
+ public static void log(Throwable t, String message) {
+ WebUI.getDefault().getLog().log(
+ new Status(IStatus.ERROR, WebUI.PLUGIN_ID,
+ IStatus.ERROR, message, t));
+ }
+
+ public static void handle(CoreException e, String title, String message) {
+ handle(e, WebUI.getActiveWorkbenchShell(), title, message);
+ }
+
+ public static void handle(CoreException e, Shell parent, String title,
+ String message) {
+ fgInstance.perform(e, parent, title, message);
+ }
+
+ public static void handle(InvocationTargetException e, String title,
+ String message) {
+ handle(e, WebUI.getActiveWorkbenchShell(), title, message);
+ }
+
+ public static void handle(InvocationTargetException e, Shell parent,
+ String title, String message) {
+ fgInstance.perform(e, parent, title, message);
+ }
+
+ protected void perform(CoreException e, Shell shell, String title,
+ String message) {
+ WebUI.log(e);
+ IStatus status = e.getStatus();
+ if (status != null) {
+ ErrorDialog.openError(shell, title, message, status);
+ } else {
+ displayMessageDialog(e, e.getMessage(), shell, title, message);
+ }
+ }
+
+ protected void perform(InvocationTargetException e, Shell shell,
+ String title, String message) {
+ Throwable target = e.getTargetException();
+ if (target instanceof CoreException) {
+ perform((CoreException) target, shell, title, message);
+ } else {
+ WebUI.log(e);
+ if (e.getMessage() != null && e.getMessage().length() > 0) {
+ displayMessageDialog(e, e.getMessage(), shell, title, message);
+ } else {
+ displayMessageDialog(e, target.getMessage(), shell, title,
+ message);
+ }
+ }
+ }
+
+ private void displayMessageDialog(Throwable t, String exceptionMessage,
+ Shell shell, String title, String message) {
+ StringWriter msg = new StringWriter();
+ if (message != null) {
+ msg.write(message);
+ msg.write("\n\n");
+ }
+ if (exceptionMessage == null || exceptionMessage.length() == 0)
+ msg.write(PHPUIMessages
+ .getString("ExceptionDialog.seeErrorLogMessage"));
+ else
+ msg.write(exceptionMessage);
+ MessageDialog.openError(shell, title, msg.toString());
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/FilteredList.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/FilteredList.java
new file mode 100644
index 0000000..65b17f6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/FilteredList.java
@@ -0,0 +1,504 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionListener;
+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.Event;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+/**
+ * A composite widget which holds a list of elements for user selection. The
+ * elements are sorted alphabetically. Optionally, the elements can be filtered
+ * and duplicate entries can be hidden (folding).
+ */
+public class FilteredList extends Composite {
+
+ public interface FilterMatcher {
+ /**
+ * Sets the filter.
+ *
+ * @param pattern
+ * the filter pattern.
+ * @param ignoreCase
+ * a flag indicating whether pattern matching is case
+ * insensitive or not.
+ * @param ignoreWildCards
+ * a flag indicating whether wildcard characters are
+ * interpreted or not.
+ */
+ void setFilter(String pattern, boolean ignoreCase,
+ boolean ignoreWildCards);
+
+ /**
+ * Returns true
if the object matches the pattern,
+ * false
otherwise. setFilter()
must have
+ * been called at least once prior to a call to this method.
+ */
+ boolean match(Object element);
+ }
+
+ private class DefaultFilterMatcher implements FilterMatcher {
+ private StringMatcher fMatcher;
+
+ public void setFilter(String pattern, boolean ignoreCase,
+ boolean ignoreWildCards) {
+ fMatcher = new StringMatcher(pattern + '*', ignoreCase,
+ ignoreWildCards);
+ }
+
+ public boolean match(Object element) {
+ return fMatcher.match(fRenderer.getText(element));
+ }
+ }
+
+ private Table fList;
+
+ private ILabelProvider fRenderer;
+
+ private boolean fMatchEmtpyString = true;
+
+ private boolean fIgnoreCase;
+
+ private boolean fAllowDuplicates;
+
+ private String fFilter = ""; //$NON-NLS-1$
+
+ private TwoArrayQuickSorter fSorter;
+
+ private Object[] fElements = new Object[0];
+
+ private Label[] fLabels;
+
+ private Vector fImages = new Vector();
+
+ private int[] fFoldedIndices;
+
+ private int fFoldedCount;
+
+ private int[] fFilteredIndices;
+
+ private int fFilteredCount;
+
+ private FilterMatcher fFilterMatcher = new DefaultFilterMatcher();
+
+ private Comparator fComparator;
+
+ private static class Label {
+ public final String string;
+
+ public final Image image;
+
+ public Label(String string, Image image) {
+ this.string = string;
+ this.image = image;
+ }
+
+ public boolean equals(Label label) {
+ if (label == null)
+ return false;
+
+ return string.equals(label.string) && image.equals(label.image);
+ }
+ }
+
+ private final class LabelComparator implements Comparator {
+ private boolean fIgnoreCase;
+
+ LabelComparator(boolean ignoreCase) {
+ fIgnoreCase = ignoreCase;
+ }
+
+ public int compare(Object left, Object right) {
+ Label leftLabel = (Label) left;
+ Label rightLabel = (Label) right;
+
+ int value;
+
+ if (fComparator == null) {
+ value = fIgnoreCase ? leftLabel.string
+ .compareToIgnoreCase(rightLabel.string)
+ : leftLabel.string.compareTo(rightLabel.string);
+ } else {
+ value = fComparator
+ .compare(leftLabel.string, rightLabel.string);
+ }
+
+ if (value != 0)
+ return value;
+
+ // images are allowed to be null
+ if (leftLabel.image == null) {
+ return (rightLabel.image == null) ? 0 : -1;
+ } else if (rightLabel.image == null) {
+ return +1;
+ } else {
+ return fImages.indexOf(leftLabel.image)
+ - fImages.indexOf(rightLabel.image);
+ }
+ }
+
+ }
+
+ /**
+ * Constructs a new instance of a filtered list.
+ *
+ * @param parent
+ * the parent composite.
+ * @param style
+ * the widget style.
+ * @param renderer
+ * the label renderer.
+ * @param ignoreCase
+ * specifies whether sorting and folding is case sensitive.
+ * @param allowDuplicates
+ * specifies whether folding of duplicates is desired.
+ * @param matchEmptyString
+ * specifies whether empty filter strings should filter
+ * everything or nothing.
+ */
+ public FilteredList(Composite parent, int style, ILabelProvider renderer,
+ boolean ignoreCase, boolean allowDuplicates,
+ boolean matchEmptyString) {
+ super(parent, SWT.NONE);
+
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ setLayout(layout);
+
+ fList = new Table(this, style);
+ fList.setLayoutData(new GridData(GridData.FILL_BOTH));
+ fList.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ fRenderer.dispose();
+ }
+ });
+
+ fRenderer = renderer;
+ fIgnoreCase = ignoreCase;
+ fSorter = new TwoArrayQuickSorter(new LabelComparator(ignoreCase));
+ fAllowDuplicates = allowDuplicates;
+ fMatchEmtpyString = matchEmptyString;
+ }
+
+ /**
+ * Sets the list of elements.
+ *
+ * @param elements
+ * the elements to be shown in the list.
+ */
+ public void setElements(Object[] elements) {
+ if (elements == null) {
+ fElements = new Object[0];
+ } else {
+ // copy list for sorting
+ fElements = new Object[elements.length];
+ System.arraycopy(elements, 0, fElements, 0, elements.length);
+ }
+
+ int length = fElements.length;
+
+ // fill labels
+ fLabels = new Label[length];
+ Set imageSet = new HashSet();
+ for (int i = 0; i != length; i++) {
+ String text = fRenderer.getText(fElements[i]);
+ Image image = fRenderer.getImage(fElements[i]);
+
+ fLabels[i] = new Label(text, image);
+ imageSet.add(image);
+ }
+ fImages.clear();
+ fImages.addAll(imageSet);
+
+ fSorter.sort(fLabels, fElements);
+
+ fFilteredIndices = new int[length];
+ fFilteredCount = filter();
+
+ fFoldedIndices = new int[length];
+ fFoldedCount = fold();
+
+ updateList();
+ }
+
+ /**
+ * Tests if the list (before folding and filtering) is empty.
+ *
+ * @return returns true
if the list is empty,
+ * false
otherwise.
+ */
+ public boolean isEmpty() {
+ return (fElements == null) || (fElements.length == 0);
+ }
+
+ /**
+ * Sets the filter matcher.
+ */
+ public void setFilterMatcher(FilterMatcher filterMatcher) {
+ Assert.isNotNull(filterMatcher);
+ fFilterMatcher = filterMatcher;
+ }
+
+ /**
+ * Sets a custom comparator for sorting the list.
+ */
+ public void setComparator(Comparator comparator) {
+ Assert.isNotNull(comparator);
+ fComparator = comparator;
+ }
+
+ /**
+ * Adds a selection listener to the list.
+ *
+ * @param listener
+ * the selection listener to be added.
+ */
+ public void addSelectionListener(SelectionListener listener) {
+ fList.addSelectionListener(listener);
+ }
+
+ /**
+ * Removes a selection listener from the list.
+ *
+ * @param listener
+ * the selection listener to be removed.
+ */
+ public void removeSelectionListener(SelectionListener listener) {
+ fList.removeSelectionListener(listener);
+ }
+
+ /**
+ * Sets the selection of the list.
+ *
+ * @param selection
+ * an array of indices specifying the selection.
+ */
+ public void setSelection(int[] selection) {
+ fList.setSelection(selection);
+ }
+
+ /**
+ * Returns the selection of the list.
+ *
+ * @return returns an array of indices specifying the current selection.
+ */
+ public int[] getSelectionIndices() {
+ return fList.getSelectionIndices();
+ }
+
+ /**
+ * Returns the selection of the list. This is a convenience function for
+ * getSelectionIndices()
.
+ *
+ * @return returns the index of the selection, -1 for no selection.
+ */
+ public int getSelectionIndex() {
+ return fList.getSelectionIndex();
+ }
+
+ /**
+ * Sets the selection of the list.
+ *
+ * @param elements
+ * the array of elements to be selected.
+ */
+ public void setSelection(Object[] elements) {
+ if ((elements == null) || (fElements == null))
+ return;
+
+ // fill indices
+ int[] indices = new int[elements.length];
+ for (int i = 0; i != elements.length; i++) {
+ int j;
+ for (j = 0; j != fFoldedCount; j++) {
+ int max = (j == fFoldedCount - 1) ? fFilteredCount
+ : fFoldedIndices[j + 1];
+
+ int l;
+ for (l = fFoldedIndices[j]; l != max; l++) {
+ // found matching element?
+ if (fElements[fFilteredIndices[l]].equals(elements[i])) {
+ indices[i] = j;
+ break;
+ }
+ }
+
+ if (l != max)
+ break;
+ }
+
+ // not found
+ if (j == fFoldedCount)
+ indices[i] = 0;
+ }
+
+ fList.setSelection(indices);
+ }
+
+ /**
+ * Returns an array of the selected elements. The type of the elements
+ * returned in the list are the same as the ones passed with
+ * setElements
. The array does not contain the rendered
+ * strings.
+ *
+ * @return returns the array of selected elements.
+ */
+ public Object[] getSelection() {
+ if (fList.isDisposed() || (fList.getSelectionCount() == 0))
+ return new Object[0];
+
+ int[] indices = fList.getSelectionIndices();
+ Object[] elements = new Object[indices.length];
+
+ for (int i = 0; i != indices.length; i++)
+ elements[i] = fElements[fFilteredIndices[fFoldedIndices[indices[i]]]];
+
+ return elements;
+ }
+
+ /**
+ * Sets the filter pattern. Current only prefix filter patterns are
+ * supported.
+ *
+ * @param filter
+ * the filter pattern.
+ */
+ public void setFilter(String filter) {
+ fFilter = (filter == null) ? "" : filter; //$NON-NLS-1$
+
+ fFilteredCount = filter();
+ fFoldedCount = fold();
+ updateList();
+ }
+
+ /**
+ * Returns the filter pattern.
+ *
+ * @return returns the filter pattern.
+ */
+ public String getFilter() {
+ return fFilter;
+ }
+
+ /**
+ * Returns all elements which are folded together to one entry in the list.
+ *
+ * @param index
+ * the index selecting the entry in the list.
+ * @return returns an array of elements folded together, null
+ * if index is out of range.
+ */
+ public Object[] getFoldedElements(int index) {
+ if ((index < 0) || (index >= fFoldedCount))
+ return null;
+
+ int start = fFoldedIndices[index];
+ int count = (index == fFoldedCount - 1) ? fFilteredCount - start
+ : fFoldedIndices[index + 1] - start;
+
+ Object[] elements = new Object[count];
+ for (int i = 0; i != count; i++)
+ elements[i] = fElements[fFilteredIndices[start + i]];
+
+ return elements;
+ }
+
+ /*
+ * Folds duplicate entries. Two elements are considered as a pair of
+ * duplicates if they coiincide in the rendered string and image. @return
+ * returns the number of elements after folding.
+ */
+ private int fold() {
+ if (fAllowDuplicates) {
+ for (int i = 0; i != fFilteredCount; i++)
+ fFoldedIndices[i] = i; // identity mapping
+
+ return fFilteredCount;
+
+ } else {
+ int k = 0;
+ Label last = null;
+ for (int i = 0; i != fFilteredCount; i++) {
+ int j = fFilteredIndices[i];
+
+ Label current = fLabels[j];
+ if (!current.equals(last)) {
+ fFoldedIndices[k] = i;
+ k++;
+ last = current;
+ }
+ }
+ return k;
+ }
+ }
+
+ /*
+ * Filters the list with the filter pattern. @return returns the number of
+ * elements after filtering.
+ */
+ private int filter() {
+ if (((fFilter == null) || (fFilter.length() == 0))
+ && !fMatchEmtpyString)
+ return 0;
+
+ fFilterMatcher.setFilter(fFilter.trim(), fIgnoreCase, false);
+
+ int k = 0;
+ for (int i = 0; i != fElements.length; i++) {
+ if (fFilterMatcher.match(fElements[i]))
+ fFilteredIndices[k++] = i;
+ }
+
+ return k;
+ }
+
+ /*
+ * Updates the list widget.
+ */
+ private void updateList() {
+ if (fList.isDisposed())
+ return;
+
+ fList.setRedraw(false);
+
+ // resize table
+ int itemCount = fList.getItemCount();
+ if (fFoldedCount < itemCount)
+ fList.remove(0, itemCount - fFoldedCount - 1);
+ else if (fFoldedCount > itemCount)
+ for (int i = 0; i != fFoldedCount - itemCount; i++)
+ new TableItem(fList, SWT.NONE);
+
+ // fill table
+ TableItem[] items = fList.getItems();
+ for (int i = 0; i != fFoldedCount; i++) {
+ TableItem item = items[i];
+ Label label = fLabels[fFilteredIndices[fFoldedIndices[i]]];
+
+ item.setText(label.string);
+ item.setImage(label.image);
+ }
+
+ // select first item if any
+ if (fList.getItemCount() > 0)
+ fList.setSelection(0);
+
+ fList.setRedraw(true);
+ fList.notifyListeners(SWT.Selection, new Event());
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPElementVisitor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPElementVisitor.java
new file mode 100644
index 0000000..275bd57
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPElementVisitor.java
@@ -0,0 +1,41 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+
+public class PHPElementVisitor implements IResourceVisitor {
+ protected List phpFiles = new ArrayList();
+
+ public PHPElementVisitor() {
+ super();
+ }
+
+ public boolean visit(IResource resource) throws CoreException {
+ switch (resource.getType()) {
+ case IResource.PROJECT:
+ return true;
+
+ case IResource.FOLDER:
+ return true;
+
+ case IResource.FILE:
+ IFile fileResource = (IFile) resource;
+ if (PHPFileUtil.isPHPFile(fileResource)) {
+ phpFiles.add(fileResource);
+ return true;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+ public Object[] getCollectedPHPFiles() {
+ return phpFiles.toArray();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPFileSelector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPFileSelector.java
new file mode 100644
index 0000000..84dbafd
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPFileSelector.java
@@ -0,0 +1,114 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+public class PHPFileSelector extends ResourceSelector {
+ static class FileLabelProvider extends LabelProvider {
+ /**
+ * Returns the implementation of IWorkbenchAdapter for the given object.
+ *
+ * @param o
+ * the object to look up.
+ * @return IWorkbenchAdapter or null
if the adapter is
+ * not defined or the object is not adaptable.
+ */
+ protected final IWorkbenchAdapter getAdapter(Object o) {
+ if (!(o instanceof IAdaptable)) {
+ return null;
+ }
+ return (IWorkbenchAdapter) ((IAdaptable) o)
+ .getAdapter(IWorkbenchAdapter.class);
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ if (element instanceof IFile) {
+ // query the element for its label
+ IWorkbenchAdapter adapter = getAdapter(element);
+ if (adapter == null) {
+ return ""; //$NON-NLS-1$
+ }
+ String filename = adapter.getLabel(element);
+ IPath path = ((IFile) element).getFullPath();
+ String filePathname = path != null ? path.toString() : ""; //$NON-NLS-1$
+ return filename + " (" + filePathname + ")";
+ }
+ return super.getText(element);
+ }
+ }
+
+ protected PHPProjectSelector phpProjectSelector;
+
+ public PHPFileSelector(Composite parent, PHPProjectSelector aProjectSelector) {
+ super(parent);
+ Assert.isNotNull(aProjectSelector);
+ phpProjectSelector = aProjectSelector;
+
+ browseDialogTitle = "File Selection";
+ }
+
+ protected Object[] getPHPFiles() {
+ IProject phpProject = phpProjectSelector.getSelection();
+ if (phpProject == null)
+ return new Object[0];
+
+ PHPElementVisitor visitor = new PHPElementVisitor();
+ try {
+ phpProject.accept(visitor);
+ } catch (CoreException e) {
+ WebUI.log(e);
+ }
+ return visitor.getCollectedPHPFiles();
+ }
+
+ public IFile getSelection() {
+ String fileName = getSelectionText();
+ if (fileName != null && !fileName.equals("")) {
+ IPath filePath = new Path(fileName);
+ IProject project = phpProjectSelector.getSelection();
+ if (project != null && project.exists(filePath))
+ return project.getFile(filePath);
+ }
+
+ return null;
+ }
+
+ protected void handleBrowseSelected() {
+ // ElementListSelectionDialog dialog = new
+ // ElementListSelectionDialog(getShell(), new WorkbenchLabelProvider());
+ ElementListSelectionDialog dialog = new ElementListSelectionDialog(
+ getShell(), new FileLabelProvider());
+
+ dialog.setTitle(browseDialogTitle);
+ dialog.setMessage(browseDialogMessage);
+ dialog.setElements(getPHPFiles());
+
+ if (dialog.open() == ElementListSelectionDialog.OK) {
+ textField.setText(((IResource) dialog.getFirstResult())
+ .getProjectRelativePath().toString());
+ }
+ }
+
+ protected String validateResourceSelection() {
+ IFile selection = getSelection();
+ return selection == null ? EMPTY_STRING : selection
+ .getProjectRelativePath().toString();
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java
new file mode 100644
index 0000000..b9f3421
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java
@@ -0,0 +1,214 @@
+/*
+ * Created on 09.08.2003
+ *
+ */
+
+/*duplicated incastrix*/
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.io.File;
+import java.util.List;
+
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+
+public class PHPFileUtil {
+ // private static String[] PHP_EXTENSIONS = null;
+
+ public final static String[] SMARTY_EXTENSIONS = { "tpl" };
+
+ public static boolean isPHPFile(IFile file) {
+ return isPHPFileName(file.getFullPath().toString());
+ }
+
+ // public final static String getFileExtension(String name) {
+ // int index = name.lastIndexOf('.');
+ // if (index == -1)
+ // return null;
+ // if (index == (name.length() - 1))
+ // return null; //$NON-NLS-1$
+ // return name.substring(index + 1);
+ // }
+
+ /**
+ * Returns true iff str.toLowerCase().endsWith(".php") implementation is not
+ * creating extra strings.
+ */
+ public final static boolean isPHPFileName(String name) {
+
+ // avoid handling a file without base name, e.g. ".php", which is a
+ // valid
+ // Eclipse resource name
+ File file = new File(name);
+ if (file.getName().startsWith(".")) {
+ return false;
+ }
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ IEditorRegistry registry = workbench.getEditorRegistry();
+ IEditorDescriptor[] descriptors = registry.getEditors(name);
+
+ for (int i = 0; i < descriptors.length; i++) {
+ if (descriptors[i].getId().equals(WebUI.EDITOR_ID)) {
+ return true;
+ }
+ }
+ // String extension = getFileExtension(name);
+ // if (extension == null) {
+ // return false;
+ // }
+ // extension = extension.toLowerCase();
+ // PHP_EXTENSIONS = getExtensions();
+ // if (PHP_EXTENSIONS == null) {
+ // return false;
+ // }
+ // for (int i = 0; i < PHP_EXTENSIONS.length; i++) {
+ // if (extension.equals(PHP_EXTENSIONS[i])) {
+ // return true;
+ // }
+ // }
+ return false;
+ }
+
+ /**
+ * Returns true iff the file extension is a valid PHP Unit name
+ * implementation is not creating extra strings.
+ */
+ public final static boolean isValidPHPUnitName(String filename) {
+ return PHPFileUtil.isPHPFileName(filename);
+ }
+
+ /**
+ * @return Returns the PHP extensions.
+ */
+ // public static String[] getExtensions() {
+ // if (PHP_EXTENSIONS == null) {
+ // ArrayList list = new ArrayList();
+ // final IPreferenceStore store =
+ // PHPeclipsePlugin.getDefault().getPreferenceStore();
+ // String extensions =
+ // store.getString(PHPeclipsePlugin.PHP_EXTENSION_PREFS);
+ // extensions = extensions.trim();
+ // if (extensions.length() != 0) {
+ // StringTokenizer tokenizer = new StringTokenizer(extensions, " ,;:/-|");
+ // String token;
+ // while (tokenizer.hasMoreTokens()) {
+ // token = tokenizer.nextToken();
+ // if (token != null && token.length() >= 1) {
+ // list.add(token);
+ // }
+ // }
+ // if (list.size() != 0) {
+ // PHP_EXTENSIONS = new String[list.size()];
+ // for (int i = 0; i < list.size(); i++) {
+ // PHP_EXTENSIONS[i] = (String) list.get(i);
+ // }
+ // }
+ // }
+ // }
+ // return PHP_EXTENSIONS;
+ // }
+ /**
+ * @param php_extensions
+ * The PHP extensions to set.
+ */
+ // public static void setExtensions(String[] php_extensions) {
+ // PHP_EXTENSIONS = php_extensions;
+ // }
+ /**
+ * Creata the file for the given absolute file path
+ *
+ * @param absoluteFilePath
+ * @param project
+ * @return the file for the given absolute file path or null
+ * if no existing file can be found
+ */
+ public static IFile createFile(IPath absoluteFilePath, IProject project) {
+ if (absoluteFilePath == null || project == null) {
+ return null;
+ }
+
+ String projectPath = project.getFullPath().toString();
+ String filePath = absoluteFilePath.toString().substring(
+ projectPath.length() + 1);
+ return project.getFile(filePath);
+
+ }
+
+ /**
+ * Determine the path of an include name string
+ *
+ * @param includeNameString
+ * @param resource
+ * @param project
+ * @return the path for the given include filename or null
if
+ * no existing file can be found
+ */
+ public static IPath determineFilePath(String includeNameString,
+ IResource resource, IProject project) {
+ IPath documentRootPath = ProjectPrefUtil.getDocumentRoot(project);
+ IPath resourcePath = resource.getProjectRelativePath();
+
+ IPath path = null;
+
+ // script location based
+ path = project.getFullPath().append(resourcePath.removeLastSegments(1))
+ .append(includeNameString);
+ //path =
+ if (fileExists(path, false)) {
+ return path;
+ }
+ // project root based
+ path = project.getFullPath().append(includeNameString);
+ if (fileExists(path, false)) {
+ return path;
+ }
+
+ // DocumentRoot (absolute path) based
+ path = documentRootPath.append(includeNameString);
+ if (fileExists(path, true)) {
+ return path;
+ }
+
+ // IncludePaths settings (absolute path) based
+ List includePaths = ProjectPrefUtil.getIncludePaths(project);
+ if (includePaths.size() > 0) {
+ for (int i = 0; i < includePaths.size(); i++) {
+ path = new Path(includePaths.get(i).toString())
+ .append(includeNameString);
+ if (fileExists(path, true)) {
+ return path;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static boolean fileExists(IPath path, boolean absolute) {
+ File file = path.toFile();
+ if (file.exists()) {
+ return true;
+ }
+ if (!absolute) {
+ IFile ifile = FileBuffers.getWorkspaceFileAtLocation(path);
+ if (ifile != null) {
+ IResource resource = ifile;
+ if (resource.exists()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPProjectSelector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPProjectSelector.java
new file mode 100644
index 0000000..034d691
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PHPProjectSelector.java
@@ -0,0 +1,45 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+public class PHPProjectSelector extends ResourceSelector {
+
+ public PHPProjectSelector(Composite parent) {
+ super(parent);
+
+ browseDialogTitle = "Project Selection";
+ }
+
+ public IProject getSelection() {
+ String projectName = getSelectionText();
+ if (projectName != null && !projectName.equals(""))
+ return WebUI.getWorkspace().getRoot().getProject(
+ projectName);
+
+ return null;
+ }
+
+ protected void handleBrowseSelected() {
+ ElementListSelectionDialog dialog = new ElementListSelectionDialog(
+ getShell(), new WorkbenchLabelProvider());
+ dialog.setTitle(browseDialogTitle);
+ dialog.setMessage(browseDialogMessage);
+ dialog.setElements(JavaCore.getPHPProjects());
+
+ if (dialog.open() == ElementListSelectionDialog.OK) {
+ textField.setText(((IProject) dialog.getFirstResult()).getName());
+ }
+ }
+
+ protected String validateResourceSelection() {
+ IProject project = getSelection();
+ return project == null ? EMPTY_STRING : project.getName();
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PixelConverter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PixelConverter.java
new file mode 100644
index 0000000..46ace94
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/PixelConverter.java
@@ -0,0 +1,49 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.widgets.Control;
+
+public class PixelConverter {
+
+ private FontMetrics fFontMetrics;
+
+ public PixelConverter(Control control) {
+ GC gc = new GC(control);
+ gc.setFont(control.getFont());
+ fFontMetrics = gc.getFontMetrics();
+ gc.dispose();
+ }
+
+ private FontMetrics fgFontMetrics;
+
+ /**
+ * @see org.eclipse.jface.dialogs.DialogPage#convertHeightInCharsToPixels(int)
+ */
+ public int convertHeightInCharsToPixels(int chars) {
+ return Dialog.convertHeightInCharsToPixels(fFontMetrics, chars);
+ }
+
+ /**
+ * @see org.eclipse.jface.dialogs.DialogPage#convertHorizontalDLUsToPixels(int)
+ */
+ public int convertHorizontalDLUsToPixels(int dlus) {
+ return Dialog.convertHorizontalDLUsToPixels(fFontMetrics, dlus);
+ }
+
+ /**
+ * @see org.eclipse.jface.dialogs.DialogPage#convertVerticalDLUsToPixels(int)
+ */
+ public int convertVerticalDLUsToPixels(int dlus) {
+ return Dialog.convertVerticalDLUsToPixels(fFontMetrics, dlus);
+ }
+
+ /**
+ * @see org.eclipse.jface.dialogs.DialogPage#convertWidthInCharsToPixels(int)
+ */
+ public int convertWidthInCharsToPixels(int chars) {
+ return Dialog.convertWidthInCharsToPixels(fFontMetrics, chars);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/ResourceSelector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/ResourceSelector.java
new file mode 100644
index 0000000..42e78de
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/ResourceSelector.java
@@ -0,0 +1,96 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+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.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public abstract class ResourceSelector {
+ protected final static String EMPTY_STRING = "";
+
+ protected Composite composite;
+
+ protected Button browseButton;
+
+ protected Text textField;
+
+ protected String browseDialogMessage = EMPTY_STRING;
+
+ protected String browseDialogTitle = EMPTY_STRING;
+
+ protected String validatedSelectionText = EMPTY_STRING;
+
+ public ResourceSelector(Composite parent) {
+ composite = new Composite(parent, SWT.NONE);
+ GridLayout compositeLayout = new GridLayout();
+ compositeLayout.marginWidth = 0;
+ compositeLayout.marginHeight = 0;
+ compositeLayout.numColumns = 2;
+ composite.setLayout(compositeLayout);
+
+ textField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ textField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ textField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ validatedSelectionText = validateResourceSelection();
+ }
+ });
+
+ browseButton = new Button(composite, SWT.PUSH);
+ browseButton.setText("Browse...");
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowseSelected();
+ }
+ });
+ }
+
+ protected abstract void handleBrowseSelected();
+
+ protected abstract String validateResourceSelection();
+
+ protected Shell getShell() {
+ return composite.getShell();
+ }
+
+ public void setLayoutData(Object layoutData) {
+ composite.setLayoutData(layoutData);
+ }
+
+ public void addModifyListener(ModifyListener aListener) {
+ textField.addModifyListener(aListener);
+ }
+
+ public void setBrowseDialogMessage(String aMessage) {
+ browseDialogMessage = aMessage;
+ }
+
+ public void setBrowseDialogTitle(String aTitle) {
+ browseDialogTitle = aTitle;
+ }
+
+ public void setEnabled(boolean enabled) {
+ composite.setEnabled(enabled);
+ textField.setEnabled(enabled);
+ browseButton.setEnabled(enabled);
+ }
+
+ public String getSelectionText() {
+ return textField.getText();
+ }
+
+ public String getValidatedSelectionText() {
+ return validatedSelectionText;
+ }
+
+ public void setSelectionText(String newText) {
+ textField.setText(newText);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/SWTUtil.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/SWTUtil.java
new file mode 100644
index 0000000..979463c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/SWTUtil.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.util;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Caret;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Utility class to simplify access to some SWT resources.
+ */
+public class SWTUtil {
+
+ /**
+ * Returns the standard display to be used. The method first checks, if the
+ * thread calling this method has an associated disaply. If so, this display
+ * is returned. Otherwise the method returns the default display.
+ */
+ public static Display getStandardDisplay() {
+ Display display;
+ display = Display.getCurrent();
+ if (display == null)
+ display = Display.getDefault();
+ return display;
+ }
+
+ /**
+ * Returns the shell for the given widget. If the widget doesn't represent a
+ * SWT object that manage a shell, null
is returned.
+ *
+ * @return the shell for the given widget
+ */
+ public static Shell getShell(Widget widget) {
+ if (widget instanceof Control)
+ return ((Control) widget).getShell();
+ if (widget instanceof Caret)
+ return ((Caret) widget).getParent().getShell();
+ if (widget instanceof DragSource)
+ return ((DragSource) widget).getControl().getShell();
+ if (widget instanceof DropTarget)
+ return ((DropTarget) widget).getControl().getShell();
+ if (widget instanceof Menu)
+ return ((Menu) widget).getParent().getShell();
+ if (widget instanceof ScrollBar)
+ return ((ScrollBar) widget).getParent().getShell();
+
+ return null;
+ }
+
+ /**
+ * Returns a width hint for a button control.
+ */
+ public static int getButtonWidthHint(Button button) {
+ button.setFont(JFaceResources.getDialogFont());
+ PixelConverter converter = new PixelConverter(button);
+ int widthHint = converter
+ .convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
+ return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT,
+ true).x);
+ }
+
+ /**
+ * Returns a height hint for a button control.
+ */
+ public static int getButtonHeightHint(Button button) {
+ button.setFont(JFaceResources.getDialogFont());
+ PixelConverter converter = new PixelConverter(button);
+ return converter
+ .convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT);
+ }
+
+ /**
+ * Sets width and height hint for the button control. Note: This is
+ * a NOP if the button's layout data is not an instance of
+ * GridData
.
+ *
+ * @param button
+ * the button for which to set the dimension hint
+ */
+ public static void setButtonDimensionHint(Button button) {
+ Assert.isNotNull(button);
+ Object gd = button.getLayoutData();
+ if (gd instanceof GridData) {
+ ((GridData) gd).heightHint = getButtonHeightHint(button);
+ ((GridData) gd).widthHint = getButtonWidthHint(button);
+ ((GridData) gd).horizontalAlignment = GridData.FILL;
+ }
+ }
+
+ public static int getTableHeightHint(Table table, int rows) {
+ if (table.getFont().equals(JFaceResources.getDefaultFont()))
+ table.setFont(JFaceResources.getDialogFont());
+ int result = table.getItemHeight() * rows + table.getHeaderHeight();
+ if (table.getLinesVisible())
+ result += table.getGridLineWidth() * (rows - 1);
+ return result;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/StreamUtil.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/StreamUtil.java
new file mode 100644
index 0000000..5cdf1b9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/StreamUtil.java
@@ -0,0 +1,29 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class StreamUtil {
+ public static void transferStreams(InputStream source,
+ OutputStream destination) throws IOException {
+ try {
+ byte[] buffer = new byte[8192];
+ while (true) {
+ int bytesRead = source.read(buffer);
+ if (bytesRead == -1)
+ break;
+ destination.write(buffer, 0, bytesRead);
+ }
+ } finally {
+ try {
+ source.close();
+ } catch (IOException e) {
+ }
+ try {
+ destination.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/StringMatcher.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/StringMatcher.java
new file mode 100644
index 0000000..756f28e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/StringMatcher.java
@@ -0,0 +1,440 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.util.Vector;
+
+/**
+ * A string pattern matcher, suppporting * and ? wildcards.
+ */
+public class StringMatcher {
+ protected String fPattern;
+
+ protected int fLength; // pattern length
+
+ protected boolean fIgnoreWildCards;
+
+ protected boolean fIgnoreCase;
+
+ protected boolean fHasLeadingStar;
+
+ protected boolean fHasTrailingStar;
+
+ protected String fSegments[]; // the given pattern is split into *
+ // separated segments
+
+ /* boundary value beyond which we don't need to search in the text */
+ protected int fBound = 0;
+
+ protected static final char fSingleWildCard = '\u0000';
+
+ public static class Position {
+ int start; // inclusive
+
+ int end; // exclusive
+
+ public Position(int start, int end) {
+ this.start = start;
+ this.end = end;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+ }
+
+ /**
+ * StringMatcher constructor takes in a String object that is a simple
+ * pattern which may contain �*� for 0 and many characters and �?� for
+ * exactly one character.
+ *
+ * Literal '*' and '?' characters must be escaped in the pattern e.g., "\*"
+ * means literal "*", etc.
+ *
+ * Escaping any other character (including the escape character itself),
+ * just results in that character in the pattern. e.g., "\a" means "a" and
+ * "\\" means "\"
+ *
+ * If invoking the StringMatcher with string literals in Java, don't forget
+ * escape characters are represented by "\\".
+ *
+ * @param pattern
+ * the pattern to match text against
+ * @param ignoreCase
+ * if true, case is ignored
+ * @param ignoreWildCards
+ * if true, wild cards and their escape sequences are ignored
+ * (everything is taken literally).
+ */
+ public StringMatcher(String pattern, boolean ignoreCase,
+ boolean ignoreWildCards) {
+ if (pattern == null)
+ throw new IllegalArgumentException();
+ fIgnoreCase = ignoreCase;
+ fIgnoreWildCards = ignoreWildCards;
+ fPattern = pattern;
+ fLength = pattern.length();
+
+ if (fIgnoreWildCards) {
+ parseNoWildCards();
+ } else {
+ parseWildCards();
+ }
+ }
+
+ /**
+ * Find the first occurrence of the pattern between
+ * start
end
(exclusive).
+ * @param text
, the String object to search in
+ * @param start
, the starting index of the search range, inclusive
+ * @param end
, the ending index of the search range, exclusive
+ * @return an StringMatcher.Position
object that keeps the starting
+ * (inclusive) and ending positions (exclusive) of the first occurrence of the
+ * pattern in the specified range of the text; return null if not found or subtext
+ * is empty (start==end). A pair of zeros is returned if pattern is empty string
+ * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc"
+ * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned
+ */
+ public StringMatcher.Position find(String text, int start, int end) {
+ if (text == null)
+ throw new IllegalArgumentException();
+
+ int tlen = text.length();
+ if (start < 0)
+ start = 0;
+ if (end > tlen)
+ end = tlen;
+ if (end < 0 || start >= end)
+ return null;
+ if (fLength == 0)
+ return new Position(start, start);
+ if (fIgnoreWildCards) {
+ int x = posIn(text, start, end);
+ if (x < 0)
+ return null;
+ return new Position(x, x + fLength);
+ }
+
+ int segCount = fSegments.length;
+ if (segCount == 0)// pattern contains only '*'(s)
+ return new Position(start, end);
+
+ int curPos = start;
+ int matchStart = -1;
+ int i;
+ for (i = 0; i < segCount && curPos < end; ++i) {
+ String current = fSegments[i];
+ int nextMatch = regExpPosIn(text, curPos, end, current);
+ if (nextMatch < 0)
+ return null;
+ if (i == 0)
+ matchStart = nextMatch;
+ curPos = nextMatch + current.length();
+ }
+ if (i < segCount)
+ return null;
+ return new Position(matchStart, curPos);
+ }
+
+ /**
+ * match the given text
with the pattern
+ *
+ * @return true if matched eitherwise false
+ * @param text
, a String object
+ */
+ public boolean match(String text) {
+ return match(text, 0, text.length());
+ }
+
+ /**
+ * Given the starting (inclusive) and the ending (exclusive) positions in
+ * the text
, determine if the given substring matches with
+ * aPattern
+ *
+ * @return true if the specified portion of the text matches the pattern
+ * @param String
+ * text
, a String object that contains the
+ * substring to match
+ * @param int
+ * start marks the starting position (inclusive) of the substring
+ * @param int end marks the ending index (exclusive) of the substring
+ */
+ public boolean match(String text, int start, int end) {
+ if (null == text)
+ throw new IllegalArgumentException();
+
+ if (start > end)
+ return false;
+
+ if (fIgnoreWildCards)
+ return (end - start == fLength)
+ && fPattern.regionMatches(fIgnoreCase, 0, text, start,
+ fLength);
+ int segCount = fSegments.length;
+ if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) // pattern
+ // contains
+ // only
+ // '*'(s)
+ return true;
+ if (start == end)
+ return fLength == 0;
+ if (fLength == 0)
+ return start == end;
+
+ int tlen = text.length();
+ if (start < 0)
+ start = 0;
+ if (end > tlen)
+ end = tlen;
+
+ int tCurPos = start;
+ int bound = end - fBound;
+ if (bound < 0)
+ return false;
+ int i = 0;
+ String current = fSegments[i];
+ int segLength = current.length();
+
+ /* process first segment */
+ if (!fHasLeadingStar) {
+ if (!regExpRegionMatches(text, start, current, 0, segLength)) {
+ return false;
+ } else {
+ ++i;
+ tCurPos = tCurPos + segLength;
+ }
+ }
+
+ /* process middle segments */
+ while (i < segCount) {
+ current = fSegments[i];
+ int currentMatch;
+ int k = current.indexOf(fSingleWildCard);
+ if (k < 0) {
+ currentMatch = textPosIn(text, tCurPos, end, current);
+ if (currentMatch < 0)
+ return false;
+ } else {
+ currentMatch = regExpPosIn(text, tCurPos, end, current);
+ if (currentMatch < 0)
+ return false;
+ }
+ tCurPos = currentMatch + current.length();
+ i++;
+ }
+
+ /* process final segment */
+ if (!fHasTrailingStar && tCurPos != end) {
+ int clen = current.length();
+ return regExpRegionMatches(text, end - clen, current, 0, clen);
+ }
+ return i == segCount;
+ }
+
+ /**
+ * This method parses the given pattern into segments seperated by wildcard
+ * '*' characters. Since wildcards are not being used in this case, the
+ * pattern consists of a single segment.
+ */
+ private void parseNoWildCards() {
+ fSegments = new String[1];
+ fSegments[0] = fPattern;
+ fBound = fLength;
+ }
+
+ /**
+ * Parses the given pattern into segments seperated by wildcard '*'
+ * characters.
+ *
+ * @param p,
+ * a String object that is a simple regular expression with �*�
+ * and/or �?�
+ */
+ private void parseWildCards() {
+ if (fPattern.startsWith("*"))//$NON-NLS-1$
+ fHasLeadingStar = true;
+ if (fPattern.endsWith("*")) {//$NON-NLS-1$
+ /* make sure it's not an escaped wildcard */
+ if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
+ fHasTrailingStar = true;
+ }
+ }
+
+ Vector temp = new Vector();
+
+ int pos = 0;
+ StringBuffer buf = new StringBuffer();
+ while (pos < fLength) {
+ char c = fPattern.charAt(pos++);
+ switch (c) {
+ case '\\':
+ if (pos >= fLength) {
+ buf.append(c);
+ } else {
+ char next = fPattern.charAt(pos++);
+ /* if it's an escape sequence */
+ if (next == '*' || next == '?' || next == '\\') {
+ buf.append(next);
+ } else {
+ /* not an escape sequence, just insert literally */
+ buf.append(c);
+ buf.append(next);
+ }
+ }
+ break;
+ case '*':
+ if (buf.length() > 0) {
+ /* new segment */
+ temp.addElement(buf.toString());
+ fBound += buf.length();
+ buf.setLength(0);
+ }
+ break;
+ case '?':
+ /* append special character representing single match wildcard */
+ buf.append(fSingleWildCard);
+ break;
+ default:
+ buf.append(c);
+ }
+ }
+
+ /* add last buffer to segment list */
+ if (buf.length() > 0) {
+ temp.addElement(buf.toString());
+ fBound += buf.length();
+ }
+
+ fSegments = new String[temp.size()];
+ temp.copyInto(fSegments);
+ }
+
+ /**
+ * @param text
, a string which contains no wildcard
+ * @param start
, the starting index in the text for search,
+ * inclusive
+ * @param end
, the stopping point of search, exclusive
+ * @return the starting index in the text of the pattern , or -1 if not
+ * found
+ */
+ protected int posIn(String text, int start, int end) {// no wild card in
+ // pattern
+ int max = end - fLength;
+
+ if (!fIgnoreCase) {
+ int i = text.indexOf(fPattern, start);
+ if (i == -1 || i > max)
+ return -1;
+ return i;
+ }
+
+ for (int i = start; i <= max; ++i) {
+ if (text.regionMatches(true, i, fPattern, 0, fLength))
+ return i;
+ }
+
+ return -1;
+ }
+
+ /**
+ * @param text
, a simple regular expression that may only
+ * contain '?'(s)
+ * @param start
, the starting index in the text for search,
+ * inclusive
+ * @param end
, the stopping point of search, exclusive
+ * @param p
, a simple regular expression that may contains '?'
+ * @param caseIgnored
, wether the pattern is not casesensitive
+ * @return the starting index in the text of the pattern , or -1 if not
+ * found
+ */
+ protected int regExpPosIn(String text, int start, int end, String p) {
+ int plen = p.length();
+
+ int max = end - plen;
+ for (int i = start; i <= max; ++i) {
+ if (regExpRegionMatches(text, i, p, 0, plen))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ *
+ * @return boolean
+ * @param text
, a String to match
+ * @param start
, int that indicates the starting index of
+ * match, inclusive
+ * @param end
int that indicates the ending index of match,
+ * exclusive
+ * @param p
, String, String, a simple regular expression that
+ * may contain '?'
+ * @param ignoreCase
, boolean indicating wether code>p
+ * is case sensitive
+ */
+ protected boolean regExpRegionMatches(String text, int tStart, String p,
+ int pStart, int plen) {
+ while (plen-- > 0) {
+ char tchar = text.charAt(tStart++);
+ char pchar = p.charAt(pStart++);
+
+ /* process wild cards */
+ if (!fIgnoreWildCards) {
+ /* skip single wild cards */
+ if (pchar == fSingleWildCard) {
+ continue;
+ }
+ }
+ if (pchar == tchar)
+ continue;
+ if (fIgnoreCase) {
+ if (Character.toUpperCase(tchar) == Character
+ .toUpperCase(pchar))
+ continue;
+ // comparing after converting to upper case doesn't handle all
+ // cases;
+ // also compare after converting to lower case
+ if (Character.toLowerCase(tchar) == Character
+ .toLowerCase(pchar))
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @param text
, the string to match
+ * @param start
, the starting index in the text for search,
+ * inclusive
+ * @param end
, the stopping point of search, exclusive
+ * @param code>p
+ *
, a string that has no wildcard
+ * @param
+ * ignoreCase
, boolean indicating wether code>p
+ * is case sensitive
+ * @return the starting index in the text of the pattern , or -1 if not
+ * found
+ */
+ protected int textPosIn(String text, int start, int end, String p) {
+
+ int plen = p.length();
+ int max = end - plen;
+
+ if (!fIgnoreCase) {
+ int i = text.indexOf(p, start);
+ if (i == -1 || i > max)
+ return -1;
+ return i;
+ }
+
+ for (int i = start; i <= max; ++i) {
+ if (text.regionMatches(true, i, p, 0, plen))
+ return i;
+ }
+
+ return -1;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TabFolderLayout.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TabFolderLayout.java
new file mode 100644
index 0000000..7c2f0cb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TabFolderLayout.java
@@ -0,0 +1,48 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved
+ */
+package net.sourceforge.phpdt.internal.ui.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+
+public class TabFolderLayout extends Layout {
+
+ protected Point computeSize(Composite composite, int wHint, int hHint,
+ boolean flushCache) {
+ if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT)
+ return new Point(wHint, hHint);
+
+ Control[] children = composite.getChildren();
+ int count = children.length;
+ int maxWidth = 0, maxHeight = 0;
+ for (int i = 0; i < count; i++) {
+ Control child = children[i];
+ Point pt = child.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
+ maxWidth = Math.max(maxWidth, pt.x);
+ maxHeight = Math.max(maxHeight, pt.y);
+ }
+
+ if (wHint != SWT.DEFAULT)
+ maxWidth = wHint;
+ if (hHint != SWT.DEFAULT)
+ maxHeight = hHint;
+
+ return new Point(maxWidth, maxHeight);
+
+ }
+
+ protected void layout(Composite composite, boolean flushCache) {
+ Rectangle rect = composite.getClientArea();
+
+ Control[] children = composite.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ children[i].setBounds(rect);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TableLayoutComposite.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TableLayoutComposite.java
new file mode 100644
index 0000000..9f55883
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TableLayoutComposite.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ColumnLayoutData;
+import org.eclipse.jface.viewers.ColumnPixelData;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * A special composite to layout columns inside a table. The composite is needed
+ * since we have to layout the columns "before" the actual table gets layouted.
+ * Hence we can't use a normal layout manager.
+ */
+public class TableLayoutComposite extends Composite {
+
+ private List columns = new ArrayList();
+
+ /**
+ * Creates a new TableLayoutComposite
.
+ */
+ public TableLayoutComposite(Composite parent, int style) {
+ super(parent, style);
+ addControlListener(new ControlAdapter() {
+ public void controlResized(ControlEvent e) {
+ Rectangle area = getClientArea();
+ Table table = (Table) getChildren()[0];
+ Point preferredSize = computeTableSize(table);
+ int width = area.width - 2 * table.getBorderWidth();
+ if (preferredSize.y > area.height) {
+ // Subtract the scrollbar width from the total column width
+ // if a vertical scrollbar will be required
+ Point vBarSize = table.getVerticalBar().getSize();
+ width -= vBarSize.x;
+ }
+ layoutTable(table, width, area, table.getSize().x < area.width);
+ }
+ });
+ }
+
+ /**
+ * Adds a new column of data to this table layout.
+ *
+ * @param data
+ * the column layout data
+ */
+ public void addColumnData(ColumnLayoutData data) {
+ columns.add(data);
+ }
+
+ // ---- Helpers
+ // -------------------------------------------------------------------------------------
+
+ private Point computeTableSize(Table table) {
+ Point result = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+ int width = 0;
+ int size = columns.size();
+ for (int i = 0; i < size; ++i) {
+ ColumnLayoutData layoutData = (ColumnLayoutData) columns.get(i);
+ if (layoutData instanceof ColumnPixelData) {
+ ColumnPixelData col = (ColumnPixelData) layoutData;
+ width += col.width;
+ } else if (layoutData instanceof ColumnWeightData) {
+ ColumnWeightData col = (ColumnWeightData) layoutData;
+ width += col.minimumWidth;
+ } else {
+ Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
+ }
+ }
+ if (width > result.x)
+ result.x = width;
+ return result;
+ }
+
+ private void layoutTable(Table table, int width, Rectangle area,
+ boolean increase) {
+ // XXX: Layout is being called with an invalid value the first time
+ // it is being called on Linux. This method resets the
+ // Layout to null so we make sure we run it only when
+ // the value is OK.
+ if (width <= 1)
+ return;
+
+ TableColumn[] tableColumns = table.getColumns();
+ int size = Math.min(columns.size(), tableColumns.length);
+ int[] widths = new int[size];
+ int fixedWidth = 0;
+ int numberOfWeightColumns = 0;
+ int totalWeight = 0;
+
+ // First calc space occupied by fixed columns
+ for (int i = 0; i < size; i++) {
+ ColumnLayoutData col = (ColumnLayoutData) columns.get(i);
+ if (col instanceof ColumnPixelData) {
+ int pixels = ((ColumnPixelData) col).width;
+ widths[i] = pixels;
+ fixedWidth += pixels;
+ } else if (col instanceof ColumnWeightData) {
+ ColumnWeightData cw = (ColumnWeightData) col;
+ numberOfWeightColumns++;
+ // first time, use the weight specified by the column data,
+ // otherwise use the actual width as the weight
+ // int weight = firstTime ? cw.weight :
+ // tableColumns[i].getWidth();
+ int weight = cw.weight;
+ totalWeight += weight;
+ } else {
+ Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
+ }
+ }
+
+ // Do we have columns that have a weight
+ if (numberOfWeightColumns > 0) {
+ // Now distribute the rest to the columns with weight.
+ int rest = width - fixedWidth;
+ int totalDistributed = 0;
+ for (int i = 0; i < size; ++i) {
+ ColumnLayoutData col = (ColumnLayoutData) columns.get(i);
+ if (col instanceof ColumnWeightData) {
+ ColumnWeightData cw = (ColumnWeightData) col;
+ // calculate weight as above
+ // int weight = firstTime ? cw.weight :
+ // tableColumns[i].getWidth();
+ int weight = cw.weight;
+ int pixels = totalWeight == 0 ? 0 : weight * rest
+ / totalWeight;
+ if (pixels < cw.minimumWidth)
+ pixels = cw.minimumWidth;
+ totalDistributed += pixels;
+ widths[i] = pixels;
+ }
+ }
+
+ // Distribute any remaining pixels to columns with weight.
+ int diff = rest - totalDistributed;
+ for (int i = 0; diff > 0; ++i) {
+ if (i == size)
+ i = 0;
+ ColumnLayoutData col = (ColumnLayoutData) columns.get(i);
+ if (col instanceof ColumnWeightData) {
+ ++widths[i];
+ --diff;
+ }
+ }
+ }
+
+ if (increase) {
+ table.setSize(area.width, area.height);
+ }
+ for (int i = 0; i < size; i++) {
+ tableColumns[i].setWidth(widths[i]);
+ }
+ if (!increase) {
+ table.setSize(area.width, area.height);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TwoArrayQuickSorter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TwoArrayQuickSorter.java
new file mode 100644
index 0000000..86db922
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/util/TwoArrayQuickSorter.java
@@ -0,0 +1,111 @@
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.util.Comparator;
+
+import org.eclipse.jface.util.Assert;
+
+/**
+ * Quick sort to sort key-value pairs. The keys and arrays are specified in
+ * separate arrays.
+ */
+public class TwoArrayQuickSorter {
+
+ private Comparator fComparator;
+
+ /**
+ * Default comparator.
+ */
+ public static final class StringComparator implements Comparator {
+ private boolean fIgnoreCase;
+
+ StringComparator(boolean ignoreCase) {
+ fIgnoreCase = ignoreCase;
+ }
+
+ public int compare(Object left, Object right) {
+ return fIgnoreCase ? ((String) left)
+ .compareToIgnoreCase((String) right) : ((String) left)
+ .compareTo((String) right);
+ }
+ }
+
+ /**
+ * Creates a sorter with default string comparator. The keys are assumed to
+ * be strings.
+ *
+ * @param ignoreCase
+ * specifies whether sorting is case sensitive or not.
+ */
+ public TwoArrayQuickSorter(boolean ignoreCase) {
+ fComparator = new StringComparator(ignoreCase);
+ }
+
+ /**
+ * Creates a sorter with a comparator.
+ *
+ * @param comparator
+ * the comparator to order the elements. The comparator must not
+ * be null
.
+ */
+ public TwoArrayQuickSorter(Comparator comparator) {
+ fComparator = comparator;
+ }
+
+ /**
+ * Sorts keys and values in parallel.
+ *
+ * @param keys
+ * the keys to use for sorting.
+ * @param values
+ * the values associated with the keys.
+ */
+ public void sort(Object[] keys, Object[] values) {
+ if ((keys == null) || (values == null)) {
+ Assert.isTrue(false, "Either keys or values in null"); //$NON-NLS-1$
+ return;
+ }
+
+ if (keys.length <= 1)
+ return;
+
+ internalSort(keys, values, 0, keys.length - 1);
+ }
+
+ private void internalSort(Object[] keys, Object[] values, int left,
+ int right) {
+ int original_left = left;
+ int original_right = right;
+
+ Object mid = keys[(left + right) / 2];
+ do {
+ while (fComparator.compare(keys[left], mid) < 0)
+ left++;
+
+ while (fComparator.compare(mid, keys[right]) < 0)
+ right--;
+
+ if (left <= right) {
+ swap(keys, left, right);
+ swap(values, left, right);
+ left++;
+ right--;
+ }
+ } while (left <= right);
+
+ if (original_left < right)
+ internalSort(keys, values, original_left, right);
+
+ if (left < original_right)
+ internalSort(keys, values, left, original_right);
+ }
+
+ /*
+ * Swaps x[a] with x[b].
+ */
+ private static final void swap(Object x[], int a, int b) {
+ Object t = x[a];
+ x[a] = x[b];
+ x[b] = t;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/AppearanceAwareLabelProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/AppearanceAwareLabelProvider.java
new file mode 100644
index 0000000..bbed6ac
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/AppearanceAwareLabelProvider.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+
+/**
+ * JavaUILabelProvider that respects settings from the Appearance preference
+ * page. Triggers a viewer update when a preference changes.
+ */
+public class AppearanceAwareLabelProvider extends JavaUILabelProvider implements
+ IPropertyChangeListener {
+
+ public final static int DEFAULT_TEXTFLAGS = JavaElementLabels.ROOT_VARIABLE
+ | JavaElementLabels.M_PARAMETER_TYPES
+ | JavaElementLabels.M_APP_RETURNTYPE
+ | JavaElementLabels.REFERENCED_ROOT_POST_QUALIFIED;
+
+ public final static int DEFAULT_IMAGEFLAGS = JavaElementImageProvider.OVERLAY_ICONS;
+
+ private int fTextFlagMask;
+
+ private int fImageFlagMask;
+
+ /**
+ * Constructor for AppearanceAwareLabelProvider.
+ */
+ public AppearanceAwareLabelProvider(int textFlags, int imageFlags) {
+ super(textFlags, imageFlags);
+ initMasks();
+ PreferenceConstants.getPreferenceStore()
+ .addPropertyChangeListener(this);
+ }
+
+ /**
+ * Creates a labelProvider with DEFAULT_TEXTFLAGS and DEFAULT_IMAGEFLAGS
+ */
+ public AppearanceAwareLabelProvider() {
+ this(DEFAULT_TEXTFLAGS, DEFAULT_IMAGEFLAGS);
+ }
+
+ private void initMasks() {
+ IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+ fTextFlagMask = -1;
+ if (!store.getBoolean(PreferenceConstants.APPEARANCE_METHOD_RETURNTYPE)) {
+ fTextFlagMask ^= JavaElementLabels.M_APP_RETURNTYPE;
+ }
+ if (!store
+ .getBoolean(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES)) {
+ fTextFlagMask ^= JavaElementLabels.P_COMPRESSED;
+ }
+
+ fImageFlagMask = -1;
+ }
+
+ /*
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.equals(PreferenceConstants.APPEARANCE_METHOD_RETURNTYPE)
+ || property
+ .equals(PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW)
+ || property
+ .equals(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES)) {
+ initMasks();
+ LabelProviderChangedEvent lpEvent = new LabelProviderChangedEvent(
+ this, null); // refresh all
+ fireLabelProviderChanged(lpEvent);
+ }
+ }
+
+ /*
+ * @see IBaseLabelProvider#dispose()
+ */
+ public void dispose() {
+ PreferenceConstants.getPreferenceStore().removePropertyChangeListener(
+ this);
+ super.dispose();
+ }
+
+ /*
+ * @see JavaUILabelProvider#evaluateImageFlags()
+ */
+ protected int evaluateImageFlags(Object element) {
+ return getImageFlags() & fImageFlagMask;
+ }
+
+ /*
+ * @see JavaUILabelProvider#evaluateTextFlags()
+ */
+ protected int evaluateTextFlags(Object element) {
+ return getTextFlags() & fTextFlagMask;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ContainerCheckedTreeViewer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ContainerCheckedTreeViewer.java
new file mode 100644
index 0000000..0bd7141
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ContainerCheckedTreeViewer.java
@@ -0,0 +1,181 @@
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ITreeViewerListener;
+import org.eclipse.jface.viewers.TreeExpansionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * CheckboxTreeViewer with special behaviour of the checked / gray state on
+ * container (non-leaf) nodes: The grayed state is used to visualize the checked
+ * state of its children. Containers are checked and non-gary if all contained
+ * leafs are checked. The container is grayed if some but not all leafs are
+ * checked.
+ */
+public class ContainerCheckedTreeViewer extends CheckboxTreeViewer {
+
+ /**
+ * Constructor for ContainerCheckedTreeViewer.
+ *
+ * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite)
+ */
+ public ContainerCheckedTreeViewer(Composite parent) {
+ super(parent);
+ initViewer();
+ }
+
+ /**
+ * Constructor for ContainerCheckedTreeViewer.
+ *
+ * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite,int)
+ */
+ public ContainerCheckedTreeViewer(Composite parent, int style) {
+ super(parent, style);
+ initViewer();
+ }
+
+ /**
+ * Constructor for ContainerCheckedTreeViewer.
+ *
+ * @see CheckboxTreeViewer#CheckboxTreeViewer(Tree)
+ */
+ public ContainerCheckedTreeViewer(Tree tree) {
+ super(tree);
+ initViewer();
+ }
+
+ private void initViewer() {
+ setUseHashlookup(true);
+ addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ doCheckStateChanged(event.getElement());
+ }
+ });
+ addTreeListener(new ITreeViewerListener() {
+ public void treeCollapsed(TreeExpansionEvent event) {
+ }
+
+ public void treeExpanded(TreeExpansionEvent event) {
+ Widget item = findItem(event.getElement());
+ if (item instanceof TreeItem) {
+ initializeItem((TreeItem) item);
+ }
+ }
+ });
+ }
+
+ protected void doCheckStateChanged(Object element) {
+ Widget item = findItem(element);
+ if (item instanceof TreeItem) {
+ TreeItem treeItem = (TreeItem) item;
+ treeItem.setGrayed(false);
+ updateChildrenItems(treeItem);
+ updateParentItems(treeItem.getParentItem());
+ }
+ }
+
+ /**
+ * The item has expanded. Updates the checked state of its children.
+ */
+ private void initializeItem(TreeItem item) {
+ if (item.getChecked() && !item.getGrayed()) {
+ updateChildrenItems((TreeItem) item);
+ }
+ }
+
+ /**
+ * Updates the check state of all created children
+ */
+ private void updateChildrenItems(TreeItem parent) {
+ Item[] children = getChildren(parent);
+ boolean state = parent.getChecked();
+ for (int i = 0; i < children.length; i++) {
+ TreeItem curr = (TreeItem) children[i];
+ if (curr.getData() != null
+ && ((curr.getChecked() != state) || curr.getGrayed())) {
+ curr.setChecked(state);
+ curr.setGrayed(false);
+ updateChildrenItems(curr);
+ }
+ }
+ }
+
+ /**
+ * Updates the check / gray state of all parent items
+ */
+ private void updateParentItems(TreeItem item) {
+ if (item != null) {
+ Item[] children = getChildren(item);
+ boolean containsChecked = false;
+ boolean containsUnchecked = false;
+ for (int i = 0; i < children.length; i++) {
+ TreeItem curr = (TreeItem) children[i];
+ containsChecked |= curr.getChecked();
+ containsUnchecked |= (!curr.getChecked() || curr.getGrayed());
+ }
+ item.setChecked(containsChecked);
+ item.setGrayed(containsChecked && containsUnchecked);
+ updateParentItems(item.getParentItem());
+ }
+ }
+
+ public boolean setChecked(Object element, boolean state) {
+ if (super.setChecked(element, state)) {
+ doCheckStateChanged(element);
+ return true;
+ }
+ return false;
+ }
+
+ public void setCheckedElements(Object[] elements) {
+ super.setCheckedElements(elements);
+ for (int i = 0; i < elements.length; i++) {
+ doCheckStateChanged(elements[i]);
+ }
+ }
+
+ protected void setExpanded(Item item, boolean expand) {
+ super.setExpanded(item, expand);
+ if (expand && item instanceof TreeItem) {
+ initializeItem((TreeItem) item);
+ }
+ }
+
+ public Object[] getCheckedElements() {
+ Object[] checked = super.getCheckedElements();
+ // add all items that are children of a checked node but not created yet
+ ArrayList result = new ArrayList();
+ for (int i = 0; i < checked.length; i++) {
+ Object curr = checked[i];
+ result.add(curr);
+ Widget item = findItem(curr);
+ if (item != null) {
+ Item[] children = getChildren(item);
+ // check if contains the dummy node
+ if (children.length == 1 && children[0].getData() == null) {
+ // not yet created
+ collectChildren(curr, result);
+ }
+ }
+ }
+ return result.toArray();
+ }
+
+ private void collectChildren(Object element, ArrayList result) {
+ Object[] filteredChildren = getFilteredChildren(element);
+ for (int i = 0; i < filteredChildren.length; i++) {
+ Object curr = filteredChildren[i];
+ result.add(curr);
+ collectChildren(curr, result);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/DecoratingJavaLabelProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/DecoratingJavaLabelProvider.java
new file mode 100644
index 0000000..268cfaf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/DecoratingJavaLabelProvider.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import net.sourceforge.phpdt.ui.OverrideIndicatorLabelDecorator;
+import net.sourceforge.phpdt.ui.ProblemsLabelDecorator;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IDecoratorManager;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Decorator prepared for the switch to use lightweight label decorators:
+ * uncomment the lbale decorator entries in plugin.xml and change
+ * USE_LIGHTWEIGHT to true. Certain views don't want problems or override
+ * indicators, so they signal this in the constructor. So on each getImage the
+ * corrsponding decorators are turned off and on again.
+ */
+public class DecoratingJavaLabelProvider extends DecoratingLabelProvider {
+
+ private static final boolean USE_LIGHTWEIGHT = false;
+
+ private static final String PROBLEM_DECORATOR_ID = "net.sourceforge.phpdt.ui.problem.decorator"; //$NON-NLS-1$
+
+ private static final String OVERRIDE_DECORATOR_ID = "net.sourceforge.phpdt.ui.override.decorator"; //$NON-NLS-1$
+
+ private boolean fUseErrorTick;
+
+ private boolean fUseOverride;
+
+ /**
+ * Decorating label provider for Java. Combines a JavaUILabelProvider with
+ * problem and override indicuator with the workbench decorator (label
+ * decorator extension point).
+ */
+ public DecoratingJavaLabelProvider(JavaUILabelProvider labelProvider) {
+ this(labelProvider, true, true);
+ }
+
+ /**
+ * Decorating label provider for Java. Combines a JavaUILabelProvider (if
+ * enabled with problem and override indicator) with the workbench decorator
+ * (label decorator extension point).
+ */
+ public DecoratingJavaLabelProvider(JavaUILabelProvider labelProvider,
+ boolean errorTick, boolean override) {
+ super(labelProvider, PlatformUI.getWorkbench().getDecoratorManager()
+ .getLabelDecorator());
+ fUseErrorTick = errorTick;
+ fUseOverride = override;
+ if (!USE_LIGHTWEIGHT) {
+ if (errorTick) {
+ labelProvider
+ .addLabelDecorator(new ProblemsLabelDecorator(null));
+ }
+ if (override) {
+ labelProvider
+ .addLabelDecorator(new OverrideIndicatorLabelDecorator(
+ null));
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ if (USE_LIGHTWEIGHT) {
+ IDecoratorManager manager = PlatformUI.getWorkbench()
+ .getDecoratorManager();
+
+ boolean disableErrorTick = manager.getEnabled(PROBLEM_DECORATOR_ID)
+ && !fUseErrorTick;
+ boolean disableOverride = manager.getEnabled(OVERRIDE_DECORATOR_ID)
+ && !fUseOverride;
+ try {
+ if (disableErrorTick) {
+ manager.setEnabled(PROBLEM_DECORATOR_ID, false);
+ }
+ if (disableOverride) {
+ manager.setEnabled(OVERRIDE_DECORATOR_ID, false);
+ }
+ Image image = super.getImage(element);
+ if (disableErrorTick) {
+ manager.setEnabled(PROBLEM_DECORATOR_ID, true);
+ }
+ if (disableOverride) {
+ manager.setEnabled(OVERRIDE_DECORATOR_ID, true);
+ }
+ return image;
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ return super.getImage(element);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ if (USE_LIGHTWEIGHT) {
+ IDecoratorManager manager = PlatformUI.getWorkbench()
+ .getDecoratorManager();
+
+ boolean disableErrorTick = manager.getEnabled(PROBLEM_DECORATOR_ID)
+ && !fUseErrorTick;
+ boolean disableOverride = manager.getEnabled(OVERRIDE_DECORATOR_ID)
+ && !fUseOverride;
+ try {
+ if (disableErrorTick) {
+ manager.setEnabled(PROBLEM_DECORATOR_ID, false);
+ }
+ if (disableOverride) {
+ manager.setEnabled(OVERRIDE_DECORATOR_ID, false);
+ }
+ String text = super.getText(element);
+ if (disableErrorTick) {
+ manager.setEnabled(PROBLEM_DECORATOR_ID, true);
+ }
+ if (disableOverride) {
+ manager.setEnabled(OVERRIDE_DECORATOR_ID, true);
+ }
+ return text;
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ return super.getText(element);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/FilterUpdater.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/FilterUpdater.java
new file mode 100644
index 0000000..f115b51
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/FilterUpdater.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.widgets.Control;
+
+public class FilterUpdater implements IResourceChangeListener {
+
+ private StructuredViewer fViewer;
+
+ public FilterUpdater(StructuredViewer viewer) {
+ Assert.isNotNull(viewer);
+ fViewer = viewer;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+ */
+ public void resourceChanged(IResourceChangeEvent event) {
+ IResourceDelta delta = event.getDelta();
+ if (delta == null)
+ return;
+
+ IResourceDelta[] projDeltas = delta
+ .getAffectedChildren(IResourceDelta.CHANGED);
+ for (int i = 0; i < projDeltas.length; i++) {
+ IResourceDelta pDelta = projDeltas[i];
+ if ((pDelta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
+ final Control ctrl = fViewer.getControl();
+ if (ctrl != null && !ctrl.isDisposed()) {
+ // async is needed due to bug 33783
+ ctrl.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (!ctrl.isDisposed())
+ fViewer.refresh(false);
+ }
+ });
+ }
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/IProblemChangedListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/IProblemChangedListener.java
new file mode 100644
index 0000000..948ba8c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/IProblemChangedListener.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import org.eclipse.core.resources.IResource;
+
+/**
+ * Can be added to a ProblemMarkerManager to get notified about problem marker
+ * changes. Used to update error ticks.
+ */
+public interface IProblemChangedListener {
+
+ /**
+ * Called when problems changed. This call is posted in an aynch exec,
+ * therefore passed resources must not exist.
+ *
+ * @param changedElements
+ * A set with elements of type IResource
that
+ * describe the resources that had an problem change.
+ * @param isMarkerChange
+ * If set to true
, the change was a marker
+ * change, if false
, the change came from an
+ * annotation model modification.
+ */
+ void problemsChanged(IResource[] changedResources, boolean isMarkerChange);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ISelectionListenerWithAST.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ISelectionListenerWithAST.java
new file mode 100644
index 0000000..4bd1312
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ISelectionListenerWithAST.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Listener to be informed on text selection changes in an editor (post
+ * selection), including the corresponding AST. The AST is shared and must not
+ * be modified. Listeners can be registered in a
+ * SelectionListenerWithASTManager
.
+ */
+public interface ISelectionListenerWithAST {
+
+ /**
+ * Called when a selection has changed. The method is called in a post
+ * selection event in an background thread.
+ *
+ * @param part
+ * The editor part in which the selection change has occured.
+ * @param selection
+ * The new text selection
+ * @param astRoot
+ * The AST tree corresponding to the editor's input. This AST is
+ * shared and must not be modified.
+ */
+ void selectionChanged(IEditorPart part, ITextSelection selection);
+ // void selectionChanged(IEditorPart part, ITextSelection selection,
+ // CompilationUnit astRoot);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/IViewPartInputProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/IViewPartInputProvider.java
new file mode 100644
index 0000000..137cd08
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/IViewPartInputProvider.java
@@ -0,0 +1,15 @@
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+/**
+ * Interface common to all view parts that provide an input.
+ */
+public interface IViewPartInputProvider {
+
+ /**
+ * Returns the input.
+ *
+ * @return the input object
+ */
+ public Object getViewPartInput();
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ImageDescriptorRegistry.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ImageDescriptorRegistry.java
new file mode 100644
index 0000000..5e1d19d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ImageDescriptorRegistry.java
@@ -0,0 +1,91 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A registry that maps ImageDescriptors
to Image
.
+ */
+public class ImageDescriptorRegistry {
+
+ private HashMap fRegistry = new HashMap(10);
+
+ private Display fDisplay;
+
+ /**
+ * Creates a new image descriptor registry for the current or default
+ * display, respectively.
+ */
+ public ImageDescriptorRegistry() {
+ this(SWTUtil.getStandardDisplay());
+ }
+
+ /**
+ * Creates a new image descriptor registry for the given display. All images
+ * managed by this registry will be disposed when the display gets disposed.
+ *
+ * @param diaplay
+ * the display the images managed by this registry are allocated
+ * for
+ */
+ public ImageDescriptorRegistry(Display display) {
+ fDisplay = display;
+ Assert.isNotNull(fDisplay);
+ hookDisplay();
+ }
+
+ /**
+ * Returns the image assiciated with the given image descriptor.
+ *
+ * @param descriptor
+ * the image descriptor for which the registry manages an image
+ * @return the image associated with the image descriptor or
+ * null
if the image descriptor can't create the
+ * requested image.
+ */
+ public Image get(ImageDescriptor descriptor) {
+ if (descriptor == null)
+ descriptor = ImageDescriptor.getMissingImageDescriptor();
+
+ Image result = (Image) fRegistry.get(descriptor);
+ if (result != null)
+ return result;
+
+ Assert.isTrue(fDisplay == SWTUtil.getStandardDisplay(),
+ "Allocating image for wrong display."); //$NON-NLS-1$
+ result = descriptor.createImage();
+ if (result != null)
+ fRegistry.put(descriptor, result);
+ return result;
+ }
+
+ /**
+ * Disposes all images managed by this registry.
+ */
+ public void dispose() {
+ for (Iterator iter = fRegistry.values().iterator(); iter.hasNext();) {
+ Image image = (Image) iter.next();
+ image.dispose();
+ }
+ fRegistry.clear();
+ }
+
+ private void hookDisplay() {
+ fDisplay.disposeExec(new Runnable() {
+ public void run() {
+ dispose();
+ }
+ });
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ImageImageDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ImageImageDescriptor.java
new file mode 100644
index 0000000..f49ca9f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ImageImageDescriptor.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+
+/**
+ */
+public class ImageImageDescriptor extends ImageDescriptor {
+
+ private Image fImage;
+
+ /**
+ * Constructor for ImagImageDescriptor.
+ */
+ public ImageImageDescriptor(Image image) {
+ super();
+ fImage = image;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ImageDescriptor#getImageData()
+ */
+ public ImageData getImageData() {
+ return fImage.getImageData();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see Object#equals(Object)
+ */
+ public boolean equals(Object obj) {
+ return (obj != null) && getClass().equals(obj.getClass())
+ && fImage.equals(((ImageImageDescriptor) obj).fImage);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ return fImage.hashCode();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaElementImageProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaElementImageProvider.java
new file mode 100644
index 0000000..f0b4ca1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaElementImageProvider.java
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.core.IField;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.ui.JavaElementImageDescriptor;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.ide.IDE.SharedImages;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * Default strategy of the Java plugin for the construction of Java element
+ * icons.
+ */
+public class JavaElementImageProvider {
+
+ /**
+ * Flags for the JavaImageLabelProvider: Generate images with overlays.
+ */
+ public final static int OVERLAY_ICONS = 0x1;
+
+ /**
+ * Generate small sized images.
+ */
+ public final static int SMALL_ICONS = 0x2;
+
+ /**
+ * Use the 'light' style for rendering types.
+ */
+ public final static int LIGHT_TYPE_ICONS = 0x4;
+
+ public static final Point SMALL_SIZE = new Point(16, 16);
+
+ public static final Point BIG_SIZE = new Point(22, 16);
+
+ private static ImageDescriptor DESC_OBJ_PROJECT_CLOSED;
+
+ private static ImageDescriptor DESC_OBJ_PROJECT;
+
+ private static ImageDescriptor DESC_OBJ_FOLDER;
+ {
+ ISharedImages images = WebUI.getDefault().getWorkbench()
+ .getSharedImages();
+ DESC_OBJ_PROJECT_CLOSED = images
+ .getImageDescriptor(SharedImages.IMG_OBJ_PROJECT_CLOSED);
+ DESC_OBJ_PROJECT = images
+ .getImageDescriptor(SharedImages.IMG_OBJ_PROJECT);
+ DESC_OBJ_FOLDER = images
+ .getImageDescriptor(ISharedImages.IMG_OBJ_FOLDER);
+ }
+
+ private ImageDescriptorRegistry fRegistry;
+
+ public JavaElementImageProvider() {
+ fRegistry = null; // lazy initialization
+ }
+
+ /**
+ * Returns the icon for a given element. The icon depends on the element
+ * type and element properties. If configured, overlay icons are constructed
+ * for ISourceReference
s.
+ *
+ * @param flags
+ * Flags as defined by the JavaImageLabelProvider
+ */
+ public Image getImageLabel(Object element, int flags) {
+ return getImageLabel(computeDescriptor(element, flags));
+ }
+
+ private Image getImageLabel(ImageDescriptor descriptor) {
+ if (descriptor == null)
+ return null;
+ return getRegistry().get(descriptor);
+ }
+
+ private ImageDescriptorRegistry getRegistry() {
+ if (fRegistry == null) {
+ fRegistry = WebUI.getImageDescriptorRegistry();
+ }
+ return fRegistry;
+ }
+
+ private ImageDescriptor computeDescriptor(Object element, int flags) {
+ if (element instanceof IJavaElement) {
+ return getJavaImageDescriptor((IJavaElement) element, flags);
+ } else if (element instanceof IFile) {
+ IFile file = (IFile) element;
+ if ("java".equals(file.getFileExtension())) { //$NON-NLS-1$
+ return getCUResourceImageDescriptor(file, flags); // image for
+ // a CU not
+ // on the
+ // build
+ // path
+ }
+ return getWorkbenchImageDescriptor(file, flags);
+ } else if (element instanceof IAdaptable) {
+ return getWorkbenchImageDescriptor((IAdaptable) element, flags);
+ }
+ return null;
+ }
+
+ private static boolean showOverlayIcons(int flags) {
+ return (flags & OVERLAY_ICONS) != 0;
+ }
+
+ private static boolean useSmallSize(int flags) {
+ return (flags & SMALL_ICONS) != 0;
+ }
+
+ private static boolean useLightIcons(int flags) {
+ return (flags & LIGHT_TYPE_ICONS) != 0;
+ }
+
+ /**
+ * Returns an image descriptor for a compilatio unit not on the class path.
+ * The descriptor includes overlays, if specified.
+ */
+ public ImageDescriptor getCUResourceImageDescriptor(IFile file, int flags) {
+ Point size = useSmallSize(flags) ? SMALL_SIZE : BIG_SIZE;
+ return new JavaElementImageDescriptor(
+ PHPUiImages.DESC_OBJS_CUNIT_RESOURCE, 0, size);
+ }
+
+ /**
+ * Returns an image descriptor for a java element. The descriptor includes
+ * overlays, if specified.
+ */
+ public ImageDescriptor getJavaImageDescriptor(IJavaElement element,
+ int flags) {
+ int adornmentFlags = computeJavaAdornmentFlags(element, flags);
+ Point size = useSmallSize(flags) ? SMALL_SIZE : BIG_SIZE;
+ return new JavaElementImageDescriptor(getBaseImageDescriptor(element,
+ flags), adornmentFlags, size);
+ }
+
+ /**
+ * Returns an image descriptor for a IAdaptable. The descriptor includes
+ * overlays, if specified (only error ticks apply). Returns
+ * null
if no image could be found.
+ */
+ public ImageDescriptor getWorkbenchImageDescriptor(IAdaptable adaptable,
+ int flags) {
+ IWorkbenchAdapter wbAdapter = (IWorkbenchAdapter) adaptable
+ .getAdapter(IWorkbenchAdapter.class);
+ if (wbAdapter == null) {
+ return null;
+ }
+ ImageDescriptor descriptor = wbAdapter.getImageDescriptor(adaptable);
+ if (descriptor == null) {
+ return null;
+ }
+
+ Point size = useSmallSize(flags) ? SMALL_SIZE : BIG_SIZE;
+ return new JavaElementImageDescriptor(descriptor, 0, size);
+ }
+
+ // ---- Computation of base image key
+ // -------------------------------------------------
+
+ /**
+ * Returns an image descriptor for a java element. This is the base image,
+ * no overlays.
+ */
+ public ImageDescriptor getBaseImageDescriptor(IJavaElement element,
+ int renderFlags) {
+ IType type = null;
+ boolean isInterface = false;
+ try {
+ switch (element.getElementType()) {
+ case IJavaElement.INITIALIZER:
+ return PHPUiImages.DESC_MISC_PRIVATE; // 23479
+ case IJavaElement.METHOD:
+ IMember member = (IMember) element;
+ type = member.getDeclaringType();
+ isInterface = (type != null)
+ && member.getDeclaringType().isInterface();
+ return getMethodImageDescriptor(isInterface, member.getFlags());
+ case IJavaElement.FIELD:
+ IField field = (IField) element;
+ return getFieldImageDescriptor(field.getDeclaringType()
+ .isInterface(), field.getFlags());
+
+ case IJavaElement.PACKAGE_DECLARATION:
+ return PHPUiImages.DESC_OBJS_PACKDECL;
+
+ case IJavaElement.IMPORT_DECLARATION:
+ return PHPUiImages.DESC_OBJS_IMPDECL;
+
+ case IJavaElement.IMPORT_CONTAINER:
+ return PHPUiImages.DESC_OBJS_IMPCONT;
+
+ case IJavaElement.TYPE: {
+ type = (IType) element;
+ isInterface = type.isInterface();
+
+ if (useLightIcons(renderFlags)) {
+ return isInterface ? PHPUiImages.DESC_OBJS_INTERFACEALT
+ : PHPUiImages.DESC_OBJS_CLASSALT;
+ }
+ boolean isInner = type.getDeclaringType() != null;
+ return getTypeImageDescriptor(isInterface, isInner, type
+ .getFlags());
+ }
+
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT: {
+ IPackageFragmentRoot root = (IPackageFragmentRoot) element;
+ // if (root.isArchive()) {
+ // IPath attach= root.getSourceAttachmentPath();
+ // if (root.isExternal()) {
+ // if (attach == null) {
+ // return PHPUiImages.DESC_OBJS_EXTJAR;
+ // } else {
+ // return PHPUiImages.DESC_OBJS_EXTJAR_WSRC;
+ // }
+ // } else {
+ // if (attach == null) {
+ // return PHPUiImages.DESC_OBJS_JAR;
+ // } else {
+ // return PHPUiImages.DESC_OBJS_JAR_WSRC;
+ // }
+ // }
+ // } else {
+ return PHPUiImages.DESC_OBJS_PACKFRAG_ROOT;
+ // }
+ }
+
+ case IJavaElement.PACKAGE_FRAGMENT:
+ return getPackageFragmentIcon(element, renderFlags);
+
+ case IJavaElement.COMPILATION_UNIT:
+ return PHPUiImages.DESC_OBJS_CUNIT;
+
+ case IJavaElement.CLASS_FILE:
+ /*
+ * this is too expensive for large packages try { IClassFile
+ * cfile= (IClassFile)element; if (cfile.isClass()) return
+ * PHPUiImages.IMG_OBJS_CFILECLASS; return
+ * PHPUiImages.IMG_OBJS_CFILEINT; } catch(JavaModelException e) { //
+ * fall through; }
+ */
+ return PHPUiImages.DESC_OBJS_CFILE;
+
+ case IJavaElement.JAVA_PROJECT:
+ IJavaProject jp = (IJavaProject) element;
+ if (jp.getProject().isOpen()) {
+ IProject project = jp.getProject();
+ IWorkbenchAdapter adapter = (IWorkbenchAdapter) project
+ .getAdapter(IWorkbenchAdapter.class);
+ if (adapter != null) {
+ ImageDescriptor result = adapter
+ .getImageDescriptor(project);
+ if (result != null)
+ return result;
+ }
+ return DESC_OBJ_PROJECT;
+ }
+ return DESC_OBJ_PROJECT_CLOSED;
+
+ case IJavaElement.JAVA_MODEL:
+ return PHPUiImages.DESC_OBJS_JAVA_MODEL;
+ }
+
+ Assert.isTrue(false, PHPUIMessages
+ .getString("JavaImageLabelprovider.assert.wrongImage")); //$NON-NLS-1$
+ return null; //$NON-NLS-1$
+
+ } catch (JavaModelException e) {
+ if (e.isDoesNotExist())
+ return PHPUiImages.DESC_OBJS_UNKNOWN;
+ PHPeclipsePlugin.log(e);
+ return PHPUiImages.DESC_OBJS_GHOST;
+ }
+ }
+
+ protected ImageDescriptor getPackageFragmentIcon(IJavaElement element,
+ int renderFlags) throws JavaModelException {
+ // IPackageFragment fragment= (IPackageFragment)element;
+ // boolean containsJavaElements= false;
+ // try {
+ // containsJavaElements= fragment.hasChildren();
+ // } catch(JavaModelException e) {
+ // // assuming no children;
+ // }
+ // if(!containsJavaElements && (fragment.getNonJavaResources().length >
+ // 0))
+ // return PHPUiImages.DESC_OBJS_EMPTY_PACKAGE_RESOURCES;
+ // else if (!containsJavaElements)
+ // return PHPUiImages.DESC_OBJS_EMPTY_PACKAGE;
+ return PHPUiImages.DESC_OBJS_PACKAGE;
+ }
+
+ public void dispose() {
+ }
+
+ // ---- Methods to compute the adornments flags
+ // ---------------------------------
+
+ private int computeJavaAdornmentFlags(IJavaElement element, int renderFlags) {
+ int flags = 0;
+ if (showOverlayIcons(renderFlags) && element instanceof IMember) {
+ try {
+ IMember member = (IMember) element;
+
+ if (element.getElementType() == IJavaElement.METHOD
+ && ((IMethod) element).isConstructor())
+ flags |= JavaElementImageDescriptor.CONSTRUCTOR;
+
+ int modifiers = member.getFlags();
+ if (Flags.isAbstract(modifiers) && confirmAbstract(member))
+ flags |= JavaElementImageDescriptor.ABSTRACT;
+ if (Flags.isFinal(modifiers) || isInterfaceField(member))
+ flags |= JavaElementImageDescriptor.FINAL;
+ // if (Flags.isSynchronized(modifiers) &&
+ // confirmSynchronized(member))
+ // flags |= JavaElementImageDescriptor.SYNCHRONIZED;
+ if (Flags.isStatic(modifiers) || isInterfaceField(member))
+ flags |= JavaElementImageDescriptor.STATIC;
+
+ // if (member.getElementType() == IJavaElement.TYPE) {
+ // if (JavaModelUtil.hasMainMethod((IType) member)) {
+ // flags |= JavaElementImageDescriptor.RUNNABLE;
+ // }
+ // }
+ } catch (JavaModelException e) {
+ // do nothing. Can't compute runnable adornment or get flags
+ }
+ }
+ return flags;
+ }
+
+ private static boolean confirmAbstract(IMember element)
+ throws JavaModelException {
+ // never show the abstract symbol on interfaces or members in interfaces
+ if (element.getElementType() == IJavaElement.TYPE) {
+ return ((IType) element).isClass();
+ }
+ return element.getDeclaringType().isClass();
+ }
+
+ private static boolean isInterfaceField(IMember element)
+ throws JavaModelException {
+ // always show the final && static symbol on interface fields
+ if (element.getElementType() == IJavaElement.FIELD) {
+ return element.getDeclaringType().isInterface();
+ }
+ return false;
+ }
+
+ private static boolean confirmSynchronized(IJavaElement member) {
+ // Synchronized types are allowed but meaningless.
+ return member.getElementType() != IJavaElement.TYPE;
+ }
+
+ public static ImageDescriptor getMethodImageDescriptor(
+ boolean isInInterface, int flags) {
+ if (Flags.isPublic(flags) || isInInterface)
+ return PHPUiImages.DESC_MISC_PUBLIC;
+ if (Flags.isProtected(flags))
+ return PHPUiImages.DESC_MISC_PROTECTED;
+ if (Flags.isPrivate(flags))
+ return PHPUiImages.DESC_MISC_PRIVATE;
+
+ return PHPUiImages.DESC_MISC_DEFAULT;
+ }
+
+ public static ImageDescriptor getFieldImageDescriptor(
+ boolean isInInterface, int flags) {
+ if (Flags.isPublic(flags) || isInInterface)
+ return PHPUiImages.DESC_FIELD_PUBLIC;
+ if (Flags.isProtected(flags))
+ return PHPUiImages.DESC_FIELD_PROTECTED;
+ if (Flags.isPrivate(flags))
+ return PHPUiImages.DESC_FIELD_PRIVATE;
+
+ return PHPUiImages.DESC_FIELD_DEFAULT;
+ }
+
+ public static ImageDescriptor getTypeImageDescriptor(boolean isInterface,
+ boolean isInner, int flags) {
+ if (isInner) {
+ if (isInterface) {
+ return getInnerInterfaceImageDescriptor(flags);
+ } else {
+ return getInnerClassImageDescriptor(flags);
+ }
+ } else {
+ if (isInterface) {
+ return getInterfaceImageDescriptor(flags);
+ } else {
+ return getClassImageDescriptor(flags);
+ }
+ }
+ }
+
+ private static ImageDescriptor getClassImageDescriptor(int flags) {
+ if (Flags.isPublic(flags) || Flags.isProtected(flags)
+ || Flags.isPrivate(flags))
+ return PHPUiImages.DESC_OBJS_CLASS;
+ else
+ return PHPUiImages.DESC_OBJS_CLASS_DEFAULT;
+ }
+
+ private static ImageDescriptor getInnerClassImageDescriptor(int flags) {
+ if (Flags.isPublic(flags))
+ return PHPUiImages.DESC_OBJS_INNER_CLASS_PUBLIC;
+ else if (Flags.isPrivate(flags))
+ return PHPUiImages.DESC_OBJS_INNER_CLASS_PRIVATE;
+ else if (Flags.isProtected(flags))
+ return PHPUiImages.DESC_OBJS_INNER_CLASS_PROTECTED;
+ else
+ return PHPUiImages.DESC_OBJS_INNER_CLASS_DEFAULT;
+ }
+
+ private static ImageDescriptor getInterfaceImageDescriptor(int flags) {
+ if (Flags.isPublic(flags) || Flags.isProtected(flags)
+ || Flags.isPrivate(flags))
+ return PHPUiImages.DESC_OBJS_INTERFACE;
+ else
+ return PHPUiImages.DESC_OBJS_INTERFACE_DEFAULT;
+ }
+
+ private static ImageDescriptor getInnerInterfaceImageDescriptor(int flags) {
+ if (Flags.isPublic(flags))
+ return PHPUiImages.DESC_OBJS_INNER_INTERFACE_PUBLIC;
+ else if (Flags.isPrivate(flags))
+ return PHPUiImages.DESC_OBJS_INNER_INTERFACE_PRIVATE;
+ else if (Flags.isProtected(flags))
+ return PHPUiImages.DESC_OBJS_INNER_INTERFACE_PROTECTED;
+ else
+ return PHPUiImages.DESC_OBJS_INTERFACE_DEFAULT;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaElementLabels.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaElementLabels.java
new file mode 100644
index 0000000..801580e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaElementLabels.java
@@ -0,0 +1,811 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IField;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.Signature;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+public class JavaElementLabels {
+
+ /**
+ * Method names contain parameter types. e.g. foo(int)
+ */
+ public final static int M_PARAMETER_TYPES = 1 << 0;
+
+ /**
+ * Method names contain parameter names. e.g. foo(index)
+ */
+ public final static int M_PARAMETER_NAMES = 1 << 1;
+
+ /**
+ * Method names contain thrown exceptions. e.g.
+ * foo throws IOException
+ */
+ public final static int M_EXCEPTIONS = 1 << 2;
+
+ /**
+ * Method names contain return type (appended) e.g. foo : int
+ */
+ public final static int M_APP_RETURNTYPE = 1 << 3;
+
+ /**
+ * Method names contain return type (appended) e.g. int foo
+ */
+ public final static int M_PRE_RETURNTYPE = 1 << 4;
+
+ /**
+ * Method names are fully qualified. e.g. java.util.Vector.size
+ */
+ public final static int M_FULLY_QUALIFIED = 1 << 5;
+
+ /**
+ * Method names are post qualified. e.g.
+ * size - java.util.Vector
+ */
+ public final static int M_POST_QUALIFIED = 1 << 6;
+
+ /**
+ * Initializer names are fully qualified. e.g.
+ * java.util.Vector.{ ... }
+ */
+ public final static int I_FULLY_QUALIFIED = 1 << 7;
+
+ /**
+ * Type names are post qualified. e.g. { ... } - java.util.Map
+ */
+ public final static int I_POST_QUALIFIED = 1 << 8;
+
+ /**
+ * Field names contain the declared type (appended) e.g.
+ * int fHello
+ */
+ public final static int F_APP_TYPE_SIGNATURE = 1 << 9;
+
+ /**
+ * Field names contain the declared type (prepended) e.g.
+ * fHello : int
+ */
+ public final static int F_PRE_TYPE_SIGNATURE = 1 << 10;
+
+ /**
+ * Fields names are fully qualified. e.g. java.lang.System.out
+ */
+ public final static int F_FULLY_QUALIFIED = 1 << 11;
+
+ /**
+ * Fields names are post qualified. e.g. out - java.lang.System
+ */
+ public final static int F_POST_QUALIFIED = 1 << 12;
+
+ /**
+ * Type names are fully qualified. e.g. java.util.Map.MapEntry
+ */
+ public final static int T_FULLY_QUALIFIED = 1 << 13;
+
+ /**
+ * Type names are type container qualified. e.g. Map.MapEntry
+ */
+ public final static int T_CONTAINER_QUALIFIED = 1 << 14;
+
+ /**
+ * Type names are post qualified. e.g. MapEntry - java.util.Map
+ */
+ public final static int T_POST_QUALIFIED = 1 << 15;
+
+ /**
+ * Declarations (import container / declarartion, package declarartion) are
+ * qualified. e.g. java.util.Vector.class/import container
+ */
+ public final static int D_QUALIFIED = 1 << 16;
+
+ /**
+ * Declarations (import container / declarartion, package declarartion) are
+ * post qualified. e.g.
+ * import container - java.util.Vector.class
+ */
+ public final static int D_POST_QUALIFIED = 1 << 17;
+
+ /**
+ * Class file names are fully qualified. e.g.
+ * java.util.Vector.class
+ */
+ public final static int CF_QUALIFIED = 1 << 18;
+
+ /**
+ * Class file names are post qualified. e.g.
+ * Vector.class - java.util
+ */
+ public final static int CF_POST_QUALIFIED = 1 << 19;
+
+ /**
+ * Compilation unit names are fully qualified. e.g.
+ * java.util.Vector.java
+ */
+ public final static int CU_QUALIFIED = 1 << 20;
+
+ /**
+ * Compilation unit names are post qualified. e.g.
+ * Vector.java - java.util
+ */
+ public final static int CU_POST_QUALIFIED = 1 << 21;
+
+ /**
+ * Package names are qualified. e.g. MyProject/src/java.util
+ */
+ public final static int P_QUALIFIED = 1 << 22;
+
+ /**
+ * Package names are post qualified. e.g.
+ * java.util - MyProject/src
+ */
+ public final static int P_POST_QUALIFIED = 1 << 23;
+
+ /**
+ * Package Fragment Roots contain variable name if from a variable. e.g.
+ * JRE_LIB - c:\java\lib\rt.jar
+ */
+ public final static int ROOT_VARIABLE = 1 << 24;
+
+ /**
+ * Package Fragment Roots contain the project name if not an archive
+ * (prepended). e.g. MyProject/src
+ */
+ public final static int ROOT_QUALIFIED = 1 << 25;
+
+ /**
+ * Package Fragment Roots contain the project name if not an archive
+ * (appended). e.g. src - MyProject
+ */
+ public final static int ROOT_POST_QUALIFIED = 1 << 26;
+
+ /**
+ * Add root path to all elements except Package Fragment Roots and Java
+ * projects. e.g. java.lang.Vector - c:\java\lib\rt.jar
+ * Option only applies to getElementLabel
+ */
+ public final static int APPEND_ROOT_PATH = 1 << 27;
+
+ /**
+ * Add root path to all elements except Package Fragment Roots and Java
+ * projects. e.g. java.lang.Vector - c:\java\lib\rt.jar
+ * Option only applies to getElementLabel
+ */
+ public final static int PREPEND_ROOT_PATH = 1 << 28;
+
+ /**
+ * Package names are compressed. e.g. o*.e*.search
+ */
+ public final static int P_COMPRESSED = 1 << 29;
+
+ /**
+ * Post qualify referenced package fragement roots. For example
+ * jdt.jar - net.sourceforge.phpdt.ui
if the jar is
+ * referenced from another project.
+ */
+ public final static int REFERENCED_ROOT_POST_QUALIFIED = 1 << 30;
+
+ /**
+ * Qualify all elements
+ */
+ public final static int ALL_FULLY_QUALIFIED = F_FULLY_QUALIFIED
+ | M_FULLY_QUALIFIED | I_FULLY_QUALIFIED | T_FULLY_QUALIFIED
+ | D_QUALIFIED | CF_QUALIFIED | CU_QUALIFIED | P_QUALIFIED
+ | ROOT_QUALIFIED;
+
+ /**
+ * Post qualify all elements
+ */
+ public final static int ALL_POST_QUALIFIED = F_POST_QUALIFIED
+ | M_POST_QUALIFIED | I_POST_QUALIFIED | T_POST_QUALIFIED
+ | D_POST_QUALIFIED | CF_POST_QUALIFIED | CU_POST_QUALIFIED
+ | P_POST_QUALIFIED | ROOT_POST_QUALIFIED;
+
+ /**
+ * Default options (M_PARAMETER_TYPES enabled)
+ */
+ public final static int ALL_DEFAULT = M_PARAMETER_TYPES;
+
+ /**
+ * Default qualify options (All except Root and Package)
+ */
+ public final static int DEFAULT_QUALIFIED = F_FULLY_QUALIFIED
+ | M_FULLY_QUALIFIED | I_FULLY_QUALIFIED | T_FULLY_QUALIFIED
+ | D_QUALIFIED | CF_QUALIFIED | CU_QUALIFIED;
+
+ /**
+ * Default post qualify options (All except Root and Package)
+ */
+ public final static int DEFAULT_POST_QUALIFIED = F_POST_QUALIFIED
+ | M_POST_QUALIFIED | I_POST_QUALIFIED | T_POST_QUALIFIED
+ | D_POST_QUALIFIED | CF_POST_QUALIFIED | CU_POST_QUALIFIED;
+
+ public final static String CONCAT_STRING = PHPUIMessages
+ .getString("JavaElementLabels.concat_string"); // " - ";
+ // //$NON-NLS-1$
+
+ public final static String COMMA_STRING = PHPUIMessages
+ .getString("JavaElementLabels.comma_string"); // ", ";
+ // //$NON-NLS-1$
+
+ public final static String DECL_STRING = PHPUIMessages
+ .getString("JavaElementLabels.declseparator_string"); // " "; //
+ // use for
+ // return
+ // type
+ // //$NON-NLS-1$
+
+ /*
+ * Package name compression
+ */
+ private static String fgPkgNamePattern = ""; //$NON-NLS-1$
+
+ private static String fgPkgNamePrefix;
+
+ private static String fgPkgNamePostfix;
+
+ private static int fgPkgNameChars;
+
+ private static int fgPkgNameLength = -1;
+
+ private JavaElementLabels() {
+ }
+
+ private static boolean getFlag(int flags, int flag) {
+ return (flags & flag) != 0;
+ }
+
+ public static String getTextLabel(Object obj, int flags) {
+ if (obj instanceof IJavaElement) {
+ return getElementLabel((IJavaElement) obj, flags);
+ } else if (obj instanceof IAdaptable) {
+ IWorkbenchAdapter wbadapter = (IWorkbenchAdapter) ((IAdaptable) obj)
+ .getAdapter(IWorkbenchAdapter.class);
+ if (wbadapter != null) {
+ return wbadapter.getLabel(obj);
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the label for a Java element. Flags as defined above.
+ */
+ public static String getElementLabel(IJavaElement element, int flags) {
+ StringBuffer buf = new StringBuffer(60);
+ getElementLabel(element, flags, buf);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the label for a Java element. Flags as defined above.
+ */
+ public static void getElementLabel(IJavaElement element, int flags,
+ StringBuffer buf) {
+ int type = element.getElementType();
+ IPackageFragmentRoot root = null;
+
+ if (type != IJavaElement.JAVA_MODEL
+ && type != IJavaElement.JAVA_PROJECT
+ && type != IJavaElement.PACKAGE_FRAGMENT_ROOT)
+ root = JavaModelUtil.getPackageFragmentRoot(element);
+ if (root != null && getFlag(flags, PREPEND_ROOT_PATH)) {
+ getPackageFragmentRootLabel(root, ROOT_QUALIFIED, buf);
+ buf.append(CONCAT_STRING);
+ }
+
+ switch (type) {
+ case IJavaElement.METHOD:
+ getMethodLabel((IMethod) element, flags, buf);
+ break;
+ case IJavaElement.FIELD:
+ getFieldLabel((IField) element, flags, buf);
+ break;
+ // case IJavaElement.INITIALIZER:
+ // getInitializerLabel((IInitializer) element, flags, buf);
+ // break;
+ case IJavaElement.TYPE:
+ getTypeLabel((IType) element, flags, buf);
+ break;
+ // case IJavaElement.CLASS_FILE:
+ // getClassFileLabel((IClassFile) element, flags, buf);
+ // break;
+ case IJavaElement.COMPILATION_UNIT:
+ getCompilationUnitLabel((ICompilationUnit) element, flags, buf);
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT:
+ getPackageFragmentLabel((IPackageFragment) element, flags, buf);
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+ getPackageFragmentRootLabel((IPackageFragmentRoot) element, flags,
+ buf);
+ break;
+ case IJavaElement.IMPORT_CONTAINER:
+ case IJavaElement.IMPORT_DECLARATION:
+ case IJavaElement.PACKAGE_DECLARATION:
+ getDeclararionLabel(element, flags, buf);
+ break;
+ case IJavaElement.JAVA_PROJECT:
+ case IJavaElement.JAVA_MODEL:
+ buf.append(element.getElementName());
+ break;
+ default:
+ buf.append(element.getElementName());
+ }
+
+ if (root != null && getFlag(flags, APPEND_ROOT_PATH)) {
+ buf.append(CONCAT_STRING);
+ getPackageFragmentRootLabel(root, ROOT_QUALIFIED, buf);
+ }
+ }
+
+ /**
+ * Appends the label for a method to a StringBuffer. Considers the M_*
+ * flags.
+ */
+ public static void getMethodLabel(IMethod method, int flags,
+ StringBuffer buf) {
+ try {
+ // return type
+ if (getFlag(flags, M_PRE_RETURNTYPE) && method.exists()
+ && !method.isConstructor()) {
+ buf.append(Signature.getSimpleName(Signature.toString(method
+ .getReturnType())));
+ buf.append(' ');
+ }
+
+ // qualification
+ if (getFlag(flags, M_FULLY_QUALIFIED)) {
+ getTypeLabel(method.getDeclaringType(), T_FULLY_QUALIFIED
+ | (flags & P_COMPRESSED), buf);
+ buf.append('.');
+ }
+
+ buf.append(method.getElementName());
+
+ // parameters
+ if (getFlag(flags, M_PARAMETER_TYPES | M_PARAMETER_NAMES)) {
+ buf.append('(');
+
+ String[] types = getFlag(flags, M_PARAMETER_TYPES) ? method
+ .getParameterTypes() : null;
+ String[] names = (getFlag(flags, M_PARAMETER_NAMES) && method
+ .exists()) ? method.getParameterNames() : null;
+ int nParams = types != null ? types.length : names.length;
+
+ for (int i = 0; i < nParams; i++) {
+ if (i > 0) {
+ buf.append(COMMA_STRING); //$NON-NLS-1$
+ }
+ if (types != null) {
+ buf.append(Signature.getSimpleName(Signature
+ .toString(types[i])));
+ }
+ if (names != null) {
+ if (types != null) {
+ buf.append(' ');
+ }
+ buf.append(names[i]);
+ }
+ }
+ buf.append(')');
+ }
+
+ if (getFlag(flags, M_EXCEPTIONS) && method.exists()) {
+ String[] types = method.getExceptionTypes();
+ if (types.length > 0) {
+ buf.append(" throws "); //$NON-NLS-1$
+ for (int i = 0; i < types.length; i++) {
+ if (i > 0) {
+ buf.append(COMMA_STRING);
+ }
+ buf.append(Signature.getSimpleName(Signature
+ .toString(types[i])));
+ }
+ }
+ }
+
+ if (getFlag(flags, M_APP_RETURNTYPE) && method.exists()
+ && !method.isConstructor()) {
+ buf.append(DECL_STRING);
+ buf.append(Signature.getSimpleName(Signature.toString(method
+ .getReturnType())));
+ }
+
+ // post qualification
+ if (getFlag(flags, M_POST_QUALIFIED)) {
+ buf.append(CONCAT_STRING);
+ getTypeLabel(method.getDeclaringType(), T_FULLY_QUALIFIED
+ | (flags & P_COMPRESSED), buf);
+ }
+
+ } catch (JavaModelException e) {
+ PHPeclipsePlugin.log(e); // NotExistsException will not reach
+ // this point
+ }
+ }
+
+ /**
+ * Appends the label for a field to a StringBuffer. Considers the F_* flags.
+ */
+ public static void getFieldLabel(IField field, int flags, StringBuffer buf) {
+ try {
+ if (getFlag(flags, F_PRE_TYPE_SIGNATURE) && field.exists()) {
+ buf.append(Signature.toString(field.getTypeSignature()));
+ buf.append(' ');
+ }
+
+ // qualification
+ if (getFlag(flags, F_FULLY_QUALIFIED)) {
+ getTypeLabel(field.getDeclaringType(), T_FULLY_QUALIFIED
+ | (flags & P_COMPRESSED), buf);
+ buf.append('.');
+ }
+ buf.append(field.getElementName());
+
+ if (getFlag(flags, F_APP_TYPE_SIGNATURE) && field.exists()) {
+ buf.append(DECL_STRING);
+ buf.append(Signature.toString(field.getTypeSignature()));
+ }
+
+ // post qualification
+ if (getFlag(flags, F_POST_QUALIFIED)) {
+ buf.append(CONCAT_STRING);
+ getTypeLabel(field.getDeclaringType(), T_FULLY_QUALIFIED
+ | (flags & P_COMPRESSED), buf);
+ }
+
+ } catch (JavaModelException e) {
+ PHPeclipsePlugin.log(e); // NotExistsException will not reach
+ // this point
+ }
+ }
+
+ /**
+ * Appends the label for a initializer to a StringBuffer. Considers the I_*
+ * flags.
+ */
+ // public static void getInitializerLabel(IInitializer initializer, int
+ // flags, StringBuffer buf) {
+ // // qualification
+ // if (getFlag(flags, I_FULLY_QUALIFIED)) {
+ // getTypeLabel(initializer.getDeclaringType(), T_FULLY_QUALIFIED | (flags &
+ // P_COMPRESSED), buf);
+ // buf.append('.');
+ // }
+ // buf.append(JavaUIMessages.getString("JavaElementLabels.initializer"));
+ // //$NON-NLS-1$
+ //
+ // // post qualification
+ // if (getFlag(flags, I_POST_QUALIFIED)) {
+ // buf.append(CONCAT_STRING);
+ // getTypeLabel(initializer.getDeclaringType(), T_FULLY_QUALIFIED | (flags &
+ // P_COMPRESSED), buf);
+ // }
+ // }
+ /**
+ * Appends the label for a type to a StringBuffer. Considers the T_* flags.
+ */
+ public static void getTypeLabel(IType type, int flags, StringBuffer buf) {
+ if (getFlag(flags, T_FULLY_QUALIFIED)) {
+ if (type != null) { // jsurfer INSERT
+ IPackageFragment pack = type.getPackageFragment();
+ if (!pack.isDefaultPackage()) {
+ getPackageFragmentLabel(pack, (flags & P_COMPRESSED), buf);
+ buf.append('.');
+ }
+ buf.append(JavaModelUtil.getTypeQualifiedName(type));
+ } // jsurfer INSERT
+ } else if (getFlag(flags, T_CONTAINER_QUALIFIED)) {
+ buf.append(JavaModelUtil.getTypeQualifiedName(type));
+ } else {
+ buf.append(type.getElementName());
+ }
+ // post qualification
+ if (getFlag(flags, T_POST_QUALIFIED)) {
+ buf.append(CONCAT_STRING);
+ IType declaringType = type.getDeclaringType();
+ if (declaringType != null) {
+ getTypeLabel(declaringType, T_FULLY_QUALIFIED
+ | (flags & P_COMPRESSED), buf);
+ } else {
+ getPackageFragmentLabel(type.getPackageFragment(),
+ (flags & P_COMPRESSED), buf);
+ }
+ }
+ }
+
+ /**
+ * Appends the label for a declaration to a StringBuffer. Considers the D_*
+ * flags.
+ */
+ public static void getDeclararionLabel(IJavaElement declaration, int flags,
+ StringBuffer buf) {
+ if (getFlag(flags, D_QUALIFIED)) {
+ IJavaElement openable = (IJavaElement) declaration.getOpenable();
+ if (openable != null) {
+ buf.append(getElementLabel(openable, CF_QUALIFIED
+ | CU_QUALIFIED));
+ buf.append('/');
+ }
+ }
+ if (declaration.getElementType() == IJavaElement.IMPORT_CONTAINER) {
+ buf.append(PHPUIMessages
+ .getString("JavaElementLabels.import_container")); //$NON-NLS-1$
+ } else {
+ buf.append(declaration.getElementName());
+ }
+ // post qualification
+ if (getFlag(flags, D_POST_QUALIFIED)) {
+ IJavaElement openable = (IJavaElement) declaration.getOpenable();
+ if (openable != null) {
+ buf.append(CONCAT_STRING);
+ buf.append(getElementLabel(openable, CF_QUALIFIED
+ | CU_QUALIFIED));
+ }
+ }
+ }
+
+ /**
+ * Appends the label for a class file to a StringBuffer. Considers the CF_*
+ * flags.
+ */
+ // public static void getClassFileLabel(IClassFile classFile, int flags,
+ // StringBuffer buf) {
+ // if (getFlag(flags, CF_QUALIFIED)) {
+ // IPackageFragment pack= (IPackageFragment) classFile.getParent();
+ // if (!pack.isDefaultPackage()) {
+ // buf.append(pack.getElementName());
+ // buf.append('.');
+ // }
+ // }
+ // buf.append(classFile.getElementName());
+ //
+ // if (getFlag(flags, CF_POST_QUALIFIED)) {
+ // buf.append(CONCAT_STRING);
+ // getPackageFragmentLabel((IPackageFragment) classFile.getParent(), 0,
+ // buf);
+ // }
+ // }
+ /**
+ * Appends the label for a compilation unit to a StringBuffer. Considers the
+ * CU_* flags.
+ */
+ public static void getCompilationUnitLabel(ICompilationUnit cu, int flags,
+ StringBuffer buf) {
+ if (getFlag(flags, CU_QUALIFIED)) {
+ IPackageFragment pack = (IPackageFragment) cu.getParent();
+ if (!pack.isDefaultPackage()) {
+ buf.append(pack.getElementName());
+ buf.append('.');
+ }
+ }
+ buf.append(cu.getElementName());
+
+ if (getFlag(flags, CU_POST_QUALIFIED)) {
+ buf.append(CONCAT_STRING);
+ getPackageFragmentLabel((IPackageFragment) cu.getParent(), 0, buf);
+ }
+ }
+
+ /**
+ * Appends the label for a package fragment to a StringBuffer. Considers the
+ * P_* flags.
+ */
+ public static void getPackageFragmentLabel(IPackageFragment pack,
+ int flags, StringBuffer buf) {
+ if (getFlag(flags, P_QUALIFIED)) {
+ getPackageFragmentRootLabel(
+ (IPackageFragmentRoot) pack.getParent(), ROOT_QUALIFIED,
+ buf);
+ buf.append('/');
+ }
+ refreshPackageNamePattern();
+ if (pack.isDefaultPackage()) {
+ buf.append(PHPUIMessages
+ .getString("JavaElementLabels.default_package")); //$NON-NLS-1$
+ } else if (getFlag(flags, P_COMPRESSED) && fgPkgNameLength >= 0) {
+ String name = pack.getElementName();
+ int start = 0;
+ int dot = name.indexOf('.', start);
+ while (dot > 0) {
+ if (dot - start > fgPkgNameLength - 1) {
+ buf.append(fgPkgNamePrefix);
+ if (fgPkgNameChars > 0)
+ buf.append(name.substring(start, Math.min(start
+ + fgPkgNameChars, dot)));
+ buf.append(fgPkgNamePostfix);
+ } else
+ buf.append(name.substring(start, dot + 1));
+ start = dot + 1;
+ dot = name.indexOf('.', start);
+ }
+ buf.append(name.substring(start));
+ } else {
+ buf.append(pack.getElementName());
+ }
+ if (getFlag(flags, P_POST_QUALIFIED)) {
+ buf.append(CONCAT_STRING);
+ getPackageFragmentRootLabel(
+ (IPackageFragmentRoot) pack.getParent(), ROOT_QUALIFIED,
+ buf);
+ }
+ }
+
+ /**
+ * Appends the label for a package fragment root to a StringBuffer.
+ * Considers the ROOT_* flags.
+ */
+ public static void getPackageFragmentRootLabel(IPackageFragmentRoot root,
+ int flags, StringBuffer buf) {
+ if (root.isArchive())
+ getArchiveLabel(root, flags, buf);
+ else
+ getFolderLabel(root, flags, buf);
+ }
+
+ private static void getArchiveLabel(IPackageFragmentRoot root, int flags,
+ StringBuffer buf) {
+ // Handle variables different
+ if (getFlag(flags, ROOT_VARIABLE) && getVariableLabel(root, flags, buf))
+ return;
+ boolean external = root.isExternal();
+ if (external)
+ getExternalArchiveLabel(root, flags, buf);
+ else
+ getInternalArchiveLabel(root, flags, buf);
+ }
+
+ private static boolean getVariableLabel(IPackageFragmentRoot root,
+ int flags, StringBuffer buf) {
+ // try {
+ // IClasspathEntry rawEntry= root.getRawClasspathEntry();
+ // if (rawEntry != null) {
+ // if (rawEntry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
+ // buf.append(rawEntry.getPath().makeRelative());
+ // buf.append(CONCAT_STRING);
+ // if (root.isExternal())
+ // buf.append(root.getPath().toOSString());
+ // else
+ // buf.append(root.getPath().makeRelative().toString());
+ // return true;
+ // }
+ // }
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e); // problems with class path
+ // }
+ return false;
+ }
+
+ private static void getExternalArchiveLabel(IPackageFragmentRoot root,
+ int flags, StringBuffer buf) {
+ IPath path = root.getPath();
+ if (getFlag(flags, REFERENCED_ROOT_POST_QUALIFIED)) {
+ int segements = path.segmentCount();
+ if (segements > 0) {
+ buf.append(path.segment(segements - 1));
+ if (segements > 1 || path.getDevice() != null) {
+ buf.append(CONCAT_STRING);
+ buf.append(path.removeLastSegments(1).toOSString());
+ }
+ } else {
+ buf.append(path.toOSString());
+ }
+ } else {
+ buf.append(path.toOSString());
+ }
+ }
+
+ private static void getInternalArchiveLabel(IPackageFragmentRoot root,
+ int flags, StringBuffer buf) {
+ IResource resource = root.getResource();
+ boolean rootQualified = getFlag(flags, ROOT_QUALIFIED);
+ boolean referencedQualified = getFlag(flags,
+ REFERENCED_ROOT_POST_QUALIFIED)
+ && JavaModelUtil.isReferenced(root) && resource != null;
+ if (rootQualified) {
+ buf.append(root.getPath().makeRelative().toString());
+ } else {
+ buf.append(root.getElementName());
+ if (referencedQualified) {
+ buf.append(CONCAT_STRING);
+ buf.append(resource.getParent().getFullPath().makeRelative()
+ .toString());
+ } else if (getFlag(flags, ROOT_POST_QUALIFIED)) {
+ buf.append(CONCAT_STRING);
+ buf
+ .append(root.getParent().getPath().makeRelative()
+ .toString());
+ }
+ }
+ }
+
+ private static void getFolderLabel(IPackageFragmentRoot root, int flags,
+ StringBuffer buf) {
+ IResource resource = root.getResource();
+ boolean rootQualified = getFlag(flags, ROOT_QUALIFIED);
+ boolean referencedQualified = getFlag(flags,
+ REFERENCED_ROOT_POST_QUALIFIED)
+ && JavaModelUtil.isReferenced(root) && resource != null;
+ if (rootQualified) {
+ buf.append(root.getPath().makeRelative().toString());
+ } else {
+ if (resource != null)
+ buf.append(resource.getProjectRelativePath().toString());
+ else
+ buf.append(root.getElementName());
+ if (referencedQualified) {
+ buf.append(CONCAT_STRING);
+ buf.append(resource.getProject().getName());
+ } else if (getFlag(flags, ROOT_POST_QUALIFIED)) {
+ buf.append(CONCAT_STRING);
+ buf.append(root.getParent().getElementName());
+ }
+ }
+ }
+
+ private static void refreshPackageNamePattern() {
+ String pattern = getPkgNamePatternForPackagesView();
+ if (pattern.equals(fgPkgNamePattern))
+ return;
+ else if (pattern.equals("")) { //$NON-NLS-1$
+ fgPkgNamePattern = ""; //$NON-NLS-1$
+ fgPkgNameLength = -1;
+ return;
+ }
+ fgPkgNamePattern = pattern;
+ int i = 0;
+ fgPkgNameChars = 0;
+ fgPkgNamePrefix = ""; //$NON-NLS-1$
+ fgPkgNamePostfix = ""; //$NON-NLS-1$
+ while (i < pattern.length()) {
+ char ch = pattern.charAt(i);
+ if (Character.isDigit(ch)) {
+ fgPkgNameChars = ch - 48;
+ if (i > 0)
+ fgPkgNamePrefix = pattern.substring(0, i);
+ if (i >= 0)
+ fgPkgNamePostfix = pattern.substring(i + 1);
+ fgPkgNameLength = fgPkgNamePrefix.length() + fgPkgNameChars
+ + fgPkgNamePostfix.length();
+ return;
+ }
+ i++;
+ }
+ fgPkgNamePrefix = pattern;
+ fgPkgNameLength = pattern.length();
+ }
+
+ private static String getPkgNamePatternForPackagesView() {
+ IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+ if (!store
+ .getBoolean(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES))
+ return ""; //$NON-NLS-1$
+ return store
+ .getString(PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaUILabelProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaUILabelProvider.java
new file mode 100644
index 0000000..abe10ec
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/JavaUILabelProvider.java
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class JavaUILabelProvider extends LabelProvider {
+
+ protected JavaElementImageProvider fImageLabelProvider;
+
+ protected StorageLabelProvider fStorageLabelProvider;
+
+ protected ArrayList fLabelDecorators;
+
+ private int fImageFlags;
+
+ private int fTextFlags;
+
+ /**
+ * Creates a new label provider with default flags.
+ */
+ public JavaUILabelProvider() {
+ this(JavaElementLabels.M_PARAMETER_TYPES,
+ JavaElementImageProvider.OVERLAY_ICONS);
+ }
+
+ /**
+ * @param textFlags
+ * Flags defined in JavaElementLabels
.
+ * @param imageFlags
+ * Flags defined in JavaElementImageProvider
.
+ */
+ public JavaUILabelProvider(int textFlags, int imageFlags) {
+ fImageLabelProvider = new JavaElementImageProvider();
+ fLabelDecorators = null;
+
+ fStorageLabelProvider = new StorageLabelProvider();
+ fImageFlags = imageFlags;
+ fTextFlags = textFlags;
+ }
+
+ /**
+ * Adds a decorator to the label provider
+ */
+ public void addLabelDecorator(ILabelDecorator decorator) {
+ if (fLabelDecorators == null) {
+ fLabelDecorators = new ArrayList(2);
+ }
+ fLabelDecorators.add(decorator);
+ }
+
+ /**
+ * Sets the textFlags.
+ *
+ * @param textFlags
+ * The textFlags to set
+ */
+ public final void setTextFlags(int textFlags) {
+ fTextFlags = textFlags;
+ }
+
+ /**
+ * Sets the imageFlags
+ *
+ * @param imageFlags
+ * The imageFlags to set
+ */
+ public final void setImageFlags(int imageFlags) {
+ fImageFlags = imageFlags;
+ }
+
+ /**
+ * Gets the image flags. Can be overwriten by super classes.
+ *
+ * @return Returns a int
+ */
+ public final int getImageFlags() {
+ return fImageFlags;
+ }
+
+ /**
+ * Gets the text flags.
+ *
+ * @return Returns a int
+ */
+ public final int getTextFlags() {
+ return fTextFlags;
+ }
+
+ /**
+ * Evaluates the image flags for a element. Can be overwriten by super
+ * classes.
+ *
+ * @return Returns a int
+ */
+ protected int evaluateImageFlags(Object element) {
+ return getImageFlags();
+ }
+
+ /**
+ * Evaluates the text flags for a element. Can be overwriten by super
+ * classes.
+ *
+ * @return Returns a int
+ */
+ protected int evaluateTextFlags(Object element) {
+ return getTextFlags();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelProvider#getImage
+ */
+ public Image getImage(Object element) {
+ Image result = fImageLabelProvider.getImageLabel(element,
+ evaluateImageFlags(element));
+ if (result == null && (element instanceof IStorage)) {
+ result = fStorageLabelProvider.getImage(element);
+ }
+ if (fLabelDecorators != null && result != null) {
+ for (int i = 0; i < fLabelDecorators.size(); i++) {
+ ILabelDecorator decorator = (ILabelDecorator) fLabelDecorators
+ .get(i);
+ result = decorator.decorateImage(result, element);
+ }
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelProvider#getText
+ */
+ public String getText(Object element) {
+ String result = JavaElementLabels.getTextLabel(element,
+ evaluateTextFlags(element));
+ if (result.length() == 0 && (element instanceof IStorage)) {
+ result = fStorageLabelProvider.getText(element);
+ }
+ if (fLabelDecorators != null && result.length() > 0) {
+ for (int i = 0; i < fLabelDecorators.size(); i++) {
+ ILabelDecorator decorator = (ILabelDecorator) fLabelDecorators
+ .get(i);
+ result = decorator.decorateText(result, element);
+ }
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#dispose
+ */
+ public void dispose() {
+ if (fLabelDecorators != null) {
+ for (int i = 0; i < fLabelDecorators.size(); i++) {
+ ILabelDecorator decorator = (ILabelDecorator) fLabelDecorators
+ .get(i);
+ decorator.dispose();
+ }
+ fLabelDecorators = null;
+ }
+ fStorageLabelProvider.dispose();
+ fImageLabelProvider.dispose();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#addListener(ILabelProviderListener)
+ */
+ public void addListener(ILabelProviderListener listener) {
+ if (fLabelDecorators != null) {
+ for (int i = 0; i < fLabelDecorators.size(); i++) {
+ ILabelDecorator decorator = (ILabelDecorator) fLabelDecorators
+ .get(i);
+ decorator.addListener(listener);
+ }
+ }
+ super.addListener(listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#isLabelProperty(Object, String)
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ if (fLabelDecorators != null) {
+ for (int i = 0; i < fLabelDecorators.size(); i++) {
+ ILabelDecorator decorator = (ILabelDecorator) fLabelDecorators
+ .get(i);
+ decorator.removeListener(listener);
+ }
+ }
+ super.removeListener(listener);
+ }
+
+ public static ILabelDecorator[] getDecorators(boolean errortick,
+ ILabelDecorator extra) {
+ if (errortick) {
+ if (extra == null) {
+ return new ILabelDecorator[] {};
+ } else {
+ return new ILabelDecorator[] { extra };
+ }
+ }
+ if (extra != null) {
+ return new ILabelDecorator[] { extra };
+ }
+ return null;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ListContentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ListContentProvider.java
new file mode 100644
index 0000000..e520f4f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ListContentProvider.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * A specialized content provider to show a list of editor parts.
+ */
+public class ListContentProvider implements IStructuredContentProvider {
+ List fContents;
+
+ public ListContentProvider() {
+ }
+
+ public Object[] getElements(Object input) {
+ if (fContents != null && fContents == input)
+ return fContents.toArray();
+ return new Object[0];
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (newInput instanceof List)
+ fContents = (List) newInput;
+ else
+ fContents = null;
+ // we use a fixed set.
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isDeleted(Object o) {
+ return fContents != null && !fContents.contains(o);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/MemberFilter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/MemberFilter.java
new file mode 100644
index 0000000..5b5bf44
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/MemberFilter.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.core.IField;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Filter for the methods viewer. Changing a filter property does not trigger a
+ * refiltering of the viewer
+ */
+public class MemberFilter extends ViewerFilter {
+
+ public static final int FILTER_NONPUBLIC = 1;
+
+ public static final int FILTER_STATIC = 2;
+
+ public static final int FILTER_FIELDS = 4;
+
+ private int fFilterProperties;
+
+ /**
+ * Modifies filter and add a property to filter for
+ */
+ public final void addFilter(int filter) {
+ fFilterProperties |= filter;
+ }
+
+ /**
+ * Modifies filter and remove a property to filter for
+ */
+ public final void removeFilter(int filter) {
+ fFilterProperties &= (-1 ^ filter);
+ }
+
+ /**
+ * Tests if a property is filtered
+ */
+ public final boolean hasFilter(int filter) {
+ return (fFilterProperties & filter) != 0;
+ }
+
+ /*
+ * @see ViewerFilter@isFilterProperty
+ */
+ public boolean isFilterProperty(Object element, Object property) {
+ return false;
+ }
+
+ /*
+ * @see ViewerFilter@select
+ */
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ try {
+ if (hasFilter(FILTER_FIELDS) && element instanceof IField) {
+ return false;
+ }
+ if (element instanceof IMember) {
+ IMember member = (IMember) element;
+ if (member.getElementName().startsWith("<")) { // filter out
+ //
+ // //$NON-NLS-1$
+ return false;
+ }
+ int flags = member.getFlags();
+ if (hasFilter(FILTER_STATIC)
+ && (Flags.isStatic(flags) || isFieldInInterface(member))
+ && member.getElementType() != IJavaElement.TYPE) {
+ return false;
+ }
+ if (hasFilter(FILTER_NONPUBLIC) && !Flags.isPublic(flags)
+ && !isMemberInInterface(member)
+ && !isTopLevelType(member)) {
+ return false;
+ }
+ }
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ return true;
+ }
+
+ private boolean isMemberInInterface(IMember member)
+ throws JavaModelException {
+ IType parent = member.getDeclaringType();
+ return parent != null && parent.isInterface();
+ }
+
+ private boolean isFieldInInterface(IMember member)
+ throws JavaModelException {
+ return (member.getElementType() == IJavaElement.FIELD)
+ && member.getDeclaringType().isInterface();
+ }
+
+ private boolean isTopLevelType(IMember member) throws JavaModelException {
+ IType parent = member.getDeclaringType();
+ return parent == null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/MemberFilterAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/MemberFilterAction.java
new file mode 100644
index 0000000..634678f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/MemberFilterAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import net.sourceforge.phpdt.ui.actions.MemberFilterActionGroup;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Action used to enable / disable method filter properties
+ */
+public class MemberFilterAction extends Action {
+
+ private int fFilterProperty;
+
+ private MemberFilterActionGroup fFilterActionGroup;
+
+ public MemberFilterAction(MemberFilterActionGroup actionGroup,
+ String title, int property, String contextHelpId, boolean initValue) {
+ super(title);
+ fFilterActionGroup = actionGroup;
+ fFilterProperty = property;
+
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, contextHelpId);
+
+ setChecked(initValue);
+ }
+
+ /**
+ * Returns this action's filter property.
+ */
+ public int getFilterProperty() {
+ return fFilterProperty;
+ }
+
+ /*
+ * @see Action#actionPerformed
+ */
+ public void run() {
+ fFilterActionGroup.setMemberFilter(fFilterProperty, isChecked());
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java
new file mode 100644
index 0000000..129837b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.HashSet;
+
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.CompilationUnitAnnotationModelEvent;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.source.AnnotationModelEvent;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelListener;
+import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Listens to resource deltas and filters for marker changes of type
+ * IMarker.PROBLEM Viewers showing error ticks should register as listener to
+ * this type.
+ */
+public class ProblemMarkerManager implements IResourceChangeListener,
+ IAnnotationModelListener, IAnnotationModelListenerExtension {
+
+ /**
+ * Visitors used to look if the element change delta containes a marker
+ * change.
+ */
+ private static class ProjectErrorVisitor implements IResourceDeltaVisitor {
+
+ private HashSet fChangedElements;
+
+ public ProjectErrorVisitor(HashSet changedElements) {
+ fChangedElements = changedElements;
+ }
+
+ public boolean visit(IResourceDelta delta) throws CoreException {
+ IResource res = delta.getResource();
+ if (res instanceof IProject
+ && delta.getKind() == IResourceDelta.CHANGED) {
+ try {
+ IProject project = (IProject) res;
+ if (!project.isAccessible()
+ || !project
+ .hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
+ // only track open Java projects
+ return false;
+ }
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ return false;
+ }
+ }
+ checkInvalidate(delta, res);
+ return true;
+ }
+
+ private void checkInvalidate(IResourceDelta delta, IResource resource) {
+ int kind = delta.getKind();
+ if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.ADDED
+ || (kind == IResourceDelta.CHANGED && isErrorDelta(delta))) {
+ // invalidate the resource and all parents
+ while (resource.getType() != IResource.ROOT
+ && fChangedElements.add(resource)) {
+ resource = resource.getParent();
+ }
+ }
+ }
+
+ private boolean isErrorDelta(IResourceDelta delta) {
+ if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) {
+ IMarkerDelta[] markerDeltas = delta.getMarkerDeltas();
+ for (int i = 0; i < markerDeltas.length; i++) {
+ if (markerDeltas[i].isSubtypeOf(IMarker.PROBLEM)) {
+ int kind = markerDeltas[i].getKind();
+ if (kind == IResourceDelta.ADDED
+ || kind == IResourceDelta.REMOVED)
+ return true;
+ int severity = markerDeltas[i].getAttribute(
+ IMarker.SEVERITY, -1);
+ int newSeverity = markerDeltas[i].getMarker()
+ .getAttribute(IMarker.SEVERITY, -1);
+ if (newSeverity != severity)
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ private ListenerList fListeners;
+
+ public ProblemMarkerManager() {
+ fListeners = new ListenerList(10);
+ }
+
+ /*
+ * @see IResourceChangeListener#resourceChanged
+ */
+ public void resourceChanged(IResourceChangeEvent event) {
+ HashSet changedElements = new HashSet();
+
+ try {
+ IResourceDelta delta = event.getDelta();
+ if (delta != null)
+ delta.accept(new ProjectErrorVisitor(changedElements));
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e.getStatus());
+ }
+
+ if (!changedElements.isEmpty()) {
+ IResource[] changes = (IResource[]) changedElements
+ .toArray(new IResource[changedElements.size()]);
+ fireChanges(changes, true);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
+ */
+ public void modelChanged(IAnnotationModel model) {
+ // no action
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
+ */
+ public void modelChanged(AnnotationModelEvent event) {
+ if (event instanceof CompilationUnitAnnotationModelEvent) {
+ CompilationUnitAnnotationModelEvent cuEvent = (CompilationUnitAnnotationModelEvent) event;
+ if (cuEvent.includesProblemMarkerAnnotationChanges()) {
+ IResource[] changes = new IResource[] { cuEvent
+ .getUnderlyingResource() };
+ fireChanges(changes, false);
+ }
+ }
+ }
+
+ /**
+ * Adds a listener for problem marker changes.
+ */
+ public void addListener(IProblemChangedListener listener) {
+ if (fListeners.isEmpty()) {
+ PHPeclipsePlugin.getWorkspace().addResourceChangeListener(this);
+ WebUI.getDefault().getCompilationUnitDocumentProvider()
+ .addGlobalAnnotationModelListener(this);
+ }
+ fListeners.add(listener);
+ }
+
+ /**
+ * Removes a IProblemChangedListener
.
+ */
+ public void removeListener(IProblemChangedListener listener) {
+ fListeners.remove(listener);
+ if (fListeners.isEmpty()) {
+ PHPeclipsePlugin.getWorkspace().removeResourceChangeListener(this);
+ WebUI.getDefault().getCompilationUnitDocumentProvider()
+ .removeGlobalAnnotationModelListener(this);
+ }
+ }
+
+ private void fireChanges(final IResource[] changes,
+ final boolean isMarkerChange) {
+ Display display = SWTUtil.getStandardDisplay();
+ if (display != null && !display.isDisposed()) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ Object[] listeners = fListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IProblemChangedListener curr = (IProblemChangedListener) listeners[i];
+ curr.problemsChanged(changes, isMarkerChange);
+ }
+ }
+ });
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTableViewer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTableViewer.java
new file mode 100644
index 0000000..6bc9ca3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTableViewer.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.ui.IWorkingCopyProvider;
+import net.sourceforge.phpdt.ui.ProblemsLabelDecorator.ProblemsLabelChangedEvent;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Extends a TableViewer to allow more performance when showing error ticks. A
+ * ProblemItemMapper
is contained that maps all items in the tree
+ * to underlying resource
+ */
+public class ProblemTableViewer extends TableViewer {
+
+ protected ResourceToItemsMapper fResourceToItemsMapper;
+
+ /**
+ * Constructor for ProblemTableViewer.
+ *
+ * @param parent
+ */
+ public ProblemTableViewer(Composite parent) {
+ super(parent);
+ initMapper();
+ }
+
+ /**
+ * Constructor for ProblemTableViewer.
+ *
+ * @param parent
+ * @param style
+ */
+ public ProblemTableViewer(Composite parent, int style) {
+ super(parent, style);
+ initMapper();
+ }
+
+ /**
+ * Constructor for ProblemTableViewer.
+ *
+ * @param table
+ */
+ public ProblemTableViewer(Table table) {
+ super(table);
+ initMapper();
+ }
+
+ private void initMapper() {
+ fResourceToItemsMapper = new ResourceToItemsMapper(this);
+ }
+
+ /*
+ * @see StructuredViewer#mapElement(Object, Widget)
+ */
+ protected void mapElement(Object element, Widget item) {
+ super.mapElement(element, item);
+ if (item instanceof Item) {
+ fResourceToItemsMapper.addToMap(element, (Item) item);
+ }
+ }
+
+ /*
+ * @see StructuredViewer#unmapElement(Object, Widget)
+ */
+ protected void unmapElement(Object element, Widget item) {
+ if (item instanceof Item) {
+ fResourceToItemsMapper.removeFromMap(element, (Item) item);
+ }
+ super.unmapElement(element, item);
+ }
+
+ /*
+ * @see StructuredViewer#unmapAllElements()
+ */
+ protected void unmapAllElements() {
+ fResourceToItemsMapper.clearMap();
+ super.unmapAllElements();
+ }
+
+ /*
+ * @see ContentViewer#handleLabelProviderChanged(LabelProviderChangedEvent)
+ */
+ protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
+ if (event instanceof ProblemsLabelChangedEvent) {
+ ProblemsLabelChangedEvent e = (ProblemsLabelChangedEvent) event;
+ if (!e.isMarkerChange() && canIgnoreChangesFromAnnotionModel()) {
+ return;
+ }
+ }
+
+ Object[] changed = event.getElements();
+ if (changed != null && !fResourceToItemsMapper.isEmpty()) {
+ ArrayList others = new ArrayList(changed.length);
+ for (int i = 0; i < changed.length; i++) {
+ Object curr = changed[i];
+ if (curr instanceof IResource) {
+ fResourceToItemsMapper.resourceChanged((IResource) curr);
+ } else {
+ others.add(curr);
+ }
+ }
+ if (others.isEmpty()) {
+ return;
+ }
+ event = new LabelProviderChangedEvent((IBaseLabelProvider) event
+ .getSource(), others.toArray());
+ }
+ super.handleLabelProviderChanged(event);
+ }
+
+ /**
+ * Answers whether this viewer can ignore label provider changes resulting
+ * from marker changes in annotation models
+ */
+ private boolean canIgnoreChangesFromAnnotionModel() {
+ Object contentProvider = getContentProvider();
+ return contentProvider instanceof IWorkingCopyProvider
+ && !((IWorkingCopyProvider) contentProvider)
+ .providesWorkingCopies();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTreeViewer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTreeViewer.java
new file mode 100644
index 0000000..ba501eb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTreeViewer.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.ui.IWorkingCopyProvider;
+import net.sourceforge.phpdt.ui.ProblemsLabelDecorator.ProblemsLabelChangedEvent;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Extends a TreeViewer to allow more performance when showing error ticks. A
+ * ProblemItemMapper
is contained that maps all items in the tree
+ * to underlying resource
+ */
+public class ProblemTreeViewer extends TreeViewer {
+
+ protected ResourceToItemsMapper fResourceToItemsMapper;
+
+ /*
+ * @see TreeViewer#TreeViewer(Composite)
+ */
+ public ProblemTreeViewer(Composite parent) {
+ super(parent);
+ initMapper();
+ }
+
+ /*
+ * @see TreeViewer#TreeViewer(Composite, int)
+ */
+ public ProblemTreeViewer(Composite parent, int style) {
+ super(parent, style);
+ initMapper();
+ }
+
+ /*
+ * @see TreeViewer#TreeViewer(Tree)
+ */
+ public ProblemTreeViewer(Tree tree) {
+ super(tree);
+ initMapper();
+ }
+
+ private void initMapper() {
+ fResourceToItemsMapper = new ResourceToItemsMapper(this);
+ }
+
+ /*
+ * @see StructuredViewer#mapElement(Object, Widget)
+ */
+ protected void mapElement(Object element, Widget item) {
+ super.mapElement(element, item);
+ if (item instanceof Item) {
+ fResourceToItemsMapper.addToMap(element, (Item) item);
+ }
+ }
+
+ /*
+ * @see StructuredViewer#unmapElement(Object, Widget)
+ */
+ protected void unmapElement(Object element, Widget item) {
+ if (item instanceof Item) {
+ fResourceToItemsMapper.removeFromMap(element, (Item) item);
+ }
+ super.unmapElement(element, item);
+ }
+
+ /*
+ * @see StructuredViewer#unmapAllElements()
+ */
+ protected void unmapAllElements() {
+ fResourceToItemsMapper.clearMap();
+ super.unmapAllElements();
+ }
+
+ /*
+ * @see ContentViewer#handleLabelProviderChanged(LabelProviderChangedEvent)
+ */
+ protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
+ if (event instanceof ProblemsLabelChangedEvent) {
+ ProblemsLabelChangedEvent e = (ProblemsLabelChangedEvent) event;
+ if (!e.isMarkerChange() && canIgnoreChangesFromAnnotionModel()) {
+ return;
+ }
+ }
+
+ Object[] changed = event.getElements();
+ if (changed != null && !fResourceToItemsMapper.isEmpty()) {
+ ArrayList others = new ArrayList();
+ for (int i = 0; i < changed.length; i++) {
+ Object curr = changed[i];
+ if (curr instanceof IResource) {
+ fResourceToItemsMapper.resourceChanged((IResource) curr);
+ } else {
+ others.add(curr);
+ }
+ }
+ if (others.isEmpty()) {
+ return;
+ }
+ event = new LabelProviderChangedEvent((IBaseLabelProvider) event
+ .getSource(), others.toArray());
+ }
+ super.handleLabelProviderChanged(event);
+ }
+
+ /**
+ * Answers whether this viewer can ignore label provider changes resulting
+ * from marker changes in annotation models
+ */
+ private boolean canIgnoreChangesFromAnnotionModel() {
+ Object contentProvider = getContentProvider();
+ return contentProvider instanceof IWorkingCopyProvider
+ && !((IWorkingCopyProvider) contentProvider)
+ .providesWorkingCopies();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.AbstractTreeViewer#isExpandable(java.lang.Object)
+ */
+ public boolean isExpandable(Object element) {
+ // workaround for 65762
+ if (hasFilters() && element instanceof IMember) {
+ return getFilteredChildren(element).length > 0;
+ }
+ return super.isExpandable(element);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ResourceToItemsMapper.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ResourceToItemsMapper.java
new file mode 100644
index 0000000..dba7cae
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/ResourceToItemsMapper.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Stack;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.viewers.ContentViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IViewerLabelProvider;
+import org.eclipse.jface.viewers.ViewerLabel;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Item;
+
+/**
+ * Helper class for updating error markers and other decorators that work on
+ * resources. Items are mapped to their element's underlying resource. Method
+ * resourceChanged
updates all items that are affected from the
+ * changed elements.
+ */
+public class ResourceToItemsMapper {
+
+ private static final int NUMBER_LIST_REUSE = 10;
+
+ // map from resource to item
+ private HashMap fResourceToItem;
+
+ private Stack fReuseLists;
+
+ private ContentViewer fContentViewer;
+
+ public ResourceToItemsMapper(ContentViewer viewer) {
+ fResourceToItem = new HashMap();
+ fReuseLists = new Stack();
+
+ fContentViewer = viewer;
+ }
+
+ /**
+ * Must be called from the UI thread.
+ */
+ public void resourceChanged(IResource changedResource) {
+ Object obj = fResourceToItem.get(changedResource);
+ if (obj == null) {
+ // not mapped
+ } else if (obj instanceof Item) {
+ updateItem((Item) obj);
+ } else { // List of Items
+ List list = (List) obj;
+ for (int k = 0; k < list.size(); k++) {
+ updateItem((Item) list.get(k));
+ }
+ }
+ }
+
+ private void updateItem(Item item) {
+ if (!item.isDisposed()) { // defensive code
+ ILabelProvider lprovider = (ILabelProvider) fContentViewer
+ .getLabelProvider();
+
+ Object data = item.getData();
+
+ // If it is an IItemLabelProvider than short circuit: patch Tod (bug
+ // 55012)
+ if (lprovider instanceof IViewerLabelProvider) {
+ IViewerLabelProvider provider = (IViewerLabelProvider) lprovider;
+
+ ViewerLabel updateLabel = new ViewerLabel(item.getText(), item
+ .getImage());
+ provider.updateLabel(updateLabel, data);
+
+ if (updateLabel.hasNewImage()) {
+ item.setImage(updateLabel.getImage());
+ }
+ if (updateLabel.hasNewText()) {
+ item.setText(updateLabel.getText());
+ }
+ } else {
+ Image oldImage = item.getImage();
+ Image image = lprovider.getImage(data);
+ if (image != null && !image.equals(oldImage)) {
+ item.setImage(image);
+ }
+ String oldText = item.getText();
+ String text = lprovider.getText(data);
+ if (text != null && !text.equals(oldText)) {
+ item.setText(text);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds a new item to the map.
+ *
+ * @param element
+ * Element to map
+ * @param item
+ * The item used for the element
+ */
+ public void addToMap(Object element, Item item) {
+ IResource resource = getCorrespondingResource(element);
+ if (resource != null) {
+ Object existingMapping = fResourceToItem.get(resource);
+ if (existingMapping == null) {
+ fResourceToItem.put(resource, item);
+ } else if (existingMapping instanceof Item) {
+ if (existingMapping != item) {
+ List list = getNewList();
+ list.add(existingMapping);
+ list.add(item);
+ fResourceToItem.put(resource, list);
+ }
+ } else { // List
+ List list = (List) existingMapping;
+ if (!list.contains(item)) {
+ list.add(item);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes an element from the map.
+ */
+ public void removeFromMap(Object element, Item item) {
+ IResource resource = getCorrespondingResource(element);
+ if (resource != null) {
+ Object existingMapping = fResourceToItem.get(resource);
+ if (existingMapping == null) {
+ return;
+ } else if (existingMapping instanceof Item) {
+ fResourceToItem.remove(resource);
+ } else { // List
+ List list = (List) existingMapping;
+ list.remove(item);
+ if (list.isEmpty()) {
+ fResourceToItem.remove(list);
+ releaseList(list);
+ }
+ }
+ }
+ }
+
+ private List getNewList() {
+ if (!fReuseLists.isEmpty()) {
+ return (List) fReuseLists.pop();
+ }
+ return new ArrayList(2);
+ }
+
+ private void releaseList(List list) {
+ if (fReuseLists.size() < NUMBER_LIST_REUSE) {
+ fReuseLists.push(list);
+ }
+ }
+
+ /**
+ * Clears the map.
+ */
+ public void clearMap() {
+ fResourceToItem.clear();
+ }
+
+ /**
+ * Tests if the map is empty
+ */
+ public boolean isEmpty() {
+ return fResourceToItem.isEmpty();
+ }
+
+ /**
+ * Method that decides which elements can have error markers Returns null if
+ * an element can not have error markers.
+ */
+ private static IResource getCorrespondingResource(Object element) {
+ if (element instanceof IJavaElement) {
+ IJavaElement elem = (IJavaElement) element;
+ if (!elem.isReadOnly()) { // only modifieable elements can get
+ // error ticks
+ IResource res = elem.getResource();
+ if (res == null) {
+ ICompilationUnit cu = (ICompilationUnit) elem
+ .getAncestor(IJavaElement.COMPILATION_UNIT);
+ if (cu != null) {
+ // elements in compilation units are mapped to the
+ // underlying resource of the original cu
+ res = cu.getResource();
+ }
+ }
+ return res;
+ }
+ return null;
+ } else if (element instanceof IResource) {
+ return (IResource) element;
+ }
+ return null;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java
new file mode 100644
index 0000000..682852d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Infrastructure to share an AST for editor post selection listeners.
+ */
+public class SelectionListenerWithASTManager {
+
+ private static SelectionListenerWithASTManager fgDefault;
+
+ /**
+ * @return Returns the default manager instance.
+ */
+ public static SelectionListenerWithASTManager getDefault() {
+ if (fgDefault == null) {
+ fgDefault = new SelectionListenerWithASTManager();
+ }
+ return fgDefault;
+ }
+
+ private final static class PartListenerGroup {
+ private ITextEditor fPart;
+
+ private ISelectionChangedListener fSelectionListener,
+ fPostSelectionListener;
+
+ private Job fCurrentJob;
+
+ private ListenerList fAstListeners;
+
+ /**
+ * Lock to avoid having more than one calculateAndInform job in
+ * parallel. Only jobs may synchronize on this as otherwise deadlocks
+ * are possible.
+ */
+ private final Object fJobLock = new Object();
+
+ public PartListenerGroup(ITextEditor part) {
+ fPart = part;
+ fCurrentJob = null;
+ fAstListeners = new ListenerList();
+
+ fSelectionListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if (selection instanceof ITextSelection) {
+ fireSelectionChanged((ITextSelection) selection);
+ }
+ }
+ };
+
+ fPostSelectionListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if (selection instanceof ITextSelection) {
+ firePostSelectionChanged((ITextSelection) selection);
+ }
+ }
+ };
+ }
+
+ public boolean isEmpty() {
+ return fAstListeners.isEmpty();
+ }
+
+ public void install(ISelectionListenerWithAST listener) {
+ if (isEmpty()) {
+ ISelectionProvider selectionProvider = fPart
+ .getSelectionProvider();
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ ((IPostSelectionProvider) selectionProvider)
+ .addPostSelectionChangedListener(fPostSelectionListener);
+ selectionProvider
+ .addSelectionChangedListener(fSelectionListener);
+ }
+ }
+ fAstListeners.add(listener);
+ }
+
+ public void uninstall(ISelectionListenerWithAST listener) {
+ fAstListeners.remove(listener);
+ if (isEmpty()) {
+ ISelectionProvider selectionProvider = fPart
+ .getSelectionProvider();
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ ((IPostSelectionProvider) selectionProvider)
+ .removePostSelectionChangedListener(fPostSelectionListener);
+ selectionProvider
+ .removeSelectionChangedListener(fSelectionListener);
+ }
+ }
+ }
+
+ public void fireSelectionChanged(final ITextSelection selection) {
+ if (fCurrentJob != null) {
+ fCurrentJob.cancel();
+ }
+ }
+
+ public void firePostSelectionChanged(final ITextSelection selection) {
+ if (fCurrentJob != null) {
+ fCurrentJob.cancel();
+ }
+
+ fCurrentJob = new Job("SelectionListenerWithASTManager Job") {// JavaUIMessages.SelectionListenerWithASTManager_job_title)
+ // {
+ public IStatus run(IProgressMonitor monitor) {
+ if (monitor == null) {
+ monitor = new NullProgressMonitor();
+ }
+ synchronized (fJobLock) {
+ return calculateASTandInform(/*input,*/ selection, monitor);
+ }
+ }
+ };
+ fCurrentJob.setPriority(Job.DECORATE);
+ fCurrentJob.setSystem(true);
+ fCurrentJob.schedule();
+ }
+
+ protected IStatus calculateASTandInform(/*IJavaElement input,*/
+ ITextSelection selection, IProgressMonitor monitor) {
+ if (monitor.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+ // create AST
+ try {
+ // CompilationUnit astRoot=
+ // PHPeclipsePlugin.getDefault().getASTProvider().getAST(input,
+ // ASTProvider.WAIT_ACTIVE_ONLY, monitor);
+
+ // if (astRoot != null && !monitor.isCanceled()) {
+ Object[] listeners;
+ synchronized (PartListenerGroup.this) {
+ listeners = fAstListeners.getListeners();
+ }
+ for (int i = 0; i < listeners.length; i++) {
+ ((ISelectionListenerWithAST) listeners[i])
+ .selectionChanged(fPart, selection);// , astRoot);
+ if (monitor.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+ }
+ return Status.OK_STATUS;
+ // }
+ } catch (OperationCanceledException e) {
+ // thrown when cancelling the AST creation
+ }
+ return Status.CANCEL_STATUS;
+ }
+ }
+
+ private Map fListenerGroups;
+
+ private SelectionListenerWithASTManager() {
+ fListenerGroups = new HashMap();
+ }
+
+ /**
+ * Registers a selection listener for the given editor part.
+ *
+ * @param part
+ * The editor part to listen to.
+ * @param listener
+ * The listener to register.
+ */
+ public void addListener(ITextEditor part, ISelectionListenerWithAST listener) {
+ synchronized (this) {
+ PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
+ .get(part);
+ if (partListener == null) {
+ partListener = new PartListenerGroup(part);
+ fListenerGroups.put(part, partListener);
+ }
+ partListener.install(listener);
+ }
+ }
+
+ /**
+ * Unregisters a selection listener.
+ *
+ * @param part
+ * The editor part the listener was registered.
+ * @param listener
+ * The listener to unregister.
+ */
+ public void removeListener(ITextEditor part,
+ ISelectionListenerWithAST listener) {
+ synchronized (this) {
+ PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
+ .get(part);
+ if (partListener != null) {
+ partListener.uninstall(listener);
+ if (partListener.isEmpty()) {
+ fListenerGroups.remove(part);
+ }
+ }
+ }
+ }
+
+ /**
+ * Forces a selection changed event that is sent to all listeners registered
+ * to the given editor part. The event is sent from a background thread:
+ * this method call can return before the listeners are informed.
+ *
+ * @param part
+ * The editor part that has a changed selection
+ * @param selection
+ * The new text selection
+ */
+ public void forceSelectionChange(ITextEditor part, ITextSelection selection) {
+ synchronized (this) {
+ PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
+ .get(part);
+ if (partListener != null) {
+ partListener.firePostSelectionChanged(selection);
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/StatusBarUpdater.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/StatusBarUpdater.java
new file mode 100644
index 0000000..978536f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/StatusBarUpdater.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+
+/**
+ * Add the StatusBarUpdater
to your ViewPart to have the
+ * statusbar describing the selected elements.
+ */
+public class StatusBarUpdater implements ISelectionChangedListener {
+
+ private final int LABEL_FLAGS = JavaElementLabels.DEFAULT_QUALIFIED
+ | JavaElementLabels.ROOT_POST_QUALIFIED
+ | JavaElementLabels.APPEND_ROOT_PATH
+ | JavaElementLabels.M_PARAMETER_TYPES
+ | JavaElementLabels.M_PARAMETER_NAMES
+ | JavaElementLabels.M_APP_RETURNTYPE
+ | JavaElementLabels.M_EXCEPTIONS
+ | JavaElementLabels.F_APP_TYPE_SIGNATURE;
+
+ private IStatusLineManager fStatusLineManager;
+
+ public StatusBarUpdater(IStatusLineManager statusLineManager) {
+ fStatusLineManager = statusLineManager;
+ }
+
+ /*
+ * @see ISelectionChangedListener#selectionChanged
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ String statusBarMessage = formatMessage(event.getSelection());
+ fStatusLineManager.setMessage(statusBarMessage);
+ }
+
+ protected String formatMessage(ISelection sel) {
+ if (sel instanceof IStructuredSelection && !sel.isEmpty()) {
+ IStructuredSelection selection = (IStructuredSelection) sel;
+
+ int nElements = selection.size();
+ if (nElements > 1) {
+ return PHPUIMessages
+ .getFormattedString(
+ "StatusBarUpdater.num_elements_selected", String.valueOf(nElements)); //$NON-NLS-1$
+ } else {
+ Object elem = selection.getFirstElement();
+ if (elem instanceof IJavaElement) {
+ return formatJavaElementMessage((IJavaElement) elem);
+ } else if (elem instanceof IResource) {
+ return formatResourceMessage((IResource) elem);
+ }
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ private String formatJavaElementMessage(IJavaElement element) {
+ return JavaElementLabels.getElementLabel(element, LABEL_FLAGS);
+ }
+
+ private String formatResourceMessage(IResource element) {
+ IContainer parent = element.getParent();
+ if (parent != null && parent.getType() != IResource.ROOT)
+ return element.getName() + JavaElementLabels.CONCAT_STRING
+ + parent.getFullPath().makeRelative().toString();
+ else
+ return element.getName();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/StorageLabelProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/StorageLabelProvider.java
new file mode 100644
index 0000000..a5d86bc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/viewsupport/StorageLabelProvider.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IFileEditorMapping;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Standard label provider for IStorage objects. Use this class when you want to
+ * present IStorage objects in a viewer.
+ */
+public class StorageLabelProvider extends LabelProvider {
+
+ private IEditorRegistry fEditorRegistry = PlatformUI.getWorkbench()
+ .getEditorRegistry();
+
+ private Map fJarImageMap = new HashMap(10);
+
+ private Image fDefaultImage;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelProvider#getImage
+ */
+ public Image getImage(Object element) {
+ if (element instanceof IStorage)
+ return getImageForJarEntry((IStorage) element);
+
+ return super.getImage(element);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelProvider#getText
+ */
+ public String getText(Object element) {
+ if (element instanceof IStorage)
+ return ((IStorage) element).getName();
+
+ return super.getText(element);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#dispose
+ */
+ public void dispose() {
+ if (fJarImageMap != null) {
+ Iterator each = fJarImageMap.values().iterator();
+ while (each.hasNext()) {
+ Image image = (Image) each.next();
+ image.dispose();
+ }
+ fJarImageMap = null;
+ }
+ if (fDefaultImage != null)
+ fDefaultImage.dispose();
+ fDefaultImage = null;
+ }
+
+ /*
+ * Gets and caches an image for a JarEntryFile. The image for a JarEntryFile
+ * is retrieved from the EditorRegistry.
+ */
+ private Image getImageForJarEntry(IStorage element) {
+ if (fJarImageMap == null)
+ return getDefaultImage();
+
+ if (element == null || element.getName() == null)
+ return getDefaultImage();
+
+ // Try to find icon for full name
+ String name = element.getName();
+ Image image = (Image) fJarImageMap.get(name);
+ if (image != null)
+ return image;
+ IFileEditorMapping[] mappings = fEditorRegistry.getFileEditorMappings();
+ int i = 0;
+ while (i < mappings.length) {
+ if (mappings[i].getLabel().equals(name))
+ break;
+ i++;
+ }
+ String key = name;
+ if (i == mappings.length) {
+ // Try to find icon for extension
+ IPath path = element.getFullPath();
+ if (path == null)
+ return getDefaultImage();
+ key = path.getFileExtension();
+ if (key == null)
+ return getDefaultImage();
+ image = (Image) fJarImageMap.get(key);
+ if (image != null)
+ return image;
+ }
+
+ // Get the image from the editor registry
+ ImageDescriptor desc = fEditorRegistry.getImageDescriptor(name);
+ image = desc.createImage();
+
+ fJarImageMap.put(key, image);
+
+ return image;
+ }
+
+ private Image getDefaultImage() {
+ if (fDefaultImage == null)
+ fDefaultImage = fEditorRegistry.getImageDescriptor((String) null)
+ .createImage();
+ return fDefaultImage;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/IStatusChangeListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/IStatusChangeListener.java
new file mode 100644
index 0000000..4e1a2ab
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/IStatusChangeListener.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards;
+
+import org.eclipse.core.runtime.IStatus;
+
+public interface IStatusChangeListener {
+
+ /**
+ * Notifies this listener that the given status has changed.
+ *
+ * @param status
+ * the new status
+ */
+ void statusChanged(IStatus status);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewClassCreationWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewClassCreationWizard.java
new file mode 100644
index 0000000..89a5050
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewClassCreationWizard.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.ui.wizards.NewClassWizardPage;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public class NewClassCreationWizard extends NewElementWizard {
+
+ private NewClassWizardPage fPage;
+
+ public NewClassCreationWizard() {
+ super();
+ setDefaultPageImageDescriptor(PHPUiImages.DESC_WIZBAN_NEWCLASS);
+ setDialogSettings(WebUI.getDefault().getDialogSettings());
+ setWindowTitle(NewWizardMessages
+ .getString("NewClassCreationWizard.title")); //$NON-NLS-1$
+ }
+
+ /*
+ * @see Wizard#createPages
+ */
+ public void addPages() {
+ super.addPages();
+ fPage = new NewClassWizardPage();
+ addPage(fPage);
+ fPage.init(getSelection());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.ui.wizards.NewElementWizard#finishPage(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void finishPage(IProgressMonitor monitor)
+ throws InterruptedException, CoreException {
+ fPage.createType(monitor); // use the full progress monitor
+ ICompilationUnit cu = JavaModelUtil.toOriginal(fPage.getCreatedType()
+ .getCompilationUnit());
+ if (cu != null) {
+ IResource resource = cu.getResource();
+ selectAndReveal(resource);
+ openResource((IFile) resource);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.wizard.IWizard#performFinish()
+ */
+ public boolean performFinish() {
+ // warnAboutTypeCommentDeprecation();
+ return super.performFinish();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewElementWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewElementWizard.java
new file mode 100644
index 0000000..f6f0882
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewElementWizard.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards;
+
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.internal.ui.actions.WorkbenchRunnableAdapter;
+import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+
+public abstract class NewElementWizard extends Wizard implements INewWizard {
+
+ private IWorkbench fWorkbench;
+
+ private IStructuredSelection fSelection;
+
+ public NewElementWizard() {
+ setNeedsProgressMonitor(true);
+ }
+
+ protected void openResource(final IFile resource) {
+ final IWorkbenchPage activePage = WebUI.getActivePage();
+ if (activePage != null) {
+ final Display display = getShell().getDisplay();
+ if (display != null) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ try {
+ IDE.openEditor(activePage, resource, true);
+ } catch (PartInitException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Subclasses should override to perform the actions of the wizard. This
+ * method is run in the wizard container's context as a workspace runnable.
+ */
+ protected void finishPage(IProgressMonitor monitor)
+ throws InterruptedException, CoreException {
+ }
+
+ protected void handleFinishException(Shell shell,
+ InvocationTargetException e) {
+ String title = NewWizardMessages
+ .getString("NewElementWizard.op_error.title"); //$NON-NLS-1$
+ String message = NewWizardMessages
+ .getString("NewElementWizard.op_error.message"); //$NON-NLS-1$
+ ExceptionHandler.handle(e, shell, title, message);
+ }
+
+ /*
+ * @see Wizard#performFinish
+ */
+ public boolean performFinish() {
+ IWorkspaceRunnable op = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException,
+ OperationCanceledException {
+ try {
+ finishPage(monitor);
+ } catch (InterruptedException e) {
+ throw new OperationCanceledException(e.getMessage());
+ }
+ }
+ };
+ try {
+ getContainer().run(false, true, new WorkbenchRunnableAdapter(op));
+ } catch (InvocationTargetException e) {
+ handleFinishException(getShell(), e);
+ return false;
+ } catch (InterruptedException e) {
+ return false;
+ }
+ return true;
+ }
+
+ // protected void warnAboutTypeCommentDeprecation() {
+ // String key= IUIConstants.DIALOGSTORE_TYPECOMMENT_DEPRECATED;
+ // if (OptionalMessageDialog.isDialogEnabled(key)) {
+ // Templates templates= Templates.getInstance();
+ // boolean isOldWorkspace= templates.getTemplates("filecomment").length > 0
+ // && templates.getTemplates("typecomment").length > 0;
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // if (!isOldWorkspace) {
+ // OptionalMessageDialog.setDialogEnabled(key, false);
+ // }
+ // String title=
+ // NewWizardMessages.getString("NewElementWizard.typecomment.deprecated.title");
+ // //$NON-NLS-1$
+ // String message=
+ // NewWizardMessages.getString("NewElementWizard.typecomment.deprecated.message");
+ // //$NON-NLS-1$
+ // OptionalMessageDialog.open(key, getShell(), title,
+ // OptionalMessageDialog.getDefaultImage(), message,
+ // OptionalMessageDialog.INFORMATION, new String[] {
+ // IDialogConstants.OK_LABEL }, 0);
+ // }
+ // }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench,
+ * org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
+ fWorkbench = workbench;
+ fSelection = currentSelection;
+ }
+
+ public IStructuredSelection getSelection() {
+ return fSelection;
+ }
+
+ public IWorkbench getWorkbench() {
+ return fWorkbench;
+ }
+
+ protected void selectAndReveal(IResource newResource) {
+ BasicNewResourceWizard.selectAndReveal(newResource, fWorkbench
+ .getActiveWorkbenchWindow());
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewWizardMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewWizardMessages.java
new file mode 100644
index 0000000..a78bece
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewWizardMessages.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class NewWizardMessages {
+
+ private static final String RESOURCE_BUNDLE = NewWizardMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private NewWizardMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewWizardMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewWizardMessages.properties
new file mode 100644
index 0000000..add51e7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/NewWizardMessages.properties
@@ -0,0 +1,564 @@
+###############################################################################
+# Copyright (c) 2000, 2003 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+# ------- AbstractOpenWizardAction -------
+
+AbstractOpenWizardAction.noproject.title=New
+AbstractOpenWizardAction.noproject.message=A project needs to be created first.\nOpen the 'New Project' wizard'?
+
+AbstractOpenWizardAction.createerror.title=Open Wizard
+AbstractOpenWizardAction.createerror.message=The wizard could not be opened. See log for details.
+
+# ------- NewElementWizard -------
+
+NewElementWizard.op_error.title=New
+NewElementWizard.op_error.message=Creation of element failed.
+
+NewElementWizard.typecomment.deprecated.title=Type Creation
+NewElementWizard.typecomment.deprecated.message=You can configure the default layout of newly created files and types on the 'code generation' preference page. This was previously implemented on the template page in the templates 'filecomment' and 'typecomment'.
+# ------- NewContainerWizardPage -------
+
+NewContainerWizardPage.container.label=Source Fol&der:
+NewContainerWizardPage.container.button=Br&owse...
+
+NewContainerWizardPage.error.EnterContainerName=Folder name is empty.
+NewContainerWizardPage.error.ContainerIsBinary=''{0}'' is a JAR archive.
+NewContainerWizardPage.error.ContainerDoesNotExist=Folder ''{0}'' does not exist.
+NewContainerWizardPage.error.NotAFolder=''{0}'' must be a project or folder.
+NewContainerWizardPage.error.ProjectClosed=Project ''{0}'' must be accessible.
+
+NewContainerWizardPage.warning.NotAJavaProject=Folder is not a Java project.
+NewContainerWizardPage.warning.NotInAJavaProject=Folder is not in a Java project.
+NewContainerWizardPage.warning.NotOnClassPath=Folder is not on the Java build class path.
+
+NewContainerWizardPage.ChooseSourceContainerDialog.title=Folder Selection
+NewContainerWizardPage.ChooseSourceContainerDialog.description=&Choose a folder:
+
+# ------- NewPackageWizardPage -------
+
+NewPackageCreationWizard.title=New Java Package
+
+NewPackageWizardPage.package.label=&Name:
+
+
+NewPackageWizardPage.error.InvalidPackageName=Invalid package name. {0}
+NewPackageWizardPage.error.IsOutputFolder=Name conflict with output folder.
+
+NewPackageWizardPage.error.PackageExists=Package already exists.
+NewPackageWizardPage.error.EnterName=Enter a package name.
+NewPackageWizardPage.warning.PackageNotShown=Package already exists. Note: Views might filter empty parent packages.
+NewPackageWizardPage.warning.DiscouragedPackageName=Discouraged package name. {0}
+
+NewPackageWizardPage.title=Java Package
+NewPackageWizardPage.description=Create a Java package.
+NewPackageWizardPage.info=Creates folders corresponding to packages.
+# ------- NewTypeWizardPage -------
+
+NewTypeWizardPage.package.label=Pac&kage:
+NewTypeWizardPage.package.button=Bro&wse...
+
+NewTypeWizardPage.enclosing.selection.label=Enclosing t&ype:
+NewTypeWizardPage.enclosing.button=Bro&wse...
+
+NewTypeWizardPage.error.InvalidPackageName=Package name is not valid. {0}
+NewTypeWizardPage.error.ClashOutputLocation=Package clashes with project output folder.
+NewTypeWizardPage.warning.DiscouragedPackageName=This package name is discouraged. {0}
+
+NewTypeWizardPage.default=(default)
+
+NewTypeWizardPage.ChoosePackageDialog.title=Package Selection
+NewTypeWizardPage.ChoosePackageDialog.description=&Choose a folder:
+NewTypeWizardPage.ChoosePackageDialog.empty=Cannot find packages to select.
+
+NewTypeWizardPage.ChooseEnclosingTypeDialog.title=Enclosing Type Selection
+NewTypeWizardPage.ChooseEnclosingTypeDialog.description=&Choose a type to which the new class will be added:
+
+NewTypeWizardPage.error.EnclosingTypeEnterName=Name of enclosing type must be entered.
+NewTypeWizardPage.error.EnclosingTypeNotExists=Enclosing type does not exist.
+NewTypeWizardPage.error.EnclosingNotInCU=Enclosing type is binary.
+NewTypeWizardPage.error.EnclosingNotEditable=Enclosing type is not editable.
+NewTypeWizardPage.warning.EnclosingNotInSourceFolder=Enclosing type is not in specified source folder.
+
+NewTypeWizardPage.typename.label=Na&me:
+
+NewTypeWizardPage.superclass.label=&Superclass:
+NewTypeWizardPage.superclass.button=Brows&e...
+
+NewTypeWizardPage.interfaces.class.label=&Interfaces:
+NewTypeWizardPage.interfaces.ifc.label=Extended &interfaces:
+NewTypeWizardPage.interfaces.add=&Add...
+NewTypeWizardPage.interfaces.remove=&Remove
+
+NewTypeWizardPage.modifiers.acc.label=Modifiers:
+NewTypeWizardPage.modifiers.public=&public
+NewTypeWizardPage.modifiers.private=pri&vate
+NewTypeWizardPage.modifiers.protected=pro&tected
+NewTypeWizardPage.modifiers.default=defa&ult
+NewTypeWizardPage.modifiers.abstract=abs&tract
+NewTypeWizardPage.modifiers.final=fina&l
+NewTypeWizardPage.modifiers.static=stati&c
+
+NewTypeWizardPage.error.EnterTypeName=Type name is empty.
+NewTypeWizardPage.error.TypeNameExists=Type already exists.
+NewTypeWizardPage.error.InvalidTypeName=Type name is not valid. {0}
+NewTypeWizardPage.error.QualifiedName=Type name must not be qualified.
+NewTypeWizardPage.warning.TypeNameDiscouraged=Type name is discouraged. {0}
+
+NewTypeWizardPage.error.InvalidSuperClassName=Superclass name is not valid.
+NewTypeWizardPage.warning.SuperClassNotExists=Warning: Superclass does not exist in current project.
+NewTypeWizardPage.warning.SuperClassIsFinal=Warning: Superclass ''{0}'' is final.
+NewTypeWizardPage.warning.SuperClassIsNotVisible=Warning: Superclass ''{0}'' is not visible.
+NewTypeWizardPage.warning.SuperClassIsNotClass=Warning: Superclass ''{0}'' is an interface.
+
+NewTypeWizardPage.warning.InterfaceIsNotVisible=Extended interface ''{0}'' is not visible.
+NewTypeWizardPage.warning.InterfaceNotExists=Extended interface ''{0}'' does not exist in current project.
+NewTypeWizardPage.warning.InterfaceIsNotInterface=Extended interface ''{0}'' is not an interface.
+
+NewTypeWizardPage.error.ModifiersFinalAndAbstract=Class cannot be both final and abstract
+
+NewTypeWizardPage.SuperClassDialog.title=Superclass Selection
+NewTypeWizardPage.SuperClassDialog.message=&Choose a type:
+
+NewTypeWizardPage.InterfacesDialog.class.title= Implemented Interfaces Selection
+NewTypeWizardPage.InterfacesDialog.interface.title= Extended Interfaces Selection
+NewTypeWizardPage.InterfacesDialog.message=&Choose interfaces:
+
+NewTypeWizardPage.operationdesc=Creating type....
+
+# ------- SuperInterfaceSelectionDialog -----
+
+SuperInterfaceSelectionDialog.addButton.label=&Add
+SuperInterfaceSelectionDialog.interfaceadded.info=''{0}'' added.
+
+# ------- NewClassWizardPage -------
+
+NewClassCreationWizard.title=New Java Class
+
+NewClassWizardPage.title=Java Class
+NewClassWizardPage.description=Create a new Java class.
+
+NewClassWizardPage.methods.label=Which method stubs would you like to create?
+NewClassWizardPage.methods.main=public static void main(Strin&g[] args)
+NewClassWizardPage.methods.constructors=&Constructors from superclass
+NewClassWizardPage.methods.inherited=In&herited abstract methods
+
+
+# ------- NewInterfaceWizardPage -------
+
+NewInterfaceCreationWizard.title=New Java Interface
+
+NewInterfaceWizardPage.title=Java Interface
+NewInterfaceWizardPage.description=Create a new Java interface.
+
+# ------- JavaCapabilityWizard -------
+
+JavaCapabilityWizard.title=Configure Java Capability
+JavaCapabilityWizard.op_error.title=Error Configure Java Capability
+JavaCapabilityWizard.op_error.message=An error occurred while configuring the Java project
+
+# ------- JavaCapabilityConfigurationPage -------
+
+JavaCapabilityConfigurationPage.title=Java Settings
+JavaCapabilityConfigurationPage.description=Define the Java build settings.
+JavaCapabilityConfigurationPage.op_desc_java=Configuring Java project...
+
+
+# ------- NewProjectCreationWizard -------
+
+NewProjectCreationWizard.title=New Java Project
+NewProjectCreationWizard.op_error.title=Error Creating Java Project
+NewProjectCreationWizard.op_error_create.message=An error occurred while creating the Java project
+NewProjectCreationWizard.MainPage.title=Java Project
+NewProjectCreationWizard.MainPage.description=Create a new Java project.
+
+NewProjectCreationWizardPage.op_error.title=Error Creating Java Project
+NewProjectCreationWizardPage.op_error_remove.message=An error occurred while removing a temporary project
+NewProjectCreationWizardPage.EarlyCreationOperation.desc=Creating project and examining existing resources...
+NewProjectCreationWizardPage.EarlyCreationOperation.error.title=New Java Project
+NewProjectCreationWizardPage.EarlyCreationOperation.error.desc=An error occurred while creating project. Check log for details.
+NewProjectCreationWizardPage.createproject.desc=Creating project...
+NewProjectCreationWizardPage.removeproject.desc=Removing project...
+
+# ------- NewJavaProjectWizardPage-------
+
+NewJavaProjectWizardPage.title=Java Settings
+NewJavaProjectWizardPage.description=Define the Java build settings.
+
+NewJavaProjectWizardPage.op_desc=Creating Java project...
+
+
+# ------- NewSourceFolderWizardPage-------
+
+NewSourceFolderCreationWizard.title=New Source Folder
+
+NewSourceFolderWizardPage.title=Source folder
+NewSourceFolderWizardPage.description=Add a new source folder
+
+NewSourceFolderWizardPage.root.label=Fol&der name:
+NewSourceFolderWizardPage.root.button=Br&owse...
+
+NewSourceFolderWizardPage.project.label=Project &name:
+NewSourceFolderWizardPage.project.button=Bro&wse...
+
+NewSourceFolderWizardPage.exclude.label=&Update exclusion filters in other source folders to solve nesting.
+
+NewSourceFolderWizardPage.ChooseExistingRootDialog.title=Existing Folder Selection
+NewSourceFolderWizardPage.ChooseExistingRootDialog.description=&Choose folder as source folder:
+
+NewSourceFolderWizardPage.ChooseProjectDialog.title=Project Selection
+NewSourceFolderWizardPage.ChooseProjectDialog.description=&Choose project for the new source folder:
+
+NewSourceFolderWizardPage.error.EnterRootName=Root name must be entered.
+NewSourceFolderWizardPage.error.InvalidRootName=Invalid folder name. {0}
+NewSourceFolderWizardPage.error.NotAFolder=Not a folder.
+NewSourceFolderWizardPage.error.AlreadyExisting=Already a source folder.
+
+NewSourceFolderWizardPage.error.EnterProjectName=Project name must be entered.
+NewSourceFolderWizardPage.error.InvalidProjectPath=Invalid project path.
+NewSourceFolderWizardPage.error.NotAJavaProject=Project is not a Java project.
+NewSourceFolderWizardPage.error.ProjectNotExists=Project does not exist.
+
+NewSourceFolderWizardPage.warning.ReplaceSFandOL=To avoid overlapping, the existing project source folder entry will be replaced and the output folder set to ''{0}''.
+NewSourceFolderWizardPage.warning.ReplaceOL=An exclusion pattern will be added to the project source folder entry and the output folder will be set to ''{0}''.
+NewSourceFolderWizardPage.warning.ReplaceSF=To avoid overlapping, the existing project source folder entry will be replaced.
+NewSourceFolderWizardPage.warning.AddedExclusions=Exclusion patterns of {0} source folder(s) updated to solve nesting.
+
+# ------- NewSnippetFileWizardPage-------
+
+NewSnippetFileCreationWizard.title=New Scrapbook Page
+
+NewSnippetFileWizardPage.title=Create Java Scrapbook Page
+
+NewSnippetFileWizardPage.error.AlreadyExists=A resource with the specified path already exists.
+NewSnippetFileWizardPage.error.OnlyInJavaProject=The scrapbook page can only be created in a Java project.
+
+NewSnippetFileWizardPage.open_error.message=Error in NewScrapbookPage
+
+# ------- BuildPathsBlock -------
+
+BuildPathsBlock.tab.source=&Source
+BuildPathsBlock.tab.projects=&Projects
+BuildPathsBlock.tab.libraries=&Libraries
+BuildPathsBlock.tab.order=&Order and Export
+
+BuildPathsBlock.classpath.label=Build &class path order and exported entries:\n(Exported entries are contributed to dependent projects)
+
+BuildPathsBlock.classpath.up.button=&Up
+BuildPathsBlock.classpath.down.button=&Down
+BuildPathsBlock.classpath.checkall.button=Select &All
+BuildPathsBlock.classpath.uncheckall.button=D&eselect All
+
+BuildPathsBlock.buildpath.label=Defaul&t output folder:
+BuildPathsBlock.buildpath.button=Bro&wse...
+
+BuildPathsBlock.error.InvalidBuildPath=Invalid build output folder: ''{0}''
+BuildPathsBlock.error.EnterBuildPath=Build output folder must be entered.
+
+BuildPathsBlock.warning.EntryMissing=Build path entry is missing: {0}
+BuildPathsBlock.warning.EntriesMissing={0} build path entries are missing.
+
+BuildPathsBlock.operationdesc_project=Creating project...
+BuildPathsBlock.operationdesc_java=Setting build paths...
+
+BuildPathsBlock.ChooseOutputFolderDialog.title=Folder Selection
+BuildPathsBlock.ChooseOutputFolderDialog.description=&Choose the folder for the build output:
+
+BuildPathsBlock.RemoveBinariesDialog.title=Setting Build Paths
+BuildPathsBlock.RemoveBinariesDialog.description=The output folder has changed. OK to remove all generated resources from the old location ''{0}''?
+
+# ------- CPListLabelProvider -------
+
+CPListLabelProvider.new=(new)
+CPListLabelProvider.classcontainer=(class folder)
+CPListLabelProvider.twopart={0} - {1}
+CPListLabelProvider.willbecreated=(will be created)
+
+
+# ------- SourceContainerWorkbookPage-------
+
+SourceContainerWorkbookPage.folders.label=Source folders on build pat&h:
+SourceContainerWorkbookPage.folders.remove.button=&Remove
+SourceContainerWorkbookPage.folders.add.button=&Add Folder...
+SourceContainerWorkbookPage.folders.edit.button=&Edit...
+
+SourceContainerWorkbookPage.folders.check=Allow output folders for sour&ce folders.
+
+SourceContainerWorkbookPage.ExistingSourceFolderDialog.new.title=Source Folder Selection
+SourceContainerWorkbookPage.ExistingSourceFolderDialog.new.description=&Choose source folders to be added to the build path:
+
+SourceContainerWorkbookPage.ExistingSourceFolderDialog.edit.title=Source Folder Selection
+SourceContainerWorkbookPage.ExistingSourceFolderDialog.edit.description=&Select the source folder:
+
+SourceContainerWorkbookPage.NewSourceFolderDialog.new.title=New Source Folder
+SourceContainerWorkbookPage.NewSourceFolderDialog.edit.title=Edit Source Folder
+
+SourceContainerWorkbookPage.NewSourceFolderDialog.description=&Enter a path relative to ''{0}'':
+
+SourceContainerWorkbookPage.ChangeOutputLocationDialog.title=Source Folder Added
+SourceContainerWorkbookPage.ChangeOutputLocationDialog.project_and_output.message=Do you want to remove the project as source folder and update build output folder to ''{0}''?
+SourceContainerWorkbookPage.ChangeOutputLocationDialog.project.message=Do you want to remove the project as source folder?
+
+SourceContainerWorkbookPage.exclusion_added.title=Source Folder Added
+SourceContainerWorkbookPage.exclusion_added.message=Exclusion filters have been added to nesting folders.
+
+# ------- ProjectsWorkbookPage-------
+
+ProjectsWorkbookPage.projects.label=&Required projects on the build path:
+ProjectsWorkbookPage.projects.checkall.button=Select &All
+ProjectsWorkbookPage.projects.uncheckall.button=&Deselect All
+
+# ------- LibrariesWorkbookPage-------
+
+LibrariesWorkbookPage.libraries.label=JARs &and class folders on the build path:
+LibrariesWorkbookPage.libraries.remove.button=&Remove
+
+LibrariesWorkbookPage.libraries.addjar.button=Add &JARs...
+LibrariesWorkbookPage.libraries.addextjar.button=Add E&xternal JARs...
+LibrariesWorkbookPage.libraries.addvariable.button=Add &Variable...
+LibrariesWorkbookPage.libraries.addlibrary.button=Add Li&brary...
+LibrariesWorkbookPage.libraries.addclassfolder.button=Add Class &Folder...
+
+
+LibrariesWorkbookPage.libraries.edit.button=&Edit...
+
+LibrariesWorkbookPage.ExistingClassFolderDialog.new.title=Class Folder Selection
+LibrariesWorkbookPage.ExistingClassFolderDialog.new.description=&Choose class folders to be added to the build path:
+
+LibrariesWorkbookPage.ExistingClassFolderDialog.edit.title=Edit Class Folder
+LibrariesWorkbookPage.ExistingClassFolderDialog.edit.description=&Select the class folder:
+
+LibrariesWorkbookPage.NewClassFolderDialog.new.title=New Class Folder
+LibrariesWorkbookPage.NewClassFolderDialog.edit.title=Edit Class Folder
+
+LibrariesWorkbookPage.NewClassFolderDialog.description=&Enter a path relative to ''{0}'':
+
+LibrariesWorkbookPage.JARArchiveDialog.new.title=JAR Selection
+LibrariesWorkbookPage.JARArchiveDialog.new.description=&Choose jar archives to be added to the build path:
+
+LibrariesWorkbookPage.JARArchiveDialog.edit.title=Edit JAR
+LibrariesWorkbookPage.JARArchiveDialog.edit.description=&Select the jar archive:
+
+LibrariesWorkbookPage.ContainerDialog.new.title=Add Library
+LibrariesWorkbookPage.ContainerDialog.edit.title=Edit Library
+
+LibrariesWorkbookPage.VariableSelectionDialog.new.title=New Variable Classpath Entry
+LibrariesWorkbookPage.VariableSelectionDialog.edit.title=Edit Variable Entry
+
+LibrariesWorkbookPage.ExtJARArchiveDialog.new.title=JAR Selection
+
+LibrariesWorkbookPage.ExtJARArchiveDialog.edit.title=Edit JAR
+
+LibrariesWorkbookPage.SourceAttachmentDialog.title=Source For ''{0}''
+LibrariesWorkbookPage.JavadocPropertyDialog.title=Javadoc For ''{0}''
+
+LibrariesWorkbookPage.AdvancedDialog.title=Add Classpath Entry
+LibrariesWorkbookPage.AdvancedDialog.description=Select the entry to add to the classpath:
+LibrariesWorkbookPage.AdvancedDialog.createfolder=Create &New Class Folder
+LibrariesWorkbookPage.AdvancedDialog.addfolder=Add &Existing Class Folder
+LibrariesWorkbookPage.AdvancedDialog.addcontainer=Add &Container:
+
+# ------- NewContainerDialog-------
+
+NewContainerDialog.error.invalidpath=Invalid folder path: ''{0}''
+NewContainerDialog.error.enterpath=Folder name must be entered
+NewContainerDialog.error.pathexists=This folder is already in the list or it is an output folder.
+# ------- NewSourceFolderDialog-------
+
+NewSourceFolderDialog.error.invalidpath=Invalid folder path: ''{0}''
+NewSourceFolderDialog.error.enterpath=Folder name must be entered.
+NewSourceFolderDialog.error.pathexists=The folder is already in the list.
+
+# ------- SourceAttachmentBlock-------
+
+SourceAttachmentBlock.message=Select the location (folder, JAR or zip) containing the source for ''{0}'':
+SourceAttachmentBlock.filename.description=Source attachments for variable entries are defined by variable paths. The first segment of such a path describes a variable name, the rest is an optional path extension.
+
+SourceAttachmentBlock.filename.label=Lo&cation path:
+SourceAttachmentBlock.filename.externalfile.button=External &File...
+SourceAttachmentBlock.filename.externalfolder.button=External F&older...
+SourceAttachmentBlock.filename.internal.button=&Workspace...
+
+SourceAttachmentBlock.filename.varlabel=Lo&cation variable path:
+SourceAttachmentBlock.filename.variable.button=&Variable...
+SourceAttachmentBlock.filename.external.varbutton=&Extension....
+
+SourceAttachmentBlock.filename.error.notvalid=The archive path is not a valid path.
+SourceAttachmentBlock.filename.error.filenotexists=The path ''{0}'' does not exist.
+SourceAttachmentBlock.filename.error.varnotexists=Variable in the location path does not exist.
+SourceAttachmentBlock.filename.error.deviceinpath=Location must be described a variable path.
+SourceAttachmentBlock.filename.warning.varempty=Location variable path is empty.
+
+SourceAttachmentBlock.intjardialog.title=Source Location Selection
+SourceAttachmentBlock.intjardialog.message=&Select folder or JAR/zip archive containing the source:
+
+SourceAttachmentBlock.extvardialog.title=Variable Extension Selection
+SourceAttachmentBlock.extvardialog.description=Select source location:
+
+SourceAttachmentBlock.extjardialog.text=JAR/ZIP File Selection
+SourceAttachmentBlock.extfolderdialog.text=Folder Selection
+
+SourceAttachmentBlock.putoncpdialog.title=Setting Source Attachment
+SourceAttachmentBlock.putoncpdialog.message=Source can only be attached to libraries on the build path.\nDo you want to add the library to the build path?
+
+SourceAttachmentDialog.title=Source Attachment Configuration
+SourceAttachmentDialog.error.title=Error Attaching Source
+SourceAttachmentDialog.error.message=An error occurred while associating the source.
+
+# ------- EditVariableEntryDialog -------
+
+EditVariableEntryDialog.filename.varlabel=Edit classpath variable entry:
+EditVariableEntryDialog.filename.variable.button=&Variable...
+EditVariableEntryDialog.filename.external.varbutton=&Extension....
+
+EditVariableEntryDialog.extvardialog.title=Variable Extension Selection
+EditVariableEntryDialog.extvardialog.description=Select JAR archive:
+
+EditVariableEntryDialog.filename.error.notvalid=The archive path is not a valid path.
+EditVariableEntryDialog.filename.error.filenotexists=The path ''{0}'' does not point to an existing archive.
+EditVariableEntryDialog.filename.error.varnotexists=Variable in the archive path does not exist.
+EditVariableEntryDialog.filename.error.deviceinpath=The archive has to be described by a variable path.
+EditVariableEntryDialog.filename.warning.varempty=Archive variable path is empty.
+EditVariableEntryDialog.filename.error.alreadyexists=Classpath entry already exists.
+
+
+# ------- VariableBlock-------
+
+VariableBlock.vars.label=Defined &classpath variables:
+VariableBlock.vars.add.button=Ne&w...
+VariableBlock.vars.edit.button=&Edit...
+VariableBlock.vars.remove.button=&Remove
+VariableBlock.operation_desc=Setting classpath variables...
+
+VariableBlock.operation_errror.title=Classpath Variables
+VariableBlock.operation_errror.message=Problem while setting classpath variable. See log for details.
+
+VariableBlock.needsbuild.title=Classpath Variables Changed
+VariableBlock.needsbuild.message=The classpath variables have changed. A full rebuild is recommended to make changes effective. Do the full build now?
+
+VariablePathDialogField.variabledialog.title=Variable Selection
+
+CPVariableElementLabelProvider.reserved=(reserved)
+CPVariableElementLabelProvider.empty=(empty)
+
+# ------- VariableCreationDialog-------
+
+VariableCreationDialog.titlenew=New Variable Entry
+VariableCreationDialog.titleedit=Edit Variable Entry
+
+VariableCreationDialog.name.label=&Name:
+VariableCreationDialog.path.label=&Path:
+VariableCreationDialog.path.file.button=&File...
+VariableCreationDialog.path.dir.button=F&older...
+
+VariableCreationDialog.error.entername=Variable name must be entered.
+VariableCreationDialog.error.invalidname=Invalid name: ''{0}''.
+VariableCreationDialog.error.nameexists=Variable name already exists.
+VariableCreationDialog.error.invalidpath=The path is invalid.
+
+VariableCreationDialog.warning.pathnotexists=Path does not exist.
+
+
+VariableCreationDialog.extjardialog.text=JAR Selection
+VariableCreationDialog.extdirdialog.text=Folder Selection
+VariableCreationDialog.extdirdialog.message=&Specify folder to be represented by the variable:
+
+# ------- NewVariableEntryDialog -------
+NewVariableEntryDialog.vars.extend=E&xtend...
+NewVariableEntryDialog.vars.config=&Edit...
+
+NewVariableEntryDialog.vars.label=Select &variables to add to build path:
+
+NewVariableEntryDialog.ExtensionDialog.title=Variable Extension
+NewVariableEntryDialog.ExtensionDialog.description=Choose extensions to ''{0}''.
+
+NewVariableEntryDialog.info.isfolder=Variable points to a folder: Click 'extend' to choose an archive inside the folder.
+NewVariableEntryDialog.info.noselection=Select variable(s) to add to the classpath.
+NewVariableEntryDialog.info.selected={0} variables selected.
+
+# ------- OutputLocationDialog -------
+
+OutputLocationDialog.title=Source Folder Output Location
+
+OutputLocationDialog.usedefault.label=Project's default output folder.
+OutputLocationDialog.usespecific.label=Specific output folder (path relative to ''{0}'').
+OutputLocationDialog.location.button=Bro&wse...
+
+OutputLocationDialog.error.existingisfile=Location is an existing file
+OutputLocationDialog.error.invalidpath=Invalid path: {0}
+
+OutputLocationDialog.ChooseOutputFolder.title=Folder Selection
+OutputLocationDialog.ChooseOutputFolder.description=&Choose the folder for the build output:
+
+# ------- ExclusionPatternDialog -------
+
+ExclusionPatternDialog.title=Source Folder Exclusion Patterns
+
+ExclusionPatternDialog.pattern.label=E&xclusion patterns for ''{0}'':
+ExclusionPatternDialog.pattern.add=A&dd...
+ExclusionPatternDialog.pattern.add.multiple=Add &Multiple...
+ExclusionPatternDialog.pattern.remove=&Remove
+ExclusionPatternDialog.pattern.edit=&Edit...
+
+ExclusionPatternDialog.ChooseExclusionPattern.title=Exclusion Pattern Selection
+ExclusionPatternDialog.ChooseExclusionPattern.description=&Choose folders or files to exclude:
+
+# ------- ExclusionPatternEntryDialog -------
+
+ExclusionPatternEntryDialog.add.title=Add Exclusion Pattern
+ExclusionPatternEntryDialog.edit.title=Edit Exclusion Pattern
+ExclusionPatternEntryDialog.description=Enter a pattern for excluding files from the source folder. Allowed wildcards are '*', '?' and '**'. Examples: 'java/util/A*.java', 'java/util/', '**/Test*'.
+
+ExclusionPatternEntryDialog.pattern.label=E&xclusion pattern (Path relative to ''{0}''):
+ExclusionPatternEntryDialog.pattern.button=Bro&wse...
+
+ExclusionPatternEntryDialog.error.empty=Enter a pattern.
+ExclusionPatternEntryDialog.error.notrelative=Pattern must be a relative path.
+ExclusionPatternEntryDialog.error.exists=Pattern already exists.
+
+ExclusionPatternEntryDialog.ChooseExclusionPattern.title=Exclusion Pattern Selection
+ExclusionPatternEntryDialog.ChooseExclusionPattern.description=&Choose a folder or file to exclude:
+
+# ------- ClasspathContainerDefaultPage-------
+
+ClasspathContainerDefaultPage.title=Classpath Container
+ClasspathContainerDefaultPage.description=Select classpath container path. First segment is the container type.
+
+ClasspathContainerDefaultPage.path.label=&Classpath container path:
+
+ClasspathContainerDefaultPage.path.error.enterpath=Enter path.
+ClasspathContainerDefaultPage.path.error.invalidpath=Invalid path.
+ClasspathContainerDefaultPage.path.error.needssegment=Path needs at least one segment.
+ClasspathContainerDefaultPage.path.error.alreadyexists=Entry already exists.
+
+# ------- ClasspathContainerSelectionPage-------
+
+ClasspathContainerSelectionPage.title=Add Library
+ClasspathContainerSelectionPage.description=Select the library type to add.
+
+# ------- ClasspathContainerWizard-------
+
+ClasspathContainerWizard.pagecreationerror.title= Library Wizard
+ClasspathContainerWizard.pagecreationerror.message=Wizard page creation failed. Check log for details.
+
+
+FolderSelectionDialog.button=Create New Folder...
+CPListLabelProvider.none=(None)
+CPListLabelProvider.source_attachment.label=Source attachment:
+CPListLabelProvider.source_attachment_root.label=Source attachment root:
+CPListLabelProvider.javadoc_location.label=Javadoc location:
+CPListLabelProvider.output_folder.label=Output folder:
+CPListLabelProvider.default_output_folder.label=(Default output folder)
+CPListLabelProvider.exclusion_filter.label=Exclusion filter:
+CPListLabelProvider.exclusion_filter_separator=;
+CPListLabelProvider.unknown_element.label=unknown element
+NewSourceFolderDialog.useproject.button=&Project as source folder
+NewSourceFolderDialog.usefolder.button=&Folder as source folder
+NewSourceFolderDialog.sourcefolder.label=&Source folder name:
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/CheckedListDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/CheckedListDialogField.java
new file mode 100644
index 0000000..fe748f9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/CheckedListDialogField.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+
+/**
+ * A list with checkboxes and a button bar. Typical buttons are 'Check All' and
+ * 'Uncheck All'. List model is independend of widget creation. DialogFields
+ * controls are: Label, List and Composite containing buttons.
+ */
+public class CheckedListDialogField extends ListDialogField {
+
+ private int fCheckAllButtonIndex;
+
+ private int fUncheckAllButtonIndex;
+
+ private List fCheckElements;
+
+ public CheckedListDialogField(IListAdapter adapter,
+ String[] customButtonLabels, ILabelProvider lprovider) {
+ super(adapter, customButtonLabels, lprovider);
+ fCheckElements = new ArrayList();
+
+ fCheckAllButtonIndex = -1;
+ fUncheckAllButtonIndex = -1;
+ }
+
+ /**
+ * Sets the index of the 'check' button in the button label array passed in
+ * the constructor. The behaviour of the button marked as the check button
+ * will then be handled internally. (enable state, button invocation
+ * behaviour)
+ */
+ public void setCheckAllButtonIndex(int checkButtonIndex) {
+ Assert.isTrue(checkButtonIndex < fButtonLabels.length);
+ fCheckAllButtonIndex = checkButtonIndex;
+ }
+
+ /**
+ * Sets the index of the 'uncheck' button in the button label array passed
+ * in the constructor. The behaviour of the button marked as the uncheck
+ * button will then be handled internally. (enable state, button invocation
+ * behaviour)
+ */
+ public void setUncheckAllButtonIndex(int uncheckButtonIndex) {
+ Assert.isTrue(uncheckButtonIndex < fButtonLabels.length);
+ fUncheckAllButtonIndex = uncheckButtonIndex;
+ }
+
+ /*
+ * @see ListDialogField#createTableViewer
+ */
+ protected TableViewer createTableViewer(Composite parent) {
+ Table table = new Table(parent, SWT.CHECK + getListStyle());
+ CheckboxTableViewer tableViewer = new CheckboxTableViewer(table);
+ tableViewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent e) {
+ doCheckStateChanged(e);
+ }
+ });
+ return tableViewer;
+ }
+
+ /*
+ * @see ListDialogField#getListControl
+ */
+ public Control getListControl(Composite parent) {
+ Control control = super.getListControl(parent);
+ if (parent != null) {
+ ((CheckboxTableViewer) fTable).setCheckedElements(fCheckElements
+ .toArray());
+ }
+ return control;
+ }
+
+ /*
+ * @see DialogField#dialogFieldChanged Hooks in to get element changes to
+ * update check model.
+ */
+ public void dialogFieldChanged() {
+ for (int i = fCheckElements.size() - 1; i >= 0; i--) {
+ if (!fElements.contains(fCheckElements.get(i))) {
+ fCheckElements.remove(i);
+ }
+ }
+ super.dialogFieldChanged();
+ }
+
+ private void checkStateChanged() {
+ // call super and do not update check model
+ super.dialogFieldChanged();
+ }
+
+ /**
+ * Gets the checked elements.
+ */
+ public List getCheckedElements() {
+ return new ArrayList(fCheckElements);
+ }
+
+ /**
+ * Returns true if the element is checked.
+ */
+ public boolean isChecked(Object obj) {
+ return fCheckElements.contains(obj);
+ }
+
+ /**
+ * Sets the checked elements.
+ */
+ public void setCheckedElements(List list) {
+ fCheckElements = new ArrayList(list);
+ if (fTable != null) {
+ ((CheckboxTableViewer) fTable).setCheckedElements(list.toArray());
+ }
+ checkStateChanged();
+ }
+
+ /**
+ * Sets the checked state of an element.
+ */
+ public void setChecked(Object object, boolean state) {
+ setCheckedWithoutUpdate(object, state);
+ checkStateChanged();
+ }
+
+ /**
+ * Sets the checked state of an element. No dialog changed listener is
+ * informed.
+ */
+ public void setCheckedWithoutUpdate(Object object, boolean state) {
+ if (!fCheckElements.contains(object)) {
+ fCheckElements.add(object);
+ }
+ if (fTable != null) {
+ ((CheckboxTableViewer) fTable).setChecked(object, state);
+ }
+ }
+
+ /**
+ * Sets the check state of all elements
+ */
+ public void checkAll(boolean state) {
+ if (state) {
+ fCheckElements = getElements();
+ } else {
+ fCheckElements.clear();
+ }
+ if (fTable != null) {
+ ((CheckboxTableViewer) fTable).setAllChecked(state);
+ }
+ checkStateChanged();
+ }
+
+ private void doCheckStateChanged(CheckStateChangedEvent e) {
+ if (e.getChecked()) {
+ fCheckElements.add(e.getElement());
+ } else {
+ fCheckElements.remove(e.getElement());
+ }
+ checkStateChanged();
+ }
+
+ // ------ enable / disable management
+
+ /*
+ * @see ListDialogField#getManagedButtonState
+ */
+ protected boolean getManagedButtonState(ISelection sel, int index) {
+ if (index == fCheckAllButtonIndex) {
+ return !fElements.isEmpty();
+ } else if (index == fUncheckAllButtonIndex) {
+ return !fElements.isEmpty();
+ }
+ return super.getManagedButtonState(sel, index);
+ }
+
+ /*
+ * @see ListDialogField#extraButtonPressed
+ */
+ protected boolean managedButtonPressed(int index) {
+ if (index == fCheckAllButtonIndex) {
+ checkAll(true);
+ } else if (index == fUncheckAllButtonIndex) {
+ checkAll(false);
+ } else {
+ return super.managedButtonPressed(index);
+ }
+ return true;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ComboDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ComboDialogField.java
new file mode 100644
index 0000000..777e4bf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ComboDialogField.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+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.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Dialog field containing a label and a combo control.
+ */
+public class ComboDialogField extends DialogField {
+
+ private String fText;
+
+ private int fSelectionIndex;
+
+ private String[] fItems;
+
+ private Combo fComboControl;
+
+ private ModifyListener fModifyListener;
+
+ private int fFlags;
+
+ public ComboDialogField(int flags) {
+ super();
+ fText = ""; //$NON-NLS-1$
+ fItems = new String[0];
+ fFlags = flags;
+ fSelectionIndex = -1;
+ }
+
+ // ------- layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ assertEnoughColumns(nColumns);
+
+ Label label = getLabelControl(parent);
+ label.setLayoutData(gridDataForLabel(1));
+ Combo combo = getComboControl(parent);
+ combo.setLayoutData(gridDataForCombo(nColumns - 1));
+
+ return new Control[] { label, combo };
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 2;
+ }
+
+ protected static GridData gridDataForCombo(int span) {
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = false;
+ gd.horizontalSpan = span;
+ return gd;
+ }
+
+ // ------- focus methods
+
+ /*
+ * @see DialogField#setFocus
+ */
+ public boolean setFocus() {
+ if (isOkToUse(fComboControl)) {
+ fComboControl.setFocus();
+ }
+ return true;
+ }
+
+ // ------- ui creation
+
+ /**
+ * Creates or returns the created combo control.
+ *
+ * @param parent
+ * The parent composite or null
when the widget
+ * has already been created.
+ */
+ public Combo getComboControl(Composite parent) {
+ if (fComboControl == null) {
+ assertCompositeNotNull(parent);
+ fModifyListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ doModifyText(e);
+ }
+ };
+ SelectionListener selectionListener = new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ doSelectionChanged(e);
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ };
+ };
+
+ fComboControl = new Combo(parent, fFlags);
+ // moved up due to 1GEUNW2
+ fComboControl.setItems(fItems);
+ if (fSelectionIndex != -1) {
+ fComboControl.select(fSelectionIndex);
+ } else {
+ fComboControl.setText(fText);
+ }
+ fComboControl.setFont(parent.getFont());
+ fComboControl.addModifyListener(fModifyListener);
+ fComboControl.addSelectionListener(selectionListener);
+ fComboControl.setEnabled(isEnabled());
+ }
+ return fComboControl;
+ }
+
+ private void doModifyText(ModifyEvent e) {
+ if (isOkToUse(fComboControl)) {
+ fText = fComboControl.getText();
+ fSelectionIndex = fComboControl.getSelectionIndex();
+ }
+ dialogFieldChanged();
+ }
+
+ private void doSelectionChanged(SelectionEvent e) {
+ if (isOkToUse(fComboControl)) {
+ fItems = fComboControl.getItems();
+ fText = fComboControl.getText();
+ fSelectionIndex = fComboControl.getSelectionIndex();
+ }
+ dialogFieldChanged();
+ }
+
+ // ------ enable / disable management
+
+ /*
+ * @see DialogField#updateEnableState
+ */
+ protected void updateEnableState() {
+ super.updateEnableState();
+ if (isOkToUse(fComboControl)) {
+ fComboControl.setEnabled(isEnabled());
+ }
+ }
+
+ // ------ text access
+
+ /**
+ * Gets the combo items.
+ */
+ public String[] getItems() {
+ return fItems;
+ }
+
+ /**
+ * Sets the combo items. Triggers a dialog-changed event.
+ */
+ public void setItems(String[] items) {
+ fItems = items;
+ if (isOkToUse(fComboControl)) {
+ fComboControl.setItems(items);
+ }
+ dialogFieldChanged();
+ }
+
+ /**
+ * Gets the text.
+ */
+ public String getText() {
+ return fText;
+ }
+
+ /**
+ * Sets the text. Triggers a dialog-changed event.
+ */
+ public void setText(String text) {
+ fText = text;
+ if (isOkToUse(fComboControl)) {
+ fComboControl.setText(text);
+ } else {
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Selects an item.
+ */
+ public void selectItem(int index) {
+ if (isOkToUse(fComboControl)) {
+ fComboControl.select(index);
+ } else {
+ if (index >= 0 && index < fItems.length) {
+ fText = fItems[index];
+ fSelectionIndex = index;
+ }
+ }
+ dialogFieldChanged();
+ }
+
+ public int getSelectionIndex() {
+ return fSelectionIndex;
+ }
+
+ /**
+ * Sets the text without triggering a dialog-changed event.
+ */
+ public void setTextWithoutUpdate(String text) {
+ fText = text;
+ if (isOkToUse(fComboControl)) {
+ fComboControl.removeModifyListener(fModifyListener);
+ fComboControl.setText(text);
+ fComboControl.addModifyListener(fModifyListener);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/DialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/DialogField.java
new file mode 100644
index 0000000..b624ec5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/DialogField.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Base class of all dialog fields. Dialog fields manage controls together with
+ * the model, independed from the creation time of the widgets. - support for
+ * automated layouting. - enable / disable, set focus a concept of the base
+ * class.
+ *
+ * DialogField have a label.
+ */
+public class DialogField {
+
+ private Label fLabel;
+
+ protected String fLabelText;
+
+ private IDialogFieldListener fDialogFieldListener;
+
+ private boolean fEnabled;
+
+ public DialogField() {
+ fEnabled = true;
+ fLabel = null;
+ fLabelText = ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the label of the dialog field.
+ */
+ public void setLabelText(String labeltext) {
+ fLabelText = labeltext;
+ }
+
+ // ------ change listener
+
+ /**
+ * Defines the listener for this dialog field.
+ */
+ public final void setDialogFieldListener(IDialogFieldListener listener) {
+ fDialogFieldListener = listener;
+ }
+
+ /**
+ * Programatical invocation of a dialog field change.
+ */
+ public void dialogFieldChanged() {
+ if (fDialogFieldListener != null) {
+ fDialogFieldListener.dialogFieldChanged(this);
+ }
+ }
+
+ // ------- focus management
+
+ /**
+ * Tries to set the focus to the dialog field. Returns true
+ * if the dialog field can take focus. To be reimplemented by dialog field
+ * implementors.
+ */
+ public boolean setFocus() {
+ return false;
+ }
+
+ /**
+ * Posts setFocus
to the display event queue.
+ */
+ public void postSetFocusOnDialogField(Display display) {
+ if (display != null) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ setFocus();
+ }
+ });
+ }
+ }
+
+ // ------- layout helpers
+
+ /**
+ * Creates all controls of the dialog field and fills it to a composite. The
+ * composite is assumed to have MGridLayout
as layout. The
+ * dialog field will adjust its controls' spans to the number of columns
+ * given. To be reimplemented by dialog field implementors.
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ assertEnoughColumns(nColumns);
+
+ Label label = getLabelControl(parent);
+ label.setLayoutData(gridDataForLabel(nColumns));
+
+ return new Control[] { label };
+ }
+
+ /**
+ * Returns the number of columns of the dialog field. To be reimplemented by
+ * dialog field implementors.
+ */
+ public int getNumberOfControls() {
+ return 1;
+ }
+
+ protected static GridData gridDataForLabel(int span) {
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = span;
+ return gd;
+ }
+
+ // ------- ui creation
+
+ /**
+ * Creates or returns the created label widget.
+ *
+ * @param parent
+ * The parent composite or null
if the widget has
+ * already been created.
+ */
+ public Label getLabelControl(Composite parent) {
+ if (fLabel == null) {
+ assertCompositeNotNull(parent);
+
+ fLabel = new Label(parent, SWT.LEFT | SWT.WRAP);
+ fLabel.setFont(parent.getFont());
+ fLabel.setEnabled(fEnabled);
+ if (fLabelText != null && !"".equals(fLabelText)) { //$NON-NLS-1$
+ fLabel.setText(fLabelText);
+ } else {
+ // XXX: to avoid a 16 pixel wide empty label - revisit
+ fLabel.setText("."); //$NON-NLS-1$
+ fLabel.setVisible(false);
+ }
+ }
+ return fLabel;
+ }
+
+ /**
+ * Creates a spacer control.
+ *
+ * @param parent
+ * The parent composite
+ */
+ public static Control createEmptySpace(Composite parent) {
+ return createEmptySpace(parent, 1);
+ }
+
+ /**
+ * Creates a spacer control with the given span. The composite is assumed to
+ * have MGridLayout
as layout.
+ *
+ * @param parent
+ * The parent composite
+ */
+ public static Control createEmptySpace(Composite parent, int span) {
+ Label label = new Label(parent, SWT.LEFT);
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.BEGINNING;
+ gd.grabExcessHorizontalSpace = false;
+ gd.horizontalSpan = span;
+ gd.horizontalIndent = 0;
+ gd.widthHint = 0;
+ gd.heightHint = 0;
+ label.setLayoutData(gd);
+ return label;
+ }
+
+ /**
+ * Tests is the control is not null
and not disposed.
+ */
+ protected final boolean isOkToUse(Control control) {
+ return (control != null) && !(control.isDisposed());
+ }
+
+ // --------- enable / disable management
+
+ /**
+ * Sets the enable state of the dialog field.
+ */
+ public final void setEnabled(boolean enabled) {
+ if (enabled != fEnabled) {
+ fEnabled = enabled;
+ updateEnableState();
+ }
+ }
+
+ /**
+ * Called when the enable state changed. To be extended by dialog field
+ * implementors.
+ */
+ protected void updateEnableState() {
+ if (fLabel != null) {
+ fLabel.setEnabled(fEnabled);
+ }
+ }
+
+ /**
+ * Gets the enable state of the dialog field.
+ */
+ public final boolean isEnabled() {
+ return fEnabled;
+ }
+
+ protected final void assertCompositeNotNull(Composite comp) {
+ Assert.isNotNull(comp,
+ "uncreated control requested with composite null"); //$NON-NLS-1$
+ }
+
+ protected final void assertEnoughColumns(int nColumns) {
+ Assert.isTrue(nColumns >= getNumberOfControls(),
+ "given number of columns is too small"); //$NON-NLS-1$
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IDialogFieldListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IDialogFieldListener.java
new file mode 100644
index 0000000..2d497d8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IDialogFieldListener.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+/**
+ * Change listener used by DialogField
+ */
+public interface IDialogFieldListener {
+
+ /**
+ * The dialog field has changed.
+ */
+ void dialogFieldChanged(DialogField field);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IListAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IListAdapter.java
new file mode 100644
index 0000000..825a78c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IListAdapter.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+/**
+ * Change listener used by ListDialogField
and
+ * CheckedListDialogField
+ */
+public interface IListAdapter {
+
+ /**
+ * A button from the button bar has been pressed.
+ */
+ void customButtonPressed(ListDialogField field, int index);
+
+ /**
+ * The selection of the list has changed.
+ */
+ void selectionChanged(ListDialogField field);
+
+ /**
+ * En entry in the list has been double clicked
+ */
+ void doubleClicked(ListDialogField field);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IStringButtonAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IStringButtonAdapter.java
new file mode 100644
index 0000000..7a3f1cf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/IStringButtonAdapter.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+/**
+ * Change listener used by StringButtonDialogField
+ */
+public interface IStringButtonAdapter {
+
+ void changeControlPressed(DialogField field);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ITreeListAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ITreeListAdapter.java
new file mode 100644
index 0000000..d4d186b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ITreeListAdapter.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import org.eclipse.swt.events.KeyEvent;
+
+/**
+ * Change listener used by TreeListDialogField
+ */
+public interface ITreeListAdapter {
+
+ /**
+ * A button from the button bar has been pressed.
+ */
+ void customButtonPressed(TreeListDialogField field, int index);
+
+ /**
+ * The selection of the list has changed.
+ */
+ void selectionChanged(TreeListDialogField field);
+
+ /**
+ * The list has been double clicked
+ */
+ void doubleClicked(TreeListDialogField field);
+
+ /**
+ * A key has been pressed
+ */
+ void keyPressed(TreeListDialogField field, KeyEvent event);
+
+ Object[] getChildren(TreeListDialogField field, Object element);
+
+ Object getParent(TreeListDialogField field, Object element);
+
+ boolean hasChildren(TreeListDialogField field, Object element);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/LayoutUtil.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/LayoutUtil.java
new file mode 100644
index 0000000..baee413
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/LayoutUtil.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+public class LayoutUtil {
+
+ /**
+ * Calculates the number of columns needed by field editors
+ */
+ public static int getNumberOfColumns(DialogField[] editors) {
+ int nCulumns = 0;
+ for (int i = 0; i < editors.length; i++) {
+ nCulumns = Math.max(editors[i].getNumberOfControls(), nCulumns);
+ }
+ return nCulumns;
+ }
+
+ /**
+ * Creates a composite and fills in the given editors.
+ *
+ * @param labelOnTop
+ * Defines if the label of all fields should be on top of the
+ * fields
+ */
+ public static void doDefaultLayout(Composite parent, DialogField[] editors,
+ boolean labelOnTop) {
+ doDefaultLayout(parent, editors, labelOnTop, 0, 0, 0, 0);
+ }
+
+ /**
+ * Creates a composite and fills in the given editors.
+ *
+ * @param labelOnTop
+ * Defines if the label of all fields should be on top of the
+ * fields
+ * @param minWidth
+ * The minimal width of the composite
+ * @param minHeight
+ * The minimal height of the composite
+ */
+ public static void doDefaultLayout(Composite parent, DialogField[] editors,
+ boolean labelOnTop, int minWidth, int minHeight) {
+ doDefaultLayout(parent, editors, labelOnTop, minWidth, minHeight, 0, 0);
+ }
+
+ /**
+ * Creates a composite and fills in the given editors.
+ *
+ * @param labelOnTop
+ * Defines if the label of all fields should be on top of the
+ * fields
+ * @param minWidth
+ * The minimal width of the composite
+ * @param minHeight
+ * The minimal height of the composite
+ * @param marginWidth
+ * The margin width to be used by the composite
+ * @param marginHeight
+ * The margin height to be used by the composite
+ * @deprecated
+ */
+ public static void doDefaultLayout(Composite parent, DialogField[] editors,
+ boolean labelOnTop, int minWidth, int minHeight, int marginWidth,
+ int marginHeight) {
+ int nCulumns = getNumberOfColumns(editors);
+ Control[][] controls = new Control[editors.length][];
+ for (int i = 0; i < editors.length; i++) {
+ controls[i] = editors[i].doFillIntoGrid(parent, nCulumns);
+ }
+ if (labelOnTop) {
+ nCulumns--;
+ modifyLabelSpans(controls, nCulumns);
+ }
+ GridLayout layout = new GridLayout();
+ if (marginWidth != SWT.DEFAULT) {
+ layout.marginWidth = marginWidth;
+ }
+ if (marginHeight != SWT.DEFAULT) {
+ layout.marginHeight = marginHeight;
+ }
+ layout.numColumns = nCulumns;
+ parent.setLayout(layout);
+ }
+
+ private static void modifyLabelSpans(Control[][] controls, int nCulumns) {
+ for (int i = 0; i < controls.length; i++) {
+ setHorizontalSpan(controls[i][0], nCulumns);
+ }
+ }
+
+ /**
+ * Sets the span of a control. Assumes that GridData is used.
+ */
+ public static void setHorizontalSpan(Control control, int span) {
+ Object ld = control.getLayoutData();
+ if (ld instanceof GridData) {
+ ((GridData) ld).horizontalSpan = span;
+ } else if (span != 1) {
+ GridData gd = new GridData();
+ gd.horizontalSpan = span;
+ control.setLayoutData(gd);
+ }
+ }
+
+ /**
+ * Sets the width hint of a control. Assumes that GridData is used.
+ */
+ public static void setWidthHint(Control control, int widthHint) {
+ Object ld = control.getLayoutData();
+ if (ld instanceof GridData) {
+ ((GridData) ld).widthHint = widthHint;
+ }
+ }
+
+ /**
+ * Sets the heigthHint hint of a control. Assumes that GridData is used.
+ */
+ public static void setHeigthHint(Control control, int heigthHint) {
+ Object ld = control.getLayoutData();
+ if (ld instanceof GridData) {
+ ((GridData) ld).heightHint = heigthHint;
+ }
+ }
+
+ /**
+ * Sets the horizontal indent of a control. Assumes that GridData is used.
+ */
+ public static void setHorizontalIndent(Control control, int horizontalIndent) {
+ Object ld = control.getLayoutData();
+ if (ld instanceof GridData) {
+ ((GridData) ld).horizontalIndent = horizontalIndent;
+ }
+ }
+
+ /**
+ * Sets the horizontal indent of a control. Assumes that GridData is used.
+ */
+ public static void setHorizontalGrabbing(Control control) {
+ Object ld = control.getLayoutData();
+ if (ld instanceof GridData) {
+ ((GridData) ld).grabExcessHorizontalSpace = true;
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ListDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ListDialogField.java
new file mode 100644
index 0000000..2c028b0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/ListDialogField.java
@@ -0,0 +1,918 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+import net.sourceforge.phpdt.internal.ui.util.TableLayoutComposite;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ColumnLayoutData;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * A list with a button bar. Typical buttons are 'Add', 'Remove', 'Up' and
+ * 'Down'. List model is independend of widget creation. DialogFields controls
+ * are: Label, List and Composite containing buttons.
+ */
+public class ListDialogField extends DialogField {
+
+ public static class ColumnsDescription {
+ private ColumnLayoutData[] columns;
+
+ private String[] headers;
+
+ private boolean drawLines;
+
+ public ColumnsDescription(ColumnLayoutData[] columns, String[] headers,
+ boolean drawLines) {
+ this.columns = columns;
+ this.headers = headers;
+ this.drawLines = drawLines;
+ }
+
+ public ColumnsDescription(String[] headers, boolean drawLines) {
+ this(createColumnWeightData(headers.length), headers, drawLines);
+ }
+
+ public ColumnsDescription(int nColumns, boolean drawLines) {
+ this(createColumnWeightData(nColumns), null, drawLines);
+ }
+
+ private static ColumnLayoutData[] createColumnWeightData(int nColumns) {
+ ColumnLayoutData[] data = new ColumnLayoutData[nColumns];
+ for (int i = 0; i < nColumns; i++) {
+ data[i] = new ColumnWeightData(1);
+ }
+ return data;
+ }
+ }
+
+ protected TableViewer fTable;
+
+ protected ILabelProvider fLabelProvider;
+
+ protected ListViewerAdapter fListViewerAdapter;
+
+ protected List fElements;
+
+ protected ViewerSorter fViewerSorter;
+
+ protected String[] fButtonLabels;
+
+ private Button[] fButtonControls;
+
+ private boolean[] fButtonsEnabled;
+
+ private int fRemoveButtonIndex;
+
+ private int fUpButtonIndex;
+
+ private int fDownButtonIndex;
+
+ private Label fLastSeparator;
+
+ private Control fTableControl;
+
+ private Composite fButtonsControl;
+
+ private ISelection fSelectionWhenEnabled;
+
+ private IListAdapter fListAdapter;
+
+ private Object fParentElement;
+
+ private ColumnsDescription fTableColumns;
+
+ /**
+ * Creates the ListDialogField
.
+ *
+ * @param adapter
+ * A listener for button invocation, selection changes. Can be
+ * null
.
+ * @param buttonLabels
+ * The labels of all buttons: null
is a valid
+ * array entry and marks a separator.
+ * @param lprovider
+ * The label provider to render the table entries
+ */
+ public ListDialogField(IListAdapter adapter, String[] buttonLabels,
+ ILabelProvider lprovider) {
+ super();
+ fListAdapter = adapter;
+
+ fLabelProvider = lprovider;
+ fListViewerAdapter = new ListViewerAdapter();
+ fParentElement = this;
+
+ fElements = new ArrayList(10);
+
+ fButtonLabels = buttonLabels;
+ if (fButtonLabels != null) {
+ int nButtons = fButtonLabels.length;
+ fButtonsEnabled = new boolean[nButtons];
+ for (int i = 0; i < nButtons; i++) {
+ fButtonsEnabled[i] = true;
+ }
+ }
+
+ fTable = null;
+ fTableControl = null;
+ fButtonsControl = null;
+ fTableColumns = null;
+
+ fRemoveButtonIndex = -1;
+ fUpButtonIndex = -1;
+ fDownButtonIndex = -1;
+ }
+
+ /**
+ * Sets the index of the 'remove' button in the button label array passed in
+ * the constructor. The behaviour of the button marked as the 'remove'
+ * button will then be handled internally. (enable state, button invocation
+ * behaviour)
+ */
+ public void setRemoveButtonIndex(int removeButtonIndex) {
+ Assert.isTrue(removeButtonIndex < fButtonLabels.length);
+ fRemoveButtonIndex = removeButtonIndex;
+ }
+
+ /**
+ * Sets the index of the 'up' button in the button label array passed in the
+ * constructor. The behaviour of the button marked as the 'up' button will
+ * then be handled internally. (enable state, button invocation behaviour)
+ */
+ public void setUpButtonIndex(int upButtonIndex) {
+ Assert.isTrue(upButtonIndex < fButtonLabels.length);
+ fUpButtonIndex = upButtonIndex;
+ }
+
+ /**
+ * Sets the index of the 'down' button in the button label array passed in
+ * the constructor. The behaviour of the button marked as the 'down' button
+ * will then be handled internally. (enable state, button invocation
+ * behaviour)
+ */
+ public void setDownButtonIndex(int downButtonIndex) {
+ Assert.isTrue(downButtonIndex < fButtonLabels.length);
+ fDownButtonIndex = downButtonIndex;
+ }
+
+ /**
+ * Sets the viewerSorter.
+ *
+ * @param viewerSorter
+ * The viewerSorter to set
+ */
+ public void setViewerSorter(ViewerSorter viewerSorter) {
+ fViewerSorter = viewerSorter;
+ }
+
+ public void setTableColumns(ColumnsDescription column) {
+ fTableColumns = column;
+ }
+
+ // ------ adapter communication
+
+ private void buttonPressed(int index) {
+ if (!managedButtonPressed(index) && fListAdapter != null) {
+ fListAdapter.customButtonPressed(this, index);
+ }
+ }
+
+ /**
+ * Checks if the button pressed is handled internally
+ *
+ * @return Returns true if button has been handled.
+ */
+ protected boolean managedButtonPressed(int index) {
+ if (index == fRemoveButtonIndex) {
+ remove();
+ } else if (index == fUpButtonIndex) {
+ up();
+ } else if (index == fDownButtonIndex) {
+ down();
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ // ------ layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ PixelConverter converter = new PixelConverter(parent);
+
+ assertEnoughColumns(nColumns);
+
+ Label label = getLabelControl(parent);
+ GridData gd = gridDataForLabel(1);
+ gd.verticalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gd);
+
+ Control list = getListControl(parent);
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = false;
+ gd.verticalAlignment = GridData.FILL;
+ gd.grabExcessVerticalSpace = true;
+ gd.horizontalSpan = nColumns - 2;
+ gd.widthHint = converter.convertWidthInCharsToPixels(50);
+ gd.heightHint = converter.convertHeightInCharsToPixels(6);
+
+ list.setLayoutData(gd);
+
+ Composite buttons = getButtonBox(parent);
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = false;
+ gd.verticalAlignment = GridData.FILL;
+ gd.grabExcessVerticalSpace = true;
+ gd.horizontalSpan = 1;
+ buttons.setLayoutData(gd);
+
+ return new Control[] { label, list, buttons };
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 3;
+ }
+
+ /**
+ * Sets the minimal width of the buttons. Must be called after widget
+ * creation.
+ */
+ public void setButtonsMinWidth(int minWidth) {
+ if (fLastSeparator != null) {
+ ((GridData) fLastSeparator.getLayoutData()).widthHint = minWidth;
+ }
+ }
+
+ // ------ ui creation
+
+ /**
+ * Returns the list control. When called the first time, the control will be
+ * created.
+ *
+ * @param The
+ * parent composite when called the first time, or
+ * null
after.
+ */
+ public Control getListControl(Composite parent) {
+ if (fTableControl == null) {
+ assertCompositeNotNull(parent);
+
+ if (fTableColumns == null) {
+ fTable = createTableViewer(parent);
+ Table tableControl = fTable.getTable();
+
+ fTableControl = tableControl;
+ tableControl.setLayout(new TableLayout());
+ } else {
+ TableLayoutComposite composite = new TableLayoutComposite(
+ parent, SWT.NONE);
+ fTableControl = composite;
+
+ fTable = createTableViewer(composite);
+ Table tableControl = fTable.getTable();
+
+ tableControl.setHeaderVisible(fTableColumns.headers != null);
+ tableControl.setLinesVisible(fTableColumns.drawLines);
+ ColumnLayoutData[] columns = fTableColumns.columns;
+ for (int i = 0; i < columns.length; i++) {
+ composite.addColumnData(columns[i]);
+ TableColumn column = new TableColumn(tableControl, SWT.NONE);
+ // tableLayout.addColumnData(columns[i]);
+ if (fTableColumns.headers != null) {
+ column.setText(fTableColumns.headers[i]);
+ }
+ }
+ }
+
+ fTable.getTable().addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ handleKeyPressed(e);
+ }
+ });
+
+ // fTableControl.setLayout(tableLayout);
+
+ fTable.setContentProvider(fListViewerAdapter);
+ fTable.setLabelProvider(fLabelProvider);
+ fTable.addSelectionChangedListener(fListViewerAdapter);
+ fTable.addDoubleClickListener(fListViewerAdapter);
+
+ fTable.setInput(fParentElement);
+
+ if (fViewerSorter != null) {
+ fTable.setSorter(fViewerSorter);
+ }
+
+ fTableControl.setEnabled(isEnabled());
+ if (fSelectionWhenEnabled != null) {
+ postSetSelection(fSelectionWhenEnabled);
+ }
+ }
+ return fTableControl;
+ }
+
+ /**
+ * Returns the internally used table viewer.
+ */
+ public TableViewer getTableViewer() {
+ return fTable;
+ }
+
+ /*
+ * Subclasses may override to specify a different style.
+ */
+ protected int getListStyle() {
+ int style = SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
+ if (fTableColumns != null) {
+ style |= SWT.FULL_SELECTION;
+ }
+ return style;
+ }
+
+ protected TableViewer createTableViewer(Composite parent) {
+ Table table = new Table(parent, getListStyle());
+ return new TableViewer(table);
+ }
+
+ protected Button createButton(Composite parent, String label,
+ SelectionListener listener) {
+ Button button = new Button(parent, SWT.PUSH);
+ button.setText(label);
+ button.addSelectionListener(listener);
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = true;
+ gd.verticalAlignment = GridData.BEGINNING;
+ gd.heightHint = SWTUtil.getButtonHeightHint(button);
+ gd.widthHint = SWTUtil.getButtonWidthHint(button);
+
+ button.setLayoutData(gd);
+ return button;
+ }
+
+ private Label createSeparator(Composite parent) {
+ Label separator = new Label(parent, SWT.NONE);
+ separator.setVisible(false);
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.verticalAlignment = GridData.BEGINNING;
+ gd.heightHint = 4;
+ separator.setLayoutData(gd);
+ return separator;
+ }
+
+ /**
+ * Returns the composite containing the buttons. When called the first time,
+ * the control will be created.
+ *
+ * @param The
+ * parent composite when called the first time, or
+ * null
after.
+ */
+ public Composite getButtonBox(Composite parent) {
+ if (fButtonsControl == null) {
+ assertCompositeNotNull(parent);
+
+ SelectionListener listener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ doButtonSelected(e);
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ doButtonSelected(e);
+ }
+ };
+
+ Composite contents = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ contents.setLayout(layout);
+
+ if (fButtonLabels != null) {
+ fButtonControls = new Button[fButtonLabels.length];
+ for (int i = 0; i < fButtonLabels.length; i++) {
+ String currLabel = fButtonLabels[i];
+ if (currLabel != null) {
+ fButtonControls[i] = createButton(contents, currLabel,
+ listener);
+ fButtonControls[i].setEnabled(isEnabled()
+ && fButtonsEnabled[i]);
+ } else {
+ fButtonControls[i] = null;
+ createSeparator(contents);
+ }
+ }
+ }
+
+ fLastSeparator = createSeparator(contents);
+
+ updateButtonState();
+ fButtonsControl = contents;
+ }
+
+ return fButtonsControl;
+ }
+
+ private void doButtonSelected(SelectionEvent e) {
+ if (fButtonControls != null) {
+ for (int i = 0; i < fButtonControls.length; i++) {
+ if (e.widget == fButtonControls[i]) {
+ buttonPressed(i);
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Handles key events in the table viewer. Specifically when the delete key
+ * is pressed.
+ */
+ protected void handleKeyPressed(KeyEvent event) {
+ if (event.character == SWT.DEL && event.stateMask == 0) {
+ if (fRemoveButtonIndex != -1
+ && isButtonEnabled(fTable.getSelection(),
+ fRemoveButtonIndex)) {
+ managedButtonPressed(fRemoveButtonIndex);
+ }
+ }
+ }
+
+ // ------ enable / disable management
+
+ /*
+ * @see DialogField#dialogFieldChanged
+ */
+ public void dialogFieldChanged() {
+ super.dialogFieldChanged();
+ updateButtonState();
+ }
+
+ /*
+ * Updates the enable state of the all buttons
+ */
+ protected void updateButtonState() {
+ if (fButtonControls != null) {
+ ISelection sel = fTable.getSelection();
+ for (int i = 0; i < fButtonControls.length; i++) {
+ Button button = fButtonControls[i];
+ if (isOkToUse(button)) {
+ button.setEnabled(isButtonEnabled(sel, i));
+ }
+ }
+ }
+ }
+
+ protected boolean getManagedButtonState(ISelection sel, int index) {
+ if (index == fRemoveButtonIndex) {
+ return !sel.isEmpty();
+ } else if (index == fUpButtonIndex) {
+ return !sel.isEmpty() && canMoveUp();
+ } else if (index == fDownButtonIndex) {
+ return !sel.isEmpty() && canMoveDown();
+ }
+ return true;
+ }
+
+ /*
+ * @see DialogField#updateEnableState
+ */
+ protected void updateEnableState() {
+ super.updateEnableState();
+
+ boolean enabled = isEnabled();
+ if (isOkToUse(fTableControl)) {
+ if (!enabled) {
+ fSelectionWhenEnabled = fTable.getSelection();
+ selectElements(null);
+ } else {
+ selectElements(fSelectionWhenEnabled);
+ fSelectionWhenEnabled = null;
+ }
+ fTableControl.setEnabled(enabled);
+ }
+ updateButtonState();
+ }
+
+ /**
+ * Sets a button enabled or disabled.
+ */
+ public void enableButton(int index, boolean enable) {
+ if (fButtonsEnabled != null && index < fButtonsEnabled.length) {
+ fButtonsEnabled[index] = enable;
+ updateButtonState();
+ }
+ }
+
+ private boolean isButtonEnabled(ISelection sel, int index) {
+ boolean extraState = getManagedButtonState(sel, index);
+ return isEnabled() && extraState && fButtonsEnabled[index];
+ }
+
+ // ------ model access
+
+ /**
+ * Sets the elements shown in the list.
+ */
+ public void setElements(List elements) {
+ fElements = new ArrayList(elements);
+ if (fTable != null) {
+ fTable.refresh();
+ }
+ dialogFieldChanged();
+ }
+
+ /**
+ * Gets the elements shown in the list. The list returned is a copy, so it
+ * can be modified by the user.
+ */
+ public List getElements() {
+ return new ArrayList(fElements);
+ }
+
+ /**
+ * Gets the elements shown at the given index.
+ */
+ public Object getElement(int index) {
+ return fElements.get(index);
+ }
+
+ /**
+ * Gets the index of an element in the list or -1 if element is not in list.
+ */
+ public int getIndexOfElement(Object elem) {
+ return fElements.indexOf(elem);
+ }
+
+ /**
+ * Replace an element.
+ */
+ public void replaceElement(Object oldElement, Object newElement)
+ throws IllegalArgumentException {
+ int idx = fElements.indexOf(oldElement);
+ if (idx != -1) {
+ fElements.set(idx, newElement);
+ if (fTable != null) {
+ List selected = getSelectedElements();
+ if (selected.remove(oldElement)) {
+ selected.add(newElement);
+ }
+ fTable.refresh();
+ selectElements(new StructuredSelection(selected));
+ }
+ dialogFieldChanged();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Adds an element at the end of the list.
+ */
+ public void addElement(Object element) {
+ if (fElements.contains(element)) {
+ return;
+ }
+ fElements.add(element);
+ if (fTable != null) {
+ fTable.add(element);
+ }
+ dialogFieldChanged();
+ }
+
+ /**
+ * Adds elements at the end of the list.
+ */
+ public void addElements(List elements) {
+ int nElements = elements.size();
+
+ if (nElements > 0) {
+ // filter duplicated
+ ArrayList elementsToAdd = new ArrayList(nElements);
+
+ for (int i = 0; i < nElements; i++) {
+ Object elem = elements.get(i);
+ if (!fElements.contains(elem)) {
+ elementsToAdd.add(elem);
+ }
+ }
+ fElements.addAll(elementsToAdd);
+ if (fTable != null) {
+ fTable.add(elementsToAdd.toArray());
+ }
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Adds an element at a position.
+ */
+ public void insertElementAt(Object element, int index) {
+ if (fElements.contains(element)) {
+ return;
+ }
+ fElements.add(index, element);
+ if (fTable != null) {
+ fTable.add(element);
+ }
+
+ dialogFieldChanged();
+ }
+
+ /**
+ * Adds an element at a position.
+ */
+ public void removeAllElements() {
+ if (fElements.size() > 0) {
+ fElements.clear();
+ if (fTable != null) {
+ fTable.refresh();
+ }
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Removes an element from the list.
+ */
+ public void removeElement(Object element) throws IllegalArgumentException {
+ if (fElements.remove(element)) {
+ if (fTable != null) {
+ fTable.remove(element);
+ }
+ dialogFieldChanged();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Removes elements from the list.
+ */
+ public void removeElements(List elements) {
+ if (elements.size() > 0) {
+ fElements.removeAll(elements);
+ if (fTable != null) {
+ fTable.remove(elements.toArray());
+ }
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Gets the number of elements
+ */
+ public int getSize() {
+ return fElements.size();
+ }
+
+ public void selectElements(ISelection selection) {
+ fSelectionWhenEnabled = selection;
+ if (fTable != null) {
+ fTable.setSelection(selection, true);
+ }
+ }
+
+ public void selectFirstElement() {
+ Object element = null;
+ if (fViewerSorter != null) {
+ Object[] arr = fElements.toArray();
+ fViewerSorter.sort(fTable, arr);
+ if (arr.length > 0) {
+ element = arr[0];
+ }
+ } else {
+ if (fElements.size() > 0) {
+ element = fElements.get(0);
+ }
+ }
+ if (element != null) {
+ selectElements(new StructuredSelection(element));
+ }
+ }
+
+ public void postSetSelection(final ISelection selection) {
+ if (isOkToUse(fTableControl)) {
+ Display d = fTableControl.getDisplay();
+ d.asyncExec(new Runnable() {
+ public void run() {
+ if (isOkToUse(fTableControl)) {
+ selectElements(selection);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Refreshes the table.
+ */
+ public void refresh() {
+ if (fTable != null) {
+ fTable.refresh();
+ }
+ }
+
+ // ------- list maintenance
+
+ private List moveUp(List elements, List move) {
+ int nElements = elements.size();
+ List res = new ArrayList(nElements);
+ Object floating = null;
+ for (int i = 0; i < nElements; i++) {
+ Object curr = elements.get(i);
+ if (move.contains(curr)) {
+ res.add(curr);
+ } else {
+ if (floating != null) {
+ res.add(floating);
+ }
+ floating = curr;
+ }
+ }
+ if (floating != null) {
+ res.add(floating);
+ }
+ return res;
+ }
+
+ private void moveUp(List toMoveUp) {
+ if (toMoveUp.size() > 0) {
+ setElements(moveUp(fElements, toMoveUp));
+ fTable.reveal(toMoveUp.get(0));
+ }
+ }
+
+ private void moveDown(List toMoveDown) {
+ if (toMoveDown.size() > 0) {
+ setElements(reverse(moveUp(reverse(fElements), toMoveDown)));
+ fTable.reveal(toMoveDown.get(toMoveDown.size() - 1));
+ }
+ }
+
+ private List reverse(List p) {
+ List reverse = new ArrayList(p.size());
+ for (int i = p.size() - 1; i >= 0; i--) {
+ reverse.add(p.get(i));
+ }
+ return reverse;
+ }
+
+ private void remove() {
+ removeElements(getSelectedElements());
+ }
+
+ private void up() {
+ moveUp(getSelectedElements());
+ }
+
+ private void down() {
+ moveDown(getSelectedElements());
+ }
+
+ private boolean canMoveUp() {
+ if (isOkToUse(fTableControl)) {
+ int[] indc = fTable.getTable().getSelectionIndices();
+ for (int i = 0; i < indc.length; i++) {
+ if (indc[i] != i) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean canMoveDown() {
+ if (isOkToUse(fTableControl)) {
+ int[] indc = fTable.getTable().getSelectionIndices();
+ int k = fElements.size() - 1;
+ for (int i = indc.length - 1; i >= 0; i--, k--) {
+ if (indc[i] != k) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the selected elements.
+ */
+ public List getSelectedElements() {
+ List result = new ArrayList();
+ if (fTable != null) {
+ ISelection selection = fTable.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ Iterator iter = ((IStructuredSelection) selection).iterator();
+ while (iter.hasNext()) {
+ result.add(iter.next());
+ }
+ }
+ }
+ return result;
+ }
+
+ // ------- ListViewerAdapter
+
+ private class ListViewerAdapter implements IStructuredContentProvider,
+ ISelectionChangedListener, IDoubleClickListener {
+
+ // ------- ITableContentProvider Interface ------------
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // will never happen
+ }
+
+ public boolean isDeleted(Object element) {
+ return false;
+ }
+
+ public void dispose() {
+ }
+
+ public Object[] getElements(Object obj) {
+ return fElements.toArray();
+ }
+
+ // ------- ISelectionChangedListener Interface ------------
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ doListSelected(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent)
+ */
+ public void doubleClick(DoubleClickEvent event) {
+ doDoubleClick(event);
+ }
+
+ }
+
+ protected void doListSelected(SelectionChangedEvent event) {
+ updateButtonState();
+ if (fListAdapter != null) {
+ fListAdapter.selectionChanged(this);
+ }
+ }
+
+ protected void doDoubleClick(DoubleClickEvent event) {
+ if (fListAdapter != null) {
+ fListAdapter.doubleClicked(this);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/SelectionButtonDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/SelectionButtonDialogField.java
new file mode 100644
index 0000000..57b9cd2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/SelectionButtonDialogField.java
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+
+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.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Dialog Field containing a single button such as a radio or checkbox button.
+ */
+public class SelectionButtonDialogField extends DialogField {
+
+ private Button fButton;
+
+ private boolean fIsSelected;
+
+ private DialogField[] fAttachedDialogFields;
+
+ private int fButtonStyle;
+
+ /**
+ * Creates a selection button. Allowed button styles: SWT.RADIO, SWT.CHECK,
+ * SWT.TOGGLE, SWT.PUSH
+ */
+ public SelectionButtonDialogField(int buttonStyle) {
+ super();
+ fIsSelected = false;
+ fAttachedDialogFields = null;
+ fButtonStyle = buttonStyle;
+ }
+
+ /**
+ * Attaches a field to the selection state of the selection button. The
+ * attached field will be disabled if the selection button is not selected.
+ */
+ public void attachDialogField(DialogField dialogField) {
+ attachDialogFields(new DialogField[] { dialogField });
+ }
+
+ /**
+ * Attaches fields to the selection state of the selection button. The
+ * attached fields will be disabled if the selection button is not selected.
+ */
+ public void attachDialogFields(DialogField[] dialogFields) {
+ fAttachedDialogFields = dialogFields;
+ for (int i = 0; i < dialogFields.length; i++) {
+ dialogFields[i].setEnabled(fIsSelected);
+ }
+ }
+
+ /**
+ * Returns true
is teh gived field is attached to the
+ * selection button.
+ */
+ public boolean isAttached(DialogField editor) {
+ if (fAttachedDialogFields != null) {
+ for (int i = 0; i < fAttachedDialogFields.length; i++) {
+ if (fAttachedDialogFields[i] == editor) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // ------- layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ assertEnoughColumns(nColumns);
+
+ Button button = getSelectionButton(parent);
+ GridData gd = new GridData();
+ gd.horizontalSpan = nColumns;
+ gd.horizontalAlignment = GridData.FILL;
+ if (fButtonStyle == SWT.PUSH) {
+ gd.heightHint = SWTUtil.getButtonHeightHint(button);
+ gd.widthHint = SWTUtil.getButtonWidthHint(button);
+ }
+
+ button.setLayoutData(gd);
+
+ return new Control[] { button };
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 1;
+ }
+
+ // ------- ui creation
+
+ /**
+ * Returns the selection button widget. When called the first time, the
+ * widget will be created.
+ *
+ * @param The
+ * parent composite when called the first time, or
+ * null
after.
+ */
+ public Button getSelectionButton(Composite group) {
+ if (fButton == null) {
+ assertCompositeNotNull(group);
+
+ fButton = new Button(group, fButtonStyle);
+ fButton.setFont(group.getFont());
+ fButton.setText(fLabelText);
+ fButton.setEnabled(isEnabled());
+ fButton.setSelection(fIsSelected);
+ fButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ doWidgetSelected(e);
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ doWidgetSelected(e);
+ }
+ });
+ }
+ return fButton;
+ }
+
+ private void doWidgetSelected(SelectionEvent e) {
+ if (isOkToUse(fButton)) {
+ changeValue(fButton.getSelection());
+ }
+ }
+
+ private void changeValue(boolean newState) {
+ if (fIsSelected != newState) {
+ fIsSelected = newState;
+ if (fAttachedDialogFields != null) {
+ boolean focusSet = false;
+ for (int i = 0; i < fAttachedDialogFields.length; i++) {
+ fAttachedDialogFields[i].setEnabled(fIsSelected);
+ if (fIsSelected && !focusSet) {
+ focusSet = fAttachedDialogFields[i].setFocus();
+ }
+ }
+ }
+ dialogFieldChanged();
+ } else if (fButtonStyle == SWT.PUSH) {
+ dialogFieldChanged();
+ }
+ }
+
+ // ------ model access
+
+ /**
+ * Returns the selection state of the button.
+ */
+ public boolean isSelected() {
+ return fIsSelected;
+ }
+
+ /**
+ * Sets the selection state of the button.
+ */
+ public void setSelection(boolean selected) {
+ changeValue(selected);
+ if (isOkToUse(fButton)) {
+ fButton.setSelection(selected);
+ }
+ }
+
+ // ------ enable / disable management
+
+ /*
+ * @see DialogField#updateEnableState
+ */
+ protected void updateEnableState() {
+ super.updateEnableState();
+ if (isOkToUse(fButton)) {
+ fButton.setEnabled(isEnabled());
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/SelectionButtonDialogFieldGroup.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/SelectionButtonDialogFieldGroup.java
new file mode 100644
index 0000000..2655aa8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/SelectionButtonDialogFieldGroup.java
@@ -0,0 +1,271 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import org.eclipse.jface.util.Assert;
+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.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Dialog field describing a group with buttons (Checkboxes, radio buttons..)
+ */
+public class SelectionButtonDialogFieldGroup extends DialogField {
+
+ private Composite fButtonComposite;
+
+ private Button[] fButtons;
+
+ private String[] fButtonNames;
+
+ private boolean[] fButtonsSelected;
+
+ private boolean[] fButtonsEnabled;
+
+ private int fGroupBorderStyle;
+
+ private int fGroupNumberOfColumns;
+
+ private int fButtonsStyle;
+
+ /**
+ * Creates a group without border.
+ */
+ public SelectionButtonDialogFieldGroup(int buttonsStyle,
+ String[] buttonNames, int nColumns) {
+ this(buttonsStyle, buttonNames, nColumns, SWT.NONE);
+ }
+
+ /**
+ * Creates a group with border (label in border). Accepted button styles
+ * are: SWT.RADIO, SWT.CHECK, SWT.TOGGLE For border styles see
+ * Group
+ */
+ public SelectionButtonDialogFieldGroup(int buttonsStyle,
+ String[] buttonNames, int nColumns, int borderStyle) {
+ super();
+
+ Assert.isTrue(buttonsStyle == SWT.RADIO || buttonsStyle == SWT.CHECK
+ || buttonsStyle == SWT.TOGGLE);
+ fButtonNames = buttonNames;
+
+ int nButtons = buttonNames.length;
+ fButtonsSelected = new boolean[nButtons];
+ fButtonsEnabled = new boolean[nButtons];
+ for (int i = 0; i < nButtons; i++) {
+ fButtonsSelected[i] = false;
+ fButtonsEnabled[i] = true;
+ }
+ if (fButtonsStyle == SWT.RADIO) {
+ fButtonsSelected[0] = true;
+ }
+
+ fGroupBorderStyle = borderStyle;
+ fGroupNumberOfColumns = (nColumns <= 0) ? nButtons : nColumns;
+
+ fButtonsStyle = buttonsStyle;
+
+ }
+
+ // ------- layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ assertEnoughColumns(nColumns);
+
+ if (fGroupBorderStyle == SWT.NONE) {
+ Label label = getLabelControl(parent);
+ label.setLayoutData(gridDataForLabel(1));
+
+ Composite buttonsgroup = getSelectionButtonsGroup(parent);
+ GridData gd = new GridData();
+ gd.horizontalSpan = nColumns - 1;
+ buttonsgroup.setLayoutData(gd);
+
+ return new Control[] { label, buttonsgroup };
+ } else {
+ Composite buttonsgroup = getSelectionButtonsGroup(parent);
+ GridData gd = new GridData();
+ gd.horizontalSpan = nColumns;
+ buttonsgroup.setLayoutData(gd);
+
+ return new Control[] { buttonsgroup };
+ }
+ }
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public int getNumberOfControls() {
+ return (fGroupBorderStyle == SWT.NONE) ? 2 : 1;
+ }
+
+ // ------- ui creation
+
+ private Button createSelectionButton(int index, Composite group,
+ SelectionListener listener) {
+ Button button = new Button(group, fButtonsStyle | SWT.LEFT);
+ button.setFont(group.getFont());
+ button.setText(fButtonNames[index]);
+ button.setEnabled(isEnabled() && fButtonsEnabled[index]);
+ button.setSelection(fButtonsSelected[index]);
+ button.addSelectionListener(listener);
+ button.setLayoutData(new GridData());
+ return button;
+ }
+
+ /**
+ * Returns the group widget. When called the first time, the widget will be
+ * created.
+ *
+ * @param The
+ * parent composite when called the first time, or
+ * null
after.
+ */
+ public Composite getSelectionButtonsGroup(Composite parent) {
+ if (fButtonComposite == null) {
+ assertCompositeNotNull(parent);
+
+ GridLayout layout = new GridLayout();
+ layout.makeColumnsEqualWidth = true;
+ layout.numColumns = fGroupNumberOfColumns;
+
+ if (fGroupBorderStyle != SWT.NONE) {
+ Group group = new Group(parent, fGroupBorderStyle);
+ if (fLabelText != null && fLabelText.length() > 0) {
+ group.setText(fLabelText);
+ }
+ fButtonComposite = group;
+ } else {
+ fButtonComposite = new Composite(parent, SWT.NULL);
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ }
+
+ fButtonComposite.setLayout(layout);
+
+ SelectionListener listener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ doWidgetSelected(e);
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ doWidgetSelected(e);
+ }
+ };
+ int nButtons = fButtonNames.length;
+ fButtons = new Button[nButtons];
+ for (int i = 0; i < nButtons; i++) {
+ fButtons[i] = createSelectionButton(i, fButtonComposite,
+ listener);
+ }
+ int nRows = nButtons / fGroupNumberOfColumns;
+ int nFillElements = nRows * fGroupNumberOfColumns - nButtons;
+ for (int i = 0; i < nFillElements; i++) {
+ createEmptySpace(fButtonComposite);
+ }
+ }
+ return fButtonComposite;
+ }
+
+ /**
+ * Returns a button from the group or null
if not yet
+ * created.
+ */
+ public Button getSelectionButton(int index) {
+ if (index >= 0 && index < fButtons.length) {
+ return fButtons[index];
+ }
+ return null;
+ }
+
+ private void doWidgetSelected(SelectionEvent e) {
+ Button button = (Button) e.widget;
+ for (int i = 0; i < fButtons.length; i++) {
+ if (fButtons[i] == button) {
+ fButtonsSelected[i] = button.getSelection();
+ dialogFieldChanged();
+ return;
+ }
+ }
+ }
+
+ // ------ model access
+
+ /**
+ * Returns the selection state of a button contained in the group.
+ *
+ * @param The
+ * index of the button
+ */
+ public boolean isSelected(int index) {
+ if (index >= 0 && index < fButtonsSelected.length) {
+ return fButtonsSelected[index];
+ }
+ return false;
+ }
+
+ /**
+ * Sets the selection state of a button contained in the group.
+ */
+ public void setSelection(int index, boolean selected) {
+ if (index >= 0 && index < fButtonsSelected.length) {
+ if (fButtonsSelected[index] != selected) {
+ fButtonsSelected[index] = selected;
+ if (fButtons != null) {
+ Button button = fButtons[index];
+ if (isOkToUse(button)) {
+ button.setSelection(selected);
+ }
+ }
+ }
+ }
+ }
+
+ // ------ enable / disable management
+
+ protected void updateEnableState() {
+ super.updateEnableState();
+ if (fButtons != null) {
+ boolean enabled = isEnabled();
+ for (int i = 0; i < fButtons.length; i++) {
+ Button button = fButtons[i];
+ if (isOkToUse(button)) {
+ button.setEnabled(enabled && fButtonsEnabled[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the enable state of a button contained in the group.
+ */
+ public void enableSelectionButton(int index, boolean enable) {
+ if (index >= 0 && index < fButtonsEnabled.length) {
+ fButtonsEnabled[index] = enable;
+ if (fButtons != null) {
+ Button button = fButtons[index];
+ if (isOkToUse(button)) {
+ button.setEnabled(isEnabled() && enable);
+ }
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/Separator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/Separator.java
new file mode 100644
index 0000000..ea736b9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/Separator.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Dialog field describing a separator.
+ */
+public class Separator extends DialogField {
+
+ private Label fSeparator;
+
+ private int fStyle;
+
+ public Separator() {
+ this(SWT.NONE);
+ }
+
+ /**
+ * @param style
+ * of the separator. See Label
for possible
+ * styles.
+ */
+ public Separator(int style) {
+ super();
+ fStyle = style;
+ }
+
+ // ------- layout helpers
+
+ /**
+ * Creates the separator and fills it in a MGridLayout.
+ *
+ * @param height
+ * The heigth of the separator
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns, int height) {
+ assertEnoughColumns(nColumns);
+
+ Control separator = getSeparator(parent);
+ separator.setLayoutData(gridDataForSeperator(nColumns, height));
+
+ return new Control[] { separator };
+ }
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ return doFillIntoGrid(parent, nColumns, 4);
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 1;
+ }
+
+ protected static GridData gridDataForSeperator(int span, int height) {
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.verticalAlignment = GridData.BEGINNING;
+ gd.heightHint = height;
+ gd.horizontalSpan = span;
+ return gd;
+ }
+
+ // ------- ui creation
+
+ /**
+ * Creates or returns the created separator.
+ *
+ * @param parent
+ * The parent composite or null
if the widget has
+ * already been created.
+ */
+ public Control getSeparator(Composite parent) {
+ if (fSeparator == null) {
+ assertCompositeNotNull(parent);
+ fSeparator = new Label(parent, fStyle);
+ }
+ return fSeparator;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringButtonDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringButtonDialogField.java
new file mode 100644
index 0000000..aa06105
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringButtonDialogField.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+
+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.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Dialog field containing a label, text control and a button control.
+ */
+public class StringButtonDialogField extends StringDialogField {
+
+ private Button fBrowseButton;
+
+ private String fBrowseButtonLabel;
+
+ private IStringButtonAdapter fStringButtonAdapter;
+
+ private boolean fButtonEnabled;
+
+ public StringButtonDialogField(IStringButtonAdapter adapter) {
+ super();
+ fStringButtonAdapter = adapter;
+ fBrowseButtonLabel = "!Browse...!"; //$NON-NLS-1$
+ fButtonEnabled = true;
+ }
+
+ /**
+ * Sets the label of the button.
+ */
+ public void setButtonLabel(String label) {
+ fBrowseButtonLabel = label;
+ }
+
+ // ------ adapter communication
+
+ /**
+ * Programmatical pressing of the button
+ */
+ public void changeControlPressed() {
+ fStringButtonAdapter.changeControlPressed(this);
+ }
+
+ // ------- layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ assertEnoughColumns(nColumns);
+
+ Label label = getLabelControl(parent);
+ label.setLayoutData(gridDataForLabel(1));
+ Text text = getTextControl(parent);
+ text.setLayoutData(gridDataForText(nColumns - 2));
+ Button button = getChangeControl(parent);
+ button.setLayoutData(gridDataForButton(button, 1));
+
+ return new Control[] { label, text, button };
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 3;
+ }
+
+ protected static GridData gridDataForButton(Button button, int span) {
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = false;
+ gd.horizontalSpan = span;
+ gd.heightHint = SWTUtil.getButtonHeightHint(button);
+ gd.widthHint = SWTUtil.getButtonWidthHint(button);
+ return gd;
+ }
+
+ // ------- ui creation
+
+ /**
+ * Creates or returns the created buttom widget.
+ *
+ * @param parent
+ * The parent composite or null
if the widget has
+ * already been created.
+ */
+ public Button getChangeControl(Composite parent) {
+ if (fBrowseButton == null) {
+ assertCompositeNotNull(parent);
+
+ fBrowseButton = new Button(parent, SWT.PUSH);
+ fBrowseButton.setText(fBrowseButtonLabel);
+ fBrowseButton.setEnabled(isEnabled() && fButtonEnabled);
+ fBrowseButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ changeControlPressed();
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ changeControlPressed();
+ }
+ });
+
+ }
+ return fBrowseButton;
+ }
+
+ // ------ enable / disable management
+
+ /**
+ * Sets the enable state of the button.
+ */
+ public void enableButton(boolean enable) {
+ if (isOkToUse(fBrowseButton)) {
+ fBrowseButton.setEnabled(isEnabled() && enable);
+ }
+ fButtonEnabled = enable;
+ }
+
+ /*
+ * @see DialogField#updateEnableState
+ */
+ protected void updateEnableState() {
+ super.updateEnableState();
+ if (isOkToUse(fBrowseButton)) {
+ fBrowseButton.setEnabled(isEnabled() && fButtonEnabled);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringButtonStatusDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringButtonStatusDialogField.java
new file mode 100644
index 0000000..87fd7ea
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringButtonStatusDialogField.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Dialog field containing a label, text control, status label and a button
+ * control. The status label can be either a image or text label, and can be usd
+ * to give additional information about the current element chosen.
+ */
+public class StringButtonStatusDialogField extends StringButtonDialogField {
+
+ private Label fStatusLabelControl;
+
+ private Object fStatus; // String or ImageDescriptor
+
+ private String fWidthHintString;
+
+ private int fWidthHint;
+
+ public StringButtonStatusDialogField(IStringButtonAdapter adapter) {
+ super(adapter);
+ fStatus = null;
+ fWidthHintString = null;
+ fWidthHint = -1;
+ }
+
+ // ------ set status
+
+ /**
+ * Sets the status string.
+ */
+ public void setStatus(String status) {
+ if (isOkToUse(fStatusLabelControl)) {
+ fStatusLabelControl.setText(status);
+ }
+ fStatus = status;
+ }
+
+ /**
+ * Sets the status image. Caller is responsible to dispose image
+ */
+ public void setStatus(Image image) {
+ if (isOkToUse(fStatusLabelControl)) {
+ if (image == null) {
+ fStatusLabelControl.setImage(null);
+ } else {
+ fStatusLabelControl.setImage(image);
+ }
+ }
+ fStatus = image;
+ }
+
+ /**
+ * Sets the staus string hint of the status label. The string is used to
+ * calculate the size of the status label.
+ */
+ public void setStatusWidthHint(String widthHintString) {
+ fWidthHintString = widthHintString;
+ fWidthHint = -1;
+ }
+
+ /**
+ * Sets the width hint of the status label.
+ */
+ public void setStatusWidthHint(int widthHint) {
+ fWidthHint = widthHint;
+ fWidthHintString = null;
+ }
+
+ // ------- layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ assertEnoughColumns(nColumns);
+
+ Label label = getLabelControl(parent);
+ label.setLayoutData(gridDataForLabel(1));
+ Text text = getTextControl(parent);
+ text.setLayoutData(gridDataForText(nColumns - 3));
+ Label status = getStatusLabelControl(parent);
+ status.setLayoutData(gridDataForStatusLabel(parent, 1));
+ Button button = getChangeControl(parent);
+ button.setLayoutData(gridDataForButton(button, 1));
+
+ return new Control[] { label, text, status, button };
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 4;
+ }
+
+ protected GridData gridDataForStatusLabel(Control aControl, int span) {
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.BEGINNING;
+ gd.grabExcessHorizontalSpace = false;
+ gd.horizontalIndent = 0;
+ if (fWidthHintString != null) {
+ GC gc = new GC(aControl);
+ gc.setFont(JFaceResources.getDialogFont());
+ gd.widthHint = gc.textExtent(fWidthHintString).x;
+ gc.dispose();
+ } else if (fWidthHint != -1) {
+ gd.widthHint = fWidthHint;
+ } else {
+ gd.widthHint = SWT.DEFAULT;
+ }
+ return gd;
+ }
+
+ // ------- ui creation
+
+ /**
+ * Creates or returns the created status label widget.
+ *
+ * @param parent
+ * The parent composite or null
when the widget
+ * has already been created.
+ */
+ public Label getStatusLabelControl(Composite parent) {
+ if (fStatusLabelControl == null) {
+ assertCompositeNotNull(parent);
+ fStatusLabelControl = new Label(parent, SWT.LEFT);
+ fStatusLabelControl.setFont(parent.getFont());
+ fStatusLabelControl.setEnabled(isEnabled());
+ if (fStatus instanceof Image) {
+ fStatusLabelControl.setImage((Image) fStatus);
+ } else if (fStatus instanceof String) {
+ fStatusLabelControl.setText((String) fStatus);
+ } else {
+ // must be null
+ }
+ }
+ return fStatusLabelControl;
+ }
+
+ // ------ enable / disable management
+
+ /*
+ * @see DialogField#updateEnableState
+ */
+ protected void updateEnableState() {
+ super.updateEnableState();
+ if (isOkToUse(fStatusLabelControl)) {
+ fStatusLabelControl.setEnabled(isEnabled());
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringDialogField.java
new file mode 100644
index 0000000..e43b145
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/StringDialogField.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Dialog field containing a label and a text control.
+ */
+public class StringDialogField extends DialogField {
+
+ private String fText;
+
+ private Text fTextControl;
+
+ private ModifyListener fModifyListener;
+
+ public StringDialogField() {
+ super();
+ fText = ""; //$NON-NLS-1$
+ }
+
+ // ------- layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ assertEnoughColumns(nColumns);
+
+ Label label = getLabelControl(parent);
+ label.setLayoutData(gridDataForLabel(1));
+ Text text = getTextControl(parent);
+ text.setLayoutData(gridDataForText(nColumns - 1));
+
+ return new Control[] { label, text };
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 2;
+ }
+
+ protected static GridData gridDataForText(int span) {
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = false;
+ gd.horizontalSpan = span;
+ return gd;
+ }
+
+ // ------- focus methods
+
+ /*
+ * @see DialogField#setFocus
+ */
+ public boolean setFocus() {
+ if (isOkToUse(fTextControl)) {
+ fTextControl.setFocus();
+ fTextControl.setSelection(0, fTextControl.getText().length());
+ }
+ return true;
+ }
+
+ // ------- ui creation
+
+ /**
+ * Creates or returns the created text control.
+ *
+ * @param parent
+ * The parent composite or null
when the widget
+ * has already been created.
+ */
+ public Text getTextControl(Composite parent) {
+ if (fTextControl == null) {
+ assertCompositeNotNull(parent);
+ fModifyListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ doModifyText(e);
+ }
+ };
+
+ fTextControl = new Text(parent, SWT.SINGLE | SWT.BORDER);
+ // moved up due to 1GEUNW2
+ fTextControl.setText(fText);
+ fTextControl.setFont(parent.getFont());
+ fTextControl.addModifyListener(fModifyListener);
+
+ fTextControl.setEnabled(isEnabled());
+ }
+ return fTextControl;
+ }
+
+ private void doModifyText(ModifyEvent e) {
+ if (isOkToUse(fTextControl)) {
+ fText = fTextControl.getText();
+ }
+ dialogFieldChanged();
+ }
+
+ // ------ enable / disable management
+
+ /*
+ * @see DialogField#updateEnableState
+ */
+ protected void updateEnableState() {
+ super.updateEnableState();
+ if (isOkToUse(fTextControl)) {
+ fTextControl.setEnabled(isEnabled());
+ }
+ }
+
+ // ------ text access
+
+ /**
+ * Gets the text. Can not be null
+ */
+ public String getText() {
+ return fText;
+ }
+
+ /**
+ * Sets the text. Triggers a dialog-changed event.
+ */
+ public void setText(String text) {
+ fText = text;
+ if (isOkToUse(fTextControl)) {
+ fTextControl.setText(text);
+ } else {
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Sets the text without triggering a dialog-changed event.
+ */
+ public void setTextWithoutUpdate(String text) {
+ fText = text;
+ if (isOkToUse(fTextControl)) {
+ fTextControl.removeModifyListener(fModifyListener);
+ fTextControl.setText(text);
+ fTextControl.addModifyListener(fModifyListener);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/TreeListDialogField.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/TreeListDialogField.java
new file mode 100644
index 0000000..8bed2ad
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/wizards/dialogfields/TreeListDialogField.java
@@ -0,0 +1,922 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+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.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * A list with a button bar. Typical buttons are 'Add', 'Remove', 'Up' and
+ * 'Down'. List model is independend of widget creation. DialogFields controls
+ * are: Label, List and Composite containing buttons.
+ */
+public class TreeListDialogField extends DialogField {
+
+ protected TreeViewer fTree;
+
+ protected ILabelProvider fLabelProvider;
+
+ protected TreeViewerAdapter fTreeViewerAdapter;
+
+ protected List fElements;
+
+ protected ViewerSorter fViewerSorter;
+
+ protected String[] fButtonLabels;
+
+ private Button[] fButtonControls;
+
+ private boolean[] fButtonsEnabled;
+
+ private int fRemoveButtonIndex;
+
+ private int fUpButtonIndex;
+
+ private int fDownButtonIndex;
+
+ private Label fLastSeparator;
+
+ private Tree fTreeControl;
+
+ private Composite fButtonsControl;
+
+ private ISelection fSelectionWhenEnabled;
+
+ private ITreeListAdapter fTreeAdapter;
+
+ private Object fParentElement;
+
+ private int fTreeExpandLevel;
+
+ /**
+ * @param adapter
+ * Can be null
.
+ */
+ public TreeListDialogField(ITreeListAdapter adapter, String[] buttonLabels,
+ ILabelProvider lprovider) {
+ super();
+ fTreeAdapter = adapter;
+
+ fLabelProvider = lprovider;
+ fTreeViewerAdapter = new TreeViewerAdapter();
+ fParentElement = this;
+
+ fElements = new ArrayList(10);
+
+ fButtonLabels = buttonLabels;
+ if (fButtonLabels != null) {
+ int nButtons = fButtonLabels.length;
+ fButtonsEnabled = new boolean[nButtons];
+ for (int i = 0; i < nButtons; i++) {
+ fButtonsEnabled[i] = true;
+ }
+ }
+
+ fTree = null;
+ fTreeControl = null;
+ fButtonsControl = null;
+
+ fRemoveButtonIndex = -1;
+ fUpButtonIndex = -1;
+ fDownButtonIndex = -1;
+
+ fTreeExpandLevel = 0;
+ }
+
+ /**
+ * Sets the index of the 'remove' button in the button label array passed in
+ * the constructor. The behaviour of the button marked as the 'remove'
+ * button will then behandled internally. (enable state, button invocation
+ * behaviour)
+ */
+ public void setRemoveButtonIndex(int removeButtonIndex) {
+ Assert.isTrue(removeButtonIndex < fButtonLabels.length);
+ fRemoveButtonIndex = removeButtonIndex;
+ }
+
+ /**
+ * Sets the index of the 'up' button in the button label array passed in the
+ * constructor. The behaviour of the button marked as the 'up' button will
+ * then behandled internally. (enable state, button invocation behaviour)
+ */
+ public void setUpButtonIndex(int upButtonIndex) {
+ Assert.isTrue(upButtonIndex < fButtonLabels.length);
+ fUpButtonIndex = upButtonIndex;
+ }
+
+ /**
+ * Sets the index of the 'down' button in the button label array passed in
+ * the constructor. The behaviour of the button marked as the 'down' button
+ * will then be handled internally. (enable state, button invocation
+ * behaviour)
+ */
+ public void setDownButtonIndex(int downButtonIndex) {
+ Assert.isTrue(downButtonIndex < fButtonLabels.length);
+ fDownButtonIndex = downButtonIndex;
+ }
+
+ /**
+ * Sets the viewerSorter.
+ *
+ * @param viewerSorter
+ * The viewerSorter to set
+ */
+ public void setViewerSorter(ViewerSorter viewerSorter) {
+ fViewerSorter = viewerSorter;
+ }
+
+ /**
+ * Sets the viewerSorter.
+ *
+ * @param viewerSorter
+ * The viewerSorter to set
+ */
+ public void setTreeExpansionLevel(int level) {
+ fTreeExpandLevel = level;
+ if (fTree != null) {
+ fTree.expandToLevel(level);
+ }
+ }
+
+ // ------ adapter communication
+
+ private void buttonPressed(int index) {
+ if (!managedButtonPressed(index) && fTreeAdapter != null) {
+ fTreeAdapter.customButtonPressed(this, index);
+ }
+ }
+
+ /**
+ * Checks if the button pressed is handled internally
+ *
+ * @return Returns true if button has been handled.
+ */
+ protected boolean managedButtonPressed(int index) {
+ if (index == fRemoveButtonIndex) {
+ remove();
+ } else if (index == fUpButtonIndex) {
+ up();
+ } else if (index == fDownButtonIndex) {
+ down();
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ // ------ layout helpers
+
+ /*
+ * @see DialogField#doFillIntoGrid
+ */
+ public Control[] doFillIntoGrid(Composite parent, int nColumns) {
+ PixelConverter converter = new PixelConverter(parent);
+
+ assertEnoughColumns(nColumns);
+
+ Label label = getLabelControl(parent);
+ GridData gd = gridDataForLabel(1);
+ gd.verticalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gd);
+
+ Control list = getTreeControl(parent);
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = false;
+ gd.verticalAlignment = GridData.FILL;
+ gd.grabExcessVerticalSpace = true;
+ gd.horizontalSpan = nColumns - 2;
+ gd.widthHint = converter.convertWidthInCharsToPixels(50);
+ gd.heightHint = converter.convertHeightInCharsToPixels(6);
+
+ list.setLayoutData(gd);
+
+ Composite buttons = getButtonBox(parent);
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = false;
+ gd.verticalAlignment = GridData.FILL;
+ gd.grabExcessVerticalSpace = true;
+ gd.horizontalSpan = 1;
+ buttons.setLayoutData(gd);
+
+ return new Control[] { label, list, buttons };
+ }
+
+ /*
+ * @see DialogField#getNumberOfControls
+ */
+ public int getNumberOfControls() {
+ return 3;
+ }
+
+ /**
+ * Sets the minimal width of the buttons. Must be called after widget
+ * creation.
+ */
+ public void setButtonsMinWidth(int minWidth) {
+ if (fLastSeparator != null) {
+ ((GridData) fLastSeparator.getLayoutData()).widthHint = minWidth;
+ }
+ }
+
+ // ------ ui creation
+
+ /**
+ * Returns the tree control. When called the first time, the control will be
+ * created.
+ *
+ * @param The
+ * parent composite when called the first time, or
+ * null
after.
+ */
+ public Control getTreeControl(Composite parent) {
+ if (fTreeControl == null) {
+ assertCompositeNotNull(parent);
+
+ fTree = createTreeViewer(parent);
+
+ fTreeControl = (Tree) fTree.getControl();
+ fTreeControl.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ handleKeyPressed(e);
+ }
+ });
+ fTree.setAutoExpandLevel(99);
+ fTree.setContentProvider(fTreeViewerAdapter);
+ fTree.setLabelProvider(fLabelProvider);
+ fTree.addSelectionChangedListener(fTreeViewerAdapter);
+ fTree.addDoubleClickListener(fTreeViewerAdapter);
+
+ fTree.setInput(fParentElement);
+ fTree.expandToLevel(fTreeExpandLevel);
+
+ if (fViewerSorter != null) {
+ fTree.setSorter(fViewerSorter);
+ }
+
+ fTreeControl.setEnabled(isEnabled());
+ if (fSelectionWhenEnabled != null) {
+ postSetSelection(fSelectionWhenEnabled);
+ }
+ }
+ return fTreeControl;
+ }
+
+ /**
+ * Returns the internally used table viewer.
+ */
+ public TreeViewer getTreeViewer() {
+ return fTree;
+ }
+
+ /*
+ * Subclasses may override to specify a different style.
+ */
+ protected int getTreeStyle() {
+ int style = SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
+ return style;
+ }
+
+ protected TreeViewer createTreeViewer(Composite parent) {
+ Tree tree = new Tree(parent, getTreeStyle());
+ return new TreeViewer(tree);
+ }
+
+ protected Button createButton(Composite parent, String label,
+ SelectionListener listener) {
+ Button button = new Button(parent, SWT.PUSH);
+ button.setText(label);
+ button.addSelectionListener(listener);
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = true;
+ gd.verticalAlignment = GridData.BEGINNING;
+ gd.heightHint = SWTUtil.getButtonHeightHint(button);
+ gd.widthHint = SWTUtil.getButtonWidthHint(button);
+
+ button.setLayoutData(gd);
+ return button;
+ }
+
+ private Label createSeparator(Composite parent) {
+ Label separator = new Label(parent, SWT.NONE);
+ separator.setVisible(false);
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.verticalAlignment = GridData.BEGINNING;
+ gd.heightHint = 4;
+ separator.setLayoutData(gd);
+ return separator;
+ }
+
+ /**
+ * Returns the composite containing the buttons. When called the first time,
+ * the control will be created.
+ *
+ * @param The
+ * parent composite when called the first time, or
+ * null
after.
+ */
+ public Composite getButtonBox(Composite parent) {
+ if (fButtonsControl == null) {
+ assertCompositeNotNull(parent);
+
+ SelectionListener listener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ doButtonSelected(e);
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ doButtonSelected(e);
+ }
+ };
+
+ Composite contents = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ contents.setLayout(layout);
+
+ if (fButtonLabels != null) {
+ fButtonControls = new Button[fButtonLabels.length];
+ for (int i = 0; i < fButtonLabels.length; i++) {
+ String currLabel = fButtonLabels[i];
+ if (currLabel != null) {
+ fButtonControls[i] = createButton(contents, currLabel,
+ listener);
+ fButtonControls[i].setEnabled(isEnabled()
+ && fButtonsEnabled[i]);
+ } else {
+ fButtonControls[i] = null;
+ createSeparator(contents);
+ }
+ }
+ }
+
+ fLastSeparator = createSeparator(contents);
+
+ updateButtonState();
+ fButtonsControl = contents;
+ }
+
+ return fButtonsControl;
+ }
+
+ private void doButtonSelected(SelectionEvent e) {
+ if (fButtonControls != null) {
+ for (int i = 0; i < fButtonControls.length; i++) {
+ if (e.widget == fButtonControls[i]) {
+ buttonPressed(i);
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Handles key events in the table viewer. Specifically when the delete key
+ * is pressed.
+ */
+ protected void handleKeyPressed(KeyEvent event) {
+ if (event.character == SWT.DEL && event.stateMask == 0) {
+ if (fRemoveButtonIndex != -1
+ && isButtonEnabled(fTree.getSelection(), fRemoveButtonIndex)) {
+ managedButtonPressed(fRemoveButtonIndex);
+ return;
+ }
+ }
+ fTreeAdapter.keyPressed(this, event);
+ }
+
+ // ------ enable / disable management
+
+ /*
+ * @see DialogField#dialogFieldChanged
+ */
+ public void dialogFieldChanged() {
+ super.dialogFieldChanged();
+ updateButtonState();
+ }
+
+ /*
+ * Updates the enable state of the all buttons
+ */
+ protected void updateButtonState() {
+ if (fButtonControls != null) {
+ ISelection sel = fTree.getSelection();
+ for (int i = 0; i < fButtonControls.length; i++) {
+ Button button = fButtonControls[i];
+ if (isOkToUse(button)) {
+ button.setEnabled(isButtonEnabled(sel, i));
+ }
+ }
+ }
+ }
+
+ protected boolean containsAttributes(List selected) {
+ for (int i = 0; i < selected.size(); i++) {
+ if (!fElements.contains(selected.get(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected boolean getManagedButtonState(ISelection sel, int index) {
+ List selected = getSelectedElements();
+ boolean hasAttributes = containsAttributes(selected);
+ if (index == fRemoveButtonIndex) {
+ return !selected.isEmpty() && !hasAttributes;
+ } else if (index == fUpButtonIndex) {
+ return !sel.isEmpty() && !hasAttributes && canMoveUp(selected);
+ } else if (index == fDownButtonIndex) {
+ return !sel.isEmpty() && !hasAttributes && canMoveDown(selected);
+ }
+ return true;
+ }
+
+ /*
+ * @see DialogField#updateEnableState
+ */
+ protected void updateEnableState() {
+ super.updateEnableState();
+
+ boolean enabled = isEnabled();
+ if (isOkToUse(fTreeControl)) {
+ if (!enabled) {
+ fSelectionWhenEnabled = fTree.getSelection();
+ selectElements(null);
+ } else {
+ selectElements(fSelectionWhenEnabled);
+ fSelectionWhenEnabled = null;
+ }
+ fTreeControl.setEnabled(enabled);
+ }
+ updateButtonState();
+ }
+
+ /**
+ * Sets a button enabled or disabled.
+ */
+ public void enableButton(int index, boolean enable) {
+ if (fButtonsEnabled != null && index < fButtonsEnabled.length) {
+ fButtonsEnabled[index] = enable;
+ updateButtonState();
+ }
+ }
+
+ private boolean isButtonEnabled(ISelection sel, int index) {
+ boolean extraState = getManagedButtonState(sel, index);
+ return isEnabled() && extraState && fButtonsEnabled[index];
+ }
+
+ // ------ model access
+
+ /**
+ * Sets the elements shown in the list.
+ */
+ public void setElements(List elements) {
+ fElements = new ArrayList(elements);
+ refresh();
+ if (fTree != null) {
+ fTree.expandToLevel(fTreeExpandLevel);
+ }
+ dialogFieldChanged();
+ }
+
+ /**
+ * Gets the elements shown in the list. The list returned is a copy, so it
+ * can be modified by the user.
+ */
+ public List getElements() {
+ return new ArrayList(fElements);
+ }
+
+ /**
+ * Gets the element shown at the given index.
+ */
+ public Object getElement(int index) {
+ return fElements.get(index);
+ }
+
+ /**
+ * Gets the index of an element in the list or -1 if element is not in list.
+ */
+ public int getIndexOfElement(Object elem) {
+ return fElements.indexOf(elem);
+ }
+
+ /**
+ * Replace an element.
+ */
+ public void replaceElement(Object oldElement, Object newElement)
+ throws IllegalArgumentException {
+ int idx = fElements.indexOf(oldElement);
+ if (idx != -1) {
+ fElements.set(idx, newElement);
+ if (fTree != null) {
+ List selected = getSelectedElements();
+ if (selected.remove(oldElement)) {
+ selected.add(newElement);
+ }
+ boolean isExpanded = fTree.getExpandedState(oldElement);
+ fTree.remove(oldElement);
+ fTree.add(fParentElement, newElement);
+ if (isExpanded) {
+ fTree.expandToLevel(newElement, fTreeExpandLevel);
+ }
+ selectElements(new StructuredSelection(selected));
+ }
+ dialogFieldChanged();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Adds an element at the end of the tree list.
+ */
+ public void addElement(Object element) {
+ if (fElements.contains(element)) {
+ return;
+ }
+ fElements.add(element);
+ if (fTree != null) {
+ fTree.add(fParentElement, element);
+ fTree.expandToLevel(element, fTreeExpandLevel);
+ }
+ dialogFieldChanged();
+ }
+
+ /**
+ * Adds elements at the end of the tree list.
+ */
+ public void addElements(List elements) {
+ int nElements = elements.size();
+
+ if (nElements > 0) {
+ // filter duplicated
+ ArrayList elementsToAdd = new ArrayList(nElements);
+
+ for (int i = 0; i < nElements; i++) {
+ Object elem = elements.get(i);
+ if (!fElements.contains(elem)) {
+ elementsToAdd.add(elem);
+ }
+ }
+ fElements.addAll(elementsToAdd);
+ if (fTree != null) {
+ fTree.add(fParentElement, elementsToAdd.toArray());
+ for (int i = 0; i < elementsToAdd.size(); i++) {
+ fTree.expandToLevel(elementsToAdd.get(i), fTreeExpandLevel);
+ }
+ }
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Adds an element at a position.
+ */
+ public void insertElementAt(Object element, int index) {
+ if (fElements.contains(element)) {
+ return;
+ }
+ fElements.add(index, element);
+ if (fTree != null) {
+ fTree.add(fParentElement, element);
+ if (fTreeExpandLevel != -1) {
+ fTree.expandToLevel(element, fTreeExpandLevel);
+ }
+ }
+
+ dialogFieldChanged();
+ }
+
+ /**
+ * Adds an element at a position.
+ */
+ public void removeAllElements() {
+ if (fElements.size() > 0) {
+ fElements.clear();
+ refresh();
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Removes an element from the list.
+ */
+ public void removeElement(Object element) throws IllegalArgumentException {
+ if (fElements.remove(element)) {
+ if (fTree != null) {
+ fTree.remove(element);
+ }
+ dialogFieldChanged();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Removes elements from the list.
+ */
+ public void removeElements(List elements) {
+ if (elements.size() > 0) {
+ fElements.removeAll(elements);
+ if (fTree != null) {
+ fTree.remove(elements.toArray());
+ }
+ dialogFieldChanged();
+ }
+ }
+
+ /**
+ * Gets the number of elements
+ */
+ public int getSize() {
+ return fElements.size();
+ }
+
+ public void selectElements(ISelection selection) {
+ fSelectionWhenEnabled = selection;
+ if (fTree != null) {
+ fTree.setSelection(selection, true);
+ }
+ }
+
+ public void selectFirstElement() {
+ Object element = null;
+ if (fViewerSorter != null) {
+ Object[] arr = fElements.toArray();
+ fViewerSorter.sort(fTree, arr);
+ if (arr.length > 0) {
+ element = arr[0];
+ }
+ } else {
+ if (fElements.size() > 0) {
+ element = fElements.get(0);
+ }
+ }
+ if (element != null) {
+ selectElements(new StructuredSelection(element));
+ }
+ }
+
+ public void postSetSelection(final ISelection selection) {
+ if (isOkToUse(fTreeControl)) {
+ Display d = fTreeControl.getDisplay();
+ d.asyncExec(new Runnable() {
+ public void run() {
+ if (isOkToUse(fTreeControl)) {
+ selectElements(selection);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Refreshes the tree.
+ */
+ public void refresh() {
+ if (fTree != null) {
+ fTree.refresh();
+ }
+ }
+
+ /**
+ * Refreshes the tree.
+ */
+ public void refresh(Object element) {
+ if (fTree != null) {
+ fTree.refresh(element);
+ }
+ }
+
+ // ------- list maintenance
+
+ private List moveUp(List elements, List move) {
+ int nElements = elements.size();
+ List res = new ArrayList(nElements);
+ Object floating = null;
+ for (int i = 0; i < nElements; i++) {
+ Object curr = elements.get(i);
+ if (move.contains(curr)) {
+ res.add(curr);
+ } else {
+ if (floating != null) {
+ res.add(floating);
+ }
+ floating = curr;
+ }
+ }
+ if (floating != null) {
+ res.add(floating);
+ }
+ return res;
+ }
+
+ private void moveUp(List toMoveUp) {
+ if (toMoveUp.size() > 0) {
+ setElements(moveUp(fElements, toMoveUp));
+ fTree.reveal(toMoveUp.get(0));
+ }
+ }
+
+ private void moveDown(List toMoveDown) {
+ if (toMoveDown.size() > 0) {
+ setElements(reverse(moveUp(reverse(fElements), toMoveDown)));
+ fTree.reveal(toMoveDown.get(toMoveDown.size() - 1));
+ }
+ }
+
+ private List reverse(List p) {
+ List reverse = new ArrayList(p.size());
+ for (int i = p.size() - 1; i >= 0; i--) {
+ reverse.add(p.get(i));
+ }
+ return reverse;
+ }
+
+ private void remove() {
+ removeElements(getSelectedElements());
+ }
+
+ private void up() {
+ moveUp(getSelectedElements());
+ }
+
+ private void down() {
+ moveDown(getSelectedElements());
+ }
+
+ private boolean canMoveUp(List selectedElements) {
+ if (isOkToUse(fTreeControl)) {
+ int nSelected = selectedElements.size();
+ int nElements = fElements.size();
+ for (int i = 0; i < nElements && nSelected > 0; i++) {
+ if (!selectedElements.contains(fElements.get(i))) {
+ return true;
+ }
+ nSelected--;
+ }
+ }
+ return false;
+ }
+
+ private boolean canMoveDown(List selectedElements) {
+ if (isOkToUse(fTreeControl)) {
+ int nSelected = selectedElements.size();
+ for (int i = fElements.size() - 1; i >= 0 && nSelected > 0; i--) {
+ if (!selectedElements.contains(fElements.get(i))) {
+ return true;
+ }
+ nSelected--;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the selected elements.
+ */
+ public List getSelectedElements() {
+ ArrayList result = new ArrayList();
+ if (fTree != null) {
+ ISelection selection = fTree.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ Iterator iter = ((IStructuredSelection) selection).iterator();
+ while (iter.hasNext()) {
+ result.add(iter.next());
+ }
+ }
+ }
+ return result;
+ }
+
+ public void expandElement(Object element, int level) {
+ if (fTree != null) {
+ fTree.expandToLevel(element, level);
+ }
+ }
+
+ // ------- TreeViewerAdapter
+
+ private class TreeViewerAdapter implements ITreeContentProvider,
+ ISelectionChangedListener, IDoubleClickListener {
+
+ private final Object[] NO_ELEMENTS = new Object[0];
+
+ // ------- ITreeContentProvider Interface ------------
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // will never happen
+ }
+
+ public boolean isDeleted(Object element) {
+ return false;
+ }
+
+ public void dispose() {
+ }
+
+ public Object[] getElements(Object obj) {
+ return fElements.toArray();
+ }
+
+ public Object[] getChildren(Object element) {
+ if (fTreeAdapter != null) {
+ return fTreeAdapter.getChildren(TreeListDialogField.this,
+ element);
+ }
+ return NO_ELEMENTS;
+ }
+
+ public Object getParent(Object element) {
+ if (!fElements.contains(element) && fTreeAdapter != null) {
+ return fTreeAdapter
+ .getParent(TreeListDialogField.this, element);
+ }
+ return fParentElement;
+ }
+
+ public boolean hasChildren(Object element) {
+ if (fTreeAdapter != null) {
+ return fTreeAdapter.hasChildren(TreeListDialogField.this,
+ element);
+ }
+ return false;
+ }
+
+ // ------- ISelectionChangedListener Interface ------------
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ doListSelected(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent)
+ */
+ public void doubleClick(DoubleClickEvent event) {
+ doDoubleClick(event);
+ }
+
+ }
+
+ protected void doListSelected(SelectionChangedEvent event) {
+ updateButtonState();
+ if (fTreeAdapter != null) {
+ fTreeAdapter.selectionChanged(this);
+ }
+ }
+
+ protected void doDoubleClick(DoubleClickEvent event) {
+ if (fTreeAdapter != null) {
+ fTreeAdapter.doubleClicked(this);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/UITexts.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/UITexts.java
new file mode 100644
index 0000000..0914c0c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/UITexts.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.ui;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ *
+ * provides internationalized String messages for the UI.
+ *
+ *
+ */
+public class UITexts {
+
+ private static final String BUNDLE_NAME = "net.sourceforge.phpdt.ltk.ui.uitexts"; //$NON-NLS-1$
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, UITexts.class);
+ }
+
+ // message fields
+ public static String renameProperty_refuseDlg_title;
+
+ public static String renameProperty_refuseDlg_message;
+
+ public static String renamePropertyInputPage_lblNewName;
+
+ public static String renamePropertyInputPage_cbUpdateBundle;
+
+ public static String renamePropertyInputPage_cbAllProjects;
+
+ public static String renameLocalVariable_refuseDlg_title;
+
+ public static String renameLocalVariable_refuseDlg_message;
+
+ public static String renameLocalVariable_cbDQStrings;
+
+ public static String renameLocalVariable_cbPHPdoc;
+
+ public static String renameLocalVariable_cbOtherDoc;
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/actions/RenameLocalVariable.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/actions/RenameLocalVariable.java
new file mode 100644
index 0000000..efe11dd
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/actions/RenameLocalVariable.java
@@ -0,0 +1,213 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.ui.actions;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.core.SourceMethod;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
+import net.sourceforge.phpdt.ltk.core.RenameLocalVariableDelegate;
+import net.sourceforge.phpdt.ltk.core.RenamePHPProcessor;
+import net.sourceforge.phpdt.ltk.ui.UITexts;
+import net.sourceforge.phpdt.ltk.ui.wizards.RenameLocalVariableWizard;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+public class RenameLocalVariable implements IEditorActionDelegate {
+
+ private ISelection selection;
+
+ private IEditorPart targetEditor;
+
+ private boolean onPHPFile;
+
+ private RenameIdentifierInfo info = new RenameIdentifierInfo();
+
+ public void setActiveEditor(final IAction action,
+ final IEditorPart targetEditor) {
+ this.targetEditor = targetEditor;
+ onPHPFile = false;
+ IFile file = getFile();
+
+ if (file != null && PHPFileUtil.isPHPFile(file)) {
+ onPHPFile = true;
+ }
+ }
+
+ public void run(final IAction action) {
+ if (!onPHPFile) {
+ refuse();
+ } else {
+ if (selection != null && selection instanceof ITextSelection) {
+ String word = null;
+ Point point = null;
+ if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+ PHPEditor editor = (PHPEditor) targetEditor;
+ if (editor != null) {
+ ITextSelection textSelection = (ITextSelection) editor
+ .getSelectionProvider().getSelection();
+ IDocument doc = editor.getDocumentProvider()
+ .getDocument(editor.getEditorInput());
+ int pos = textSelection.getOffset();
+ point = PHPWordExtractor.findWord(doc, pos);
+ if (point != null) {
+ try {
+ word = doc.get(point.x, point.y);
+ IWorkingCopyManager manager = WebUI
+ .getDefault().getWorkingCopyManager();
+ ICompilationUnit unit = manager
+ .getWorkingCopy(editor.getEditorInput());
+ SourceMethod method = (SourceMethod) findEnclosingElement(
+ point.x, unit, IJavaElement.METHOD);
+ if (word == null || word.charAt(0) != '$'
+ || method == null
+ || !(method instanceof SourceMethod)) {
+ refuseLocalVariable();
+ } else {
+ applySelection((ITextSelection) selection,
+ word, point, method);
+ if (saveAll()) {
+ openWizard();
+ }
+ }
+ } catch (BadLocationException e) {
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the enclosing element of a particular element type,
+ * null
if no enclosing element of that type exists.
+ */
+ public IJavaElement findEnclosingElement(int start, ICompilationUnit cu,
+ int elementType) {
+ if (cu == null)
+ return null;
+
+ try {
+ IJavaElement element = cu.getElementAt(start);
+ if (element == null) {
+ element = cu;
+ }
+
+ return element.getAncestor(elementType);
+
+ } catch (JavaModelException e) {
+ return null;
+ }
+ }
+
+ public void selectionChanged(final IAction action,
+ final ISelection selection) {
+ this.selection = selection;
+ }
+
+ // helping methods
+ // ////////////////
+
+ private void applySelection(final ITextSelection textSelection,
+ String word, Point point, SourceMethod method) {
+ if (word != null) {
+ info.setOldName(word);
+ info.setNewName(word);
+ info.setOffset(point.x);
+ } else {
+ info.setOldName(textSelection.getText());
+ info.setNewName(textSelection.getText());
+ info.setOffset(textSelection.getOffset());
+ }
+ info.setMethod(method);
+ info.setSourceFile(getFile());
+ }
+
+ private void refuseLocalVariable() {
+ String title = UITexts.renameLocalVariable_refuseDlg_title;
+ String message = UITexts.renameLocalVariable_refuseDlg_message;
+ MessageDialog.openInformation(getShell(), title, message);
+ }
+
+ private void refuse() {
+ String title = UITexts.renameProperty_refuseDlg_title;
+ String message = UITexts.renameProperty_refuseDlg_message;
+ MessageDialog.openInformation(getShell(), title, message);
+ }
+
+ private static boolean saveAll() {
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ return IDE.saveAllEditors(new IResource[] { workspaceRoot }, false);
+ }
+
+ private void openWizard() {
+ RenameLocalVariableDelegate delegate = new RenameLocalVariableDelegate(
+ info);
+ RefactoringProcessor processor = new RenamePHPProcessor(info, delegate);
+ RenameIdentifierRefactoring ref = new RenameIdentifierRefactoring(
+ processor);
+ RenameLocalVariableWizard wizard = new RenameLocalVariableWizard(ref,
+ info);
+ RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(
+ wizard);
+ try {
+ String titleForFailedChecks = ""; //$NON-NLS-1$
+ op.run(getShell(), titleForFailedChecks);
+ } catch (final InterruptedException irex) {
+ // operation was cancelled
+ }
+ }
+
+ private Shell getShell() {
+ Shell result = null;
+ if (targetEditor != null) {
+ result = targetEditor.getSite().getShell();
+ } else {
+ result = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+ .getShell();
+ }
+ return result;
+ }
+
+ private final IFile getFile() {
+ IFile result = null;
+ if (targetEditor instanceof ITextEditor) {
+ ITextEditor editor = (ITextEditor) targetEditor;
+ IEditorInput input = editor.getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ result = ((IFileEditorInput) input).getFile();
+ }
+ }
+ return result;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/actions/RenamePHPIdentifier.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/actions/RenamePHPIdentifier.java
new file mode 100644
index 0000000..53d06a5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/actions/RenamePHPIdentifier.java
@@ -0,0 +1,175 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.ui.actions;
+
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierDelegate;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
+import net.sourceforge.phpdt.ltk.core.RenamePHPProcessor;
+import net.sourceforge.phpdt.ltk.ui.UITexts;
+import net.sourceforge.phpdt.ltk.ui.wizards.RenameIdentifierWizard;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ *
+ * action that is triggered from the editor context menu.
+ *
+ *
+ *
+ * This action is declared in the plugin.xml
.
+ *
+ *
+ */
+public class RenamePHPIdentifier implements IEditorActionDelegate {
+
+ private ISelection selection;
+
+ private IEditorPart targetEditor;
+
+ private boolean onPHPFile;
+
+ private RenameIdentifierInfo info = new RenameIdentifierInfo();
+
+ // interface methods of IEditorActionDelegate
+ // ///////////////////////////////////////////
+
+ public void setActiveEditor(final IAction action,
+ final IEditorPart targetEditor) {
+ this.targetEditor = targetEditor;
+ onPHPFile = false;
+ IFile file = getFile();
+
+ if (file != null && PHPFileUtil.isPHPFile(file)) {
+ onPHPFile = true;
+ }
+ }
+
+ public void run(final IAction action) {
+ if (!onPHPFile) {
+ refuse();
+ } else {
+ if (selection != null && selection instanceof ITextSelection) {
+ String word = null;
+ Point point = null;
+ if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+ PHPEditor editor = (PHPEditor) targetEditor;
+ if (editor != null) {
+ ITextSelection textSelection = (ITextSelection) editor
+ .getSelectionProvider().getSelection();
+ IDocument doc = editor.getDocumentProvider()
+ .getDocument(editor.getEditorInput());
+ int pos = textSelection.getOffset();
+ point = PHPWordExtractor.findWord(doc, pos);
+ if (point != null) {
+ try {
+ word = doc.get(point.x, point.y);
+ } catch (BadLocationException e) {
+ }
+ }
+ }
+ }
+ applySelection((ITextSelection) selection, word, point);
+ if (saveAll()) {
+ openWizard();
+ }
+ }
+ }
+ }
+
+ public void selectionChanged(final IAction action,
+ final ISelection selection) {
+ this.selection = selection;
+ }
+
+ // helping methods
+ // ////////////////
+
+ private void applySelection(final ITextSelection textSelection,
+ String word, Point point) {
+ if (word != null) {
+ info.setOldName(word);
+ info.setNewName(word);
+ info.setOffset(point.x);
+ } else {
+ info.setOldName(textSelection.getText());
+ info.setNewName(textSelection.getText());
+ info.setOffset(textSelection.getOffset());
+ }
+ info.setSourceFile(getFile());
+ }
+
+ private void refuse() {
+ String title = UITexts.renameProperty_refuseDlg_title;
+ String message = UITexts.renameProperty_refuseDlg_message;
+ MessageDialog.openInformation(getShell(), title, message);
+ }
+
+ private static boolean saveAll() {
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ return IDE.saveAllEditors(new IResource[] { workspaceRoot }, false);
+ }
+
+ private void openWizard() {
+ RenameIdentifierDelegate delegate = new RenameIdentifierDelegate(info);
+ RefactoringProcessor processor = new RenamePHPProcessor(info, delegate);
+ RenameIdentifierRefactoring ref = new RenameIdentifierRefactoring(
+ processor);
+ RenameIdentifierWizard wizard = new RenameIdentifierWizard(ref, info);
+ RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(
+ wizard);
+ try {
+ String titleForFailedChecks = ""; //$NON-NLS-1$
+ op.run(getShell(), titleForFailedChecks);
+ } catch (final InterruptedException irex) {
+ // operation was cancelled
+ }
+ }
+
+ private Shell getShell() {
+ Shell result = null;
+ if (targetEditor != null) {
+ result = targetEditor.getSite().getShell();
+ } else {
+ result = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+ .getShell();
+ }
+ return result;
+ }
+
+ private final IFile getFile() {
+ IFile result = null;
+ if (targetEditor instanceof ITextEditor) {
+ ITextEditor editor = (ITextEditor) targetEditor;
+ IEditorInput input = editor.getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ result = ((IFileEditorInput) input).getFile();
+ }
+ }
+ return result;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/uitexts.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/uitexts.properties
new file mode 100644
index 0000000..219e39d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/uitexts.properties
@@ -0,0 +1,11 @@
+renameProperty_refuseDlg_title=Rename PHP identifier
+renameProperty_refuseDlg_message=This refactoring is only available on PHP files.
+renamePropertyInputPage_lblNewName=New name\:
+renamePropertyInputPage_cbUpdateBundle=Update all PHP files in the same project
+renamePropertyInputPage_cbAllProjects=Update all PHP projects in the workspace (forces preview)
+
+renameLocalVariable_refuseDlg_title=Rename Local PHP variable
+renameLocalVariable_refuseDlg_message=The selected identifier is no local PHP variable.
+renameLocalVariable_cbDQStrings=Rename variable inside double quoted strings
+renameLocalVariable_cbPHPdoc=Rename variable inside PHPdoc comments
+renameLocalVariable_cbOtherDoc=Rename variable inside other PHP comments (line or block)
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierPage.java
new file mode 100644
index 0000000..e29747b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierPage.java
@@ -0,0 +1,181 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+package net.sourceforge.phpdt.ltk.ui.wizards;
+
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.ui.UITexts;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+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.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ *
+ * the input page for the Rename Property refactoring, where users can control
+ * the effects of the refactoring; to be shown in the wizard.
+ *
+ *
+ *
+ * We let the user enter the new name for the property, and we let her decide
+ * whether other property files in the bundle should be affected, and whether
+ * the operation is supposed to span the entire workspace or only the current
+ * project.
+ *
+ *
+ */
+public class RenameIdentifierPage extends UserInputWizardPage {
+
+ private static final String DS_KEY = RenameIdentifierPage.class.getName();
+
+ private static final String DS_UPDATE_BUNDLE = "UPDATE_BUNDLE"; //$NON-NLS-1$
+
+ private static final String DS_ALL_PROJECTS = "ALL_PROJECTS"; //$NON-NLS-1$
+
+ private final RenameIdentifierInfo info;
+
+ private IDialogSettings dialogSettings;
+
+ private Text txtNewName;
+
+ private Button cbUpdateBundle;
+
+ private Button cbAllProjects;
+
+ public RenameIdentifierPage(final RenameIdentifierInfo info) {
+ super(RenameIdentifierPage.class.getName());
+ this.info = info;
+ initDialogSettings();
+ }
+
+ // interface methods of UserInputWizardPage
+ // /////////////////////////////////////////
+
+ public void createControl(final Composite parent) {
+ Composite composite = createRootComposite(parent);
+ setControl(composite);
+
+ createLblNewName(composite);
+ createTxtNewName(composite);
+ createCbUpdateBundle(composite);
+ createCbAllProjects(composite);
+
+ validate();
+ }
+
+ // UI creation methods
+ // ////////////////////
+
+ private Composite createRootComposite(final Composite parent) {
+ Composite result = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = 10;
+ gridLayout.marginHeight = 10;
+ result.setLayout(gridLayout);
+ initializeDialogUnits(result);
+ Dialog.applyDialogFont(result);
+ return result;
+ }
+
+ private void createLblNewName(final Composite composite) {
+ Label lblNewName = new Label(composite, SWT.NONE);
+ lblNewName.setText(UITexts.renamePropertyInputPage_lblNewName);
+ }
+
+ private void createTxtNewName(Composite composite) {
+ txtNewName = new Text(composite, SWT.BORDER);
+ txtNewName.setText(info.getOldName());
+ txtNewName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ txtNewName.selectAll();
+ txtNewName.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ info.setNewName(txtNewName.getText());
+ validate();
+ }
+ });
+ }
+
+ private void createCbUpdateBundle(final Composite composite) {
+ String texts = UITexts.renamePropertyInputPage_cbUpdateBundle;
+ cbUpdateBundle = createCheckbox(composite, texts);
+ cbUpdateBundle.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(final SelectionEvent event) {
+ boolean selected = cbUpdateBundle.getSelection();
+ dialogSettings.put(DS_UPDATE_BUNDLE, selected);
+ info.setUpdateProject(selected);
+ }
+ });
+ initUpdateBundleOption();
+ }
+
+ private void createCbAllProjects(final Composite composite) {
+ String text = UITexts.renamePropertyInputPage_cbAllProjects;
+ cbAllProjects = createCheckbox(composite, text);
+ cbAllProjects.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(final SelectionEvent event) {
+ boolean selected = cbAllProjects.getSelection();
+ dialogSettings.put(DS_ALL_PROJECTS, selected);
+ info.setAllProjects(selected);
+ // for demonstration purposes, we enforce the preview for
+ // refactorings
+ // that span the entire workspace
+ getRefactoringWizard().setForcePreviewReview(selected);
+ }
+ });
+ initAllProjectsOption();
+ }
+
+ private Button createCheckbox(final Composite composite, final String text) {
+ Button result = new Button(composite, SWT.CHECK);
+ result.setText(text);
+
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalSpan = 2;
+ result.setLayoutData(gridData);
+
+ return result;
+ }
+
+ // helping methods
+ // ////////////////
+
+ private void initDialogSettings() {
+ IDialogSettings ds = WebUI.getDefault().getDialogSettings();
+ dialogSettings = ds.getSection(DS_KEY);
+ if (dialogSettings == null) {
+ dialogSettings = ds.addNewSection(DS_KEY);
+ // init default values
+ dialogSettings.put(DS_UPDATE_BUNDLE, true);
+ dialogSettings.put(DS_ALL_PROJECTS, false);
+ }
+ }
+
+ private void validate() {
+ String txt = txtNewName.getText();
+ setPageComplete(txt.length() > 0 && !txt.equals(info.getOldName()));
+ }
+
+ private void initUpdateBundleOption() {
+ boolean updateRefs = dialogSettings.getBoolean(DS_UPDATE_BUNDLE);
+ cbUpdateBundle.setSelection(updateRefs);
+ info.setUpdateProject(updateRefs);
+ }
+
+ private void initAllProjectsOption() {
+ boolean allProjects = dialogSettings.getBoolean(DS_ALL_PROJECTS);
+ cbAllProjects.setSelection(allProjects);
+ info.setAllProjects(allProjects);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierWizard.java
new file mode 100644
index 0000000..ca8bb68
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierWizard.java
@@ -0,0 +1,40 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+package net.sourceforge.phpdt.ltk.ui.wizards;
+
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
+
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+
+/**
+ *
+ * The wizard that is shown to the user for entering the necessary information
+ * for property renaming.
+ *
+ *
+ *
+ * The wizard class is primarily needed for deciding which pages are shown to
+ * the user. The actual user interface creation goes on the pages.
+ *
+ *
+ */
+public class RenameIdentifierWizard extends RefactoringWizard {
+
+ private final RenameIdentifierInfo info;
+
+ public RenameIdentifierWizard(
+ final RenameIdentifierRefactoring refactoring,
+ final RenameIdentifierInfo info) {
+ super(refactoring, DIALOG_BASED_USER_INTERFACE);
+ this.info = info;
+ }
+
+ // interface methods of RefactoringWizard
+ // ///////////////////////////////////////
+
+ protected void addUserInputPages() {
+ setDefaultPageTitle(getRefactoring().getName());
+ addPage(new RenameLocalVariablePage(info));
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariablePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariablePage.java
new file mode 100644
index 0000000..3db9cec
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariablePage.java
@@ -0,0 +1,215 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+package net.sourceforge.phpdt.ltk.ui.wizards;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.ui.UITexts;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+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.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ *
+ * the input page for the Rename Property refactoring, where users can control
+ * the effects of the refactoring; to be shown in the wizard.
+ *
+ *
+ *
+ * We let the user enter the new name for the property, and we let her decide
+ * whether other property files in the bundle should be affected, and whether
+ * the operation is supposed to span the entire workspace or only the current
+ * project.
+ *
+ *
+ */
+public class RenameLocalVariablePage extends UserInputWizardPage {
+
+ private static final String DS_KEY = RenameLocalVariablePage.class
+ .getName();
+
+ private static final String DS_RENAME_DQ_STRINGS = "RENAME_DQ_STRINGS"; //$NON-NLS-1$
+
+ private static final String DS_RENAME_PHPDOC = "RENAME_PHPDOC"; //$NON-NLS-1$
+
+ private static final String DS_RENAME_OTHER_COMMENTS = "RENAME_OTHER_COMMENTS"; //$NON-NLS-1$
+
+ private final RenameIdentifierInfo info;
+
+ private IDialogSettings dialogSettings;
+
+ private Text txtNewName;
+
+ private Button cbRenameDQStrings;
+
+ private Button cbRenamePHPdoc;
+
+ private Button cbRenameOtherComments;
+
+ public RenameLocalVariablePage(final RenameIdentifierInfo info) {
+ super(RenameLocalVariablePage.class.getName());
+ this.info = info;
+ initDialogSettings();
+ }
+
+ public void createControl(final Composite parent) {
+ Composite composite = createRootComposite(parent);
+ setControl(composite);
+
+ createLblNewName(composite);
+ createTxtNewName(composite);
+ createCbDQStrings(composite);
+ createCbPHPdoc(composite);
+ createCbOtherComments(composite);
+
+ validate();
+
+ // TODO check if we can leave this step out in the future
+ getRefactoringWizard().setForcePreviewReview(true);
+ }
+
+ private Composite createRootComposite(final Composite parent) {
+ Composite result = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = 10;
+ gridLayout.marginHeight = 10;
+ result.setLayout(gridLayout);
+ initializeDialogUnits(result);
+ Dialog.applyDialogFont(result);
+ return result;
+ }
+
+ private void createLblNewName(final Composite composite) {
+ Label lblNewName = new Label(composite, SWT.NONE);
+ lblNewName.setText(UITexts.renamePropertyInputPage_lblNewName);
+ }
+
+ private void createTxtNewName(Composite composite) {
+ txtNewName = new Text(composite, SWT.BORDER);
+ txtNewName.setText(info.getOldName());
+ txtNewName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ txtNewName.selectAll();
+ txtNewName.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ info.setNewName(txtNewName.getText());
+ validate();
+ }
+ });
+ }
+
+ private void createCbDQStrings(final Composite composite) {
+ String texts = UITexts.renameLocalVariable_cbDQStrings;
+ cbRenameDQStrings = createCheckbox(composite, texts);
+ cbRenameDQStrings.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(final SelectionEvent event) {
+ boolean selected = cbRenameDQStrings.getSelection();
+ dialogSettings.put(DS_RENAME_DQ_STRINGS, selected);
+ info.setRenameDQString(selected);
+ }
+ });
+ initDQStringsOption();
+ }
+
+ private void createCbPHPdoc(final Composite composite) {
+ String texts = UITexts.renameLocalVariable_cbPHPdoc;
+ cbRenamePHPdoc = createCheckbox(composite, texts);
+ cbRenamePHPdoc.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(final SelectionEvent event) {
+ boolean selected = cbRenamePHPdoc.getSelection();
+ dialogSettings.put(DS_RENAME_PHPDOC, selected);
+ info.setRenamePHPdoc(selected);
+ }
+ });
+ initPHPdocOption();
+ }
+
+ private void createCbOtherComments(final Composite composite) {
+ String texts = UITexts.renameLocalVariable_cbOtherDoc;
+ cbRenameOtherComments = createCheckbox(composite, texts);
+ cbRenameOtherComments.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(final SelectionEvent event) {
+ boolean selected = cbRenameOtherComments.getSelection();
+ dialogSettings.put(DS_RENAME_OTHER_COMMENTS, selected);
+ info.setRenameOtherComments(selected);
+ }
+ });
+ initOtherCommentsOption();
+ }
+
+ private Button createCheckbox(final Composite composite, final String text) {
+ Button result = new Button(composite, SWT.CHECK);
+ result.setText(text);
+
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalSpan = 2;
+ result.setLayoutData(gridData);
+
+ return result;
+ }
+
+ private void initDialogSettings() {
+ IDialogSettings ds = WebUI.getDefault().getDialogSettings();
+ dialogSettings = ds.getSection(DS_KEY);
+ if (dialogSettings == null) {
+ dialogSettings = ds.addNewSection(DS_KEY);
+ // init default values
+ dialogSettings.put(DS_RENAME_DQ_STRINGS, true);
+ dialogSettings.put(DS_RENAME_PHPDOC, true);
+ dialogSettings.put(DS_RENAME_OTHER_COMMENTS, true);
+ }
+ }
+
+ private static boolean isVariable(String txt) {
+ if (txt.length() <= 1) {
+ return false;
+ }
+ if (txt.charAt(0) != '$') {
+ return false;
+ }
+ for (int i = 1; i < txt.length(); i++) {
+ if (!Scanner.isPHPIdentifierPart(txt.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void validate() {
+ String txt = txtNewName.getText();
+ Scanner s;
+ setPageComplete(isVariable(txt) && !txt.equals(info.getOldName()));
+ }
+
+ private void initDQStringsOption() {
+ boolean refs = dialogSettings.getBoolean(DS_RENAME_DQ_STRINGS);
+ cbRenameDQStrings.setSelection(refs);
+ info.setRenameDQString(refs);
+ }
+
+ private void initPHPdocOption() {
+ boolean refs = dialogSettings.getBoolean(DS_RENAME_PHPDOC);
+ cbRenamePHPdoc.setSelection(refs);
+ info.setRenamePHPdoc(refs);
+ }
+
+ private void initOtherCommentsOption() {
+ boolean refs = dialogSettings.getBoolean(DS_RENAME_OTHER_COMMENTS);
+ cbRenameOtherComments.setSelection(refs);
+ info.setRenameOtherComments(refs);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariableWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariableWizard.java
new file mode 100644
index 0000000..a4f8941
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariableWizard.java
@@ -0,0 +1,37 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+package net.sourceforge.phpdt.ltk.ui.wizards;
+
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
+
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+
+/**
+ *
+ * The wizard that is shown to the user for entering the necessary information
+ * for property renaming of local PHP variables.
+ *
+ *
+ *
+ * The wizard class is primarily needed for deciding which pages are shown to
+ * the user. The actual user interface creation goes on the pages.
+ *
+ *
+ */
+public class RenameLocalVariableWizard extends RefactoringWizard {
+
+ private final RenameIdentifierInfo info;
+
+ public RenameLocalVariableWizard(
+ final RenameIdentifierRefactoring refactoring,
+ final RenameIdentifierInfo info) {
+ super(refactoring, DIALOG_BASED_USER_INTERFACE);
+ this.info = info;
+ }
+
+ protected void addUserInputPages() {
+ setDefaultPageTitle(getRefactoring().getName());
+ addPage(new RenameLocalVariablePage(info));
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/CodeGeneration.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/CodeGeneration.java
new file mode 100644
index 0000000..05dacb0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/CodeGeneration.java
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * Class that offers access to the templates contained in the 'code templates'
+ * preference page.
+ *
+ * @since 2.1
+ */
+public class CodeGeneration {
+
+ private CodeGeneration() {
+ }
+
+ /**
+ * Returns the content for a new compilation unit using the 'new Java file'
+ * code template.
+ *
+ * @param cu
+ * The compilation to create the source for. The compilation unit
+ * does not need to exist.
+ * @param typeComment
+ * The comment for the type to be 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
+ * Thrown when the evaluation of the code template fails.
+ */
+ public static String getCompilationUnitContent(ICompilationUnit cu,
+ String typeComment, String typeContent, String lineDelimiter)
+ throws CoreException {
+ return StubUtility.getCompilationUnitContent(cu, typeComment,
+ typeContent, lineDelimiter);
+ }
+
+ /**
+ * Returns the content for a new type comment using the 'type comment' code
+ * template. The returned content is unformatted and is not indented.
+ *
+ * @param cu
+ * The compilation where the type is contained. The compilation
+ * 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). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @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.
+ */
+ public static String getTypeComment(ICompilationUnit cu,
+ String typeQualifiedName, String lineDelimiter)
+ throws CoreException {
+ return StubUtility.getTypeComment(cu, typeQualifiedName, lineDelimiter);
+ }
+
+ /**
+ * Returns the content for a new field comment using the 'field comment'
+ * code template. The returned content is unformatted and is not indented.
+ *
+ * @param cu
+ * The compilation where the field is contained. The compilation
+ * unit does not need to exist.
+ * @param typeName
+ * The name of the field declared type.
+ * @param fieldName
+ * The name of the field to which the comment is added.
+ * @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 3.0
+ */
+ public static String getFieldComment(ICompilationUnit cu, String typeName,
+ String fieldName, String lineDelimiter) throws CoreException {
+ return StubUtility.getFieldComment(cu, typeName, fieldName,
+ lineDelimiter);
+ }
+
+ /**
+ * Returns the comment for a method or constructor using the comment code
+ * templates (constructor / method / overriding method). null
+ * is returned if the template is empty.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs. The
+ * compilation unit does not need to exist.
+ * @param declaringTypeName
+ * Name of the type to which the method belongs. For inner types
+ * the name must be qualified and include the outer types names
+ * (dot separated). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @param decl
+ * The MethodDeclaration AST node that will be added as new
+ * method. The node does not need to exist in an AST (no parent
+ * needed) and does not need to resolve. See
+ * {@link net.sourceforge.phpdt.core.dom.AST#newMethodDeclaration()}
+ * for how to create such a node.
+ * @param overridden
+ * The binding of the method that will be overridden by the
+ * created method or null
if no method is
+ * overridden.
+ * @param lineDelimiter
+ * The line delimiter to be used.
+ * @return Returns the generated method comment or null
if
+ * the 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(ICompilationUnit cu, String
+ // declaringTypeName, MethodDeclaration decl, IMethodBinding overridden,
+ // String lineDelimiter) throws CoreException {
+ // return StubUtility.getMethodComment(cu, declaringTypeName, decl,
+ // overridden, lineDelimiter);
+ // }
+ /**
+ * Returns the comment for a method or constructor using the comment code
+ * templates (constructor / method / overriding method). null
+ * is returned if the template is empty.
+ *
+ * The returned string is unformatted and not indented.
+ *
+ * Exception types and return type are in signature notation. e.g. a source
+ * method declared as public void foo(String text, int length)
+ * would return the array {"QString;","I"}
as parameter
+ * types. See {@link net.sourceforge.phpdt.core.Signature}.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs. The
+ * compilation unit does not need to exist.
+ * @param declaringTypeName
+ * Name of the type to which the method belongs. For inner types
+ * the name must be qualified and include the outer types names
+ * (dot separated). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @param methodName
+ * Name of the method.
+ * @param paramNames
+ * Names of the parameters for the method.
+ * @param excTypeSig
+ * Thrown exceptions (Signature notation).
+ * @param retTypeSig
+ * Return type (Signature notation) or null
for
+ * constructors.
+ * @param overridden
+ * The method that will be overridden by the created method or
+ * null
for non-overriding methods. If not
+ * null
, the method must exist.
+ * @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(ICompilationUnit cu,
+ String declaringTypeName, String methodName, String[] paramNames,
+ String[] excTypeSig, String retTypeSig, IMethod overridden,
+ String lineDelimiter) throws CoreException {
+ return StubUtility.getMethodComment(cu, declaringTypeName, methodName,
+ paramNames, excTypeSig, retTypeSig, overridden, lineDelimiter);
+ }
+
+ /**
+ * Returns the comment for a method or constructor using the comment code
+ * templates (constructor / method / overriding method). null
+ * is returned if the template is empty.
+ *
+ * The returned string is unformatted and not indented.
+ *
+ * @param method
+ * The method to be documented. The method must exist.
+ * @param overridden
+ * The method that will be overridden by the created method or
+ * null
for non-overriding methods. If not
+ * null
, the method must exist.
+ * @param lineDelimiter
+ * The line delimiter to be used.
+ * @return Returns the constructed comment 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 getMethodComment(IMethod method, IMethod overridden,
+ String lineDelimiter) throws CoreException {
+ return StubUtility.getMethodComment(method, overridden, lineDelimiter);
+ }
+
+ /**
+ * Returns the content of the body for a method or constructor using the
+ * method body templates. null
is returned if the template is
+ * empty.
+ *
+ * The returned string is unformatted and not indented.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs. The
+ * compilation unit does not need to exist.
+ * @param declaringTypeName
+ * Name of the type to which the method belongs. For inner types
+ * the name must be qualified and include the outer types names
+ * (dot separated). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @param methodName
+ * Name of the method.
+ * @param isConstructor
+ * Defines if the created body is for a constructor.
+ * @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(ICompilationUnit cu,
+ String declaringTypeName, String methodName, boolean isConstructor,
+ String bodyStatement, String lineDelimiter) throws CoreException {
+ return StubUtility.getMethodBodyContent(isConstructor, cu
+ .getJavaProject(), declaringTypeName, methodName,
+ bodyStatement, lineDelimiter);
+ }
+
+ /**
+ * Returns the content of body for a getter method using the getter method
+ * body template. null
is returned if the template is empty.
+ *
+ * The returned string is unformatted and not indented.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs. The
+ * compilation unit does not need to exist.
+ * @param declaringTypeName
+ * Name of the type to which the method belongs. For inner types
+ * the name must be qualified and include the outer types names
+ * (dot separated). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @param methodName
+ * The name of the getter method.
+ * @param fieldName
+ * The name of the field to get in the getter method,
+ * corresponding to the template variable for ${field}.
+ * @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.
+ * @since 3.0
+ */
+ public static String getGetterMethodBodyContent(ICompilationUnit cu,
+ String declaringTypeName, String methodName, String fieldName,
+ String lineDelimiter) throws CoreException {
+ return StubUtility.getGetterMethodBodyContent(cu.getJavaProject(),
+ declaringTypeName, methodName, fieldName, lineDelimiter);
+ }
+
+ /**
+ * Returns the content of body for a setter method using the setter method
+ * body template. null
is returned if the template is empty.
+ *
+ * The returned string is unformatted and not indented.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs. The
+ * compilation unit does not need to exist.
+ * @param declaringTypeName
+ * Name of the type to which the method belongs. For inner types
+ * the name must be qualified and include the outer types names
+ * (dot separated). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @param methodName
+ * The name of the setter method.
+ * @param fieldName
+ * The name of the field to be set in the setter method,
+ * corresponding to the template variable for ${field}.
+ * @param paramName
+ * The name of the parameter passed to the setter method,
+ * corresponding to the template variable for $(param).
+ * @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.
+ * @since 3.0
+ */
+ public static String getSetterMethodBodyContent(ICompilationUnit cu,
+ String declaringTypeName, String methodName, String fieldName,
+ String paramName, String lineDelimiter) throws CoreException {
+ return StubUtility.getSetterMethodBodyContent(cu.getJavaProject(),
+ declaringTypeName, methodName, fieldName, paramName,
+ lineDelimiter);
+ }
+
+ /**
+ * Returns the comment for a getter method using the getter comment
+ * template. null
is returned if the template is empty.
+ *
+ * The returned string is unformatted and not indented.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs. The
+ * compilation unit does not need to exist.
+ * @param declaringTypeName
+ * Name of the type to which the method belongs. For inner types
+ * the name must be qualified and include the outer types names
+ * (dot separated). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @param methodName
+ * Name of the method.
+ * @param fieldName
+ * Name of the field to get.
+ * @param fieldType
+ * The type of the field to get.
+ * @param bareFieldName
+ * The field name without prefix or suffix.
+ * @param lineDelimiter
+ * The line delimiter to be used.
+ * @return Returns the generated getter comment or null
if
+ * the code template is empty. The returned content is not indented.
+ * @throws CoreException
+ * Thrown when the evaluation of the code template fails.
+ * @since 3.0
+ */
+ public static String getGetterComment(ICompilationUnit cu,
+ String declaringTypeName, String methodName, String fieldName,
+ String fieldType, String bareFieldName, String lineDelimiter)
+ throws CoreException {
+ return StubUtility.getGetterComment(cu, declaringTypeName, methodName,
+ fieldName, fieldType, bareFieldName, lineDelimiter);
+ }
+
+ /**
+ * Returns the comment for a setter method using the setter method body
+ * template. null
is returned if the template is empty.
+ *
+ * The returned string is unformatted and not indented.
+ *
+ * @param cu
+ * The compilation unit to which the method belongs. The
+ * compilation unit does not need to exist.
+ * @param declaringTypeName
+ * Name of the type to which the method belongs. For inner types
+ * the name must be qualified and include the outer types names
+ * (dot separated). See
+ * {@link net.sourceforge.phpdt.core.IType#getTypeQualifiedName(char)}.
+ * @param methodName
+ * Name of the method.
+ * @param fieldName
+ * Name of the field that is set.
+ * @param fieldType
+ * The type of the field that is to set.
+ * @param paramName
+ * The name of the parameter that used to set.
+ * @param bareFieldName
+ * The field name without prefix or suffix.
+ * @param lineDelimiter
+ * The line delimiter to be used.
+ * @return Returns the generated setter comment or null
if
+ * the code template is empty. The returned comment is not indented.
+ * @throws CoreException
+ * Thrown when the evaluation of the code template fails.
+ * @since 3.0
+ */
+ public static String getSetterComment(ICompilationUnit cu,
+ String declaringTypeName, String methodName, String fieldName,
+ String fieldType, String paramName, String bareFieldName,
+ String lineDelimiter) throws CoreException {
+ return StubUtility.getSetterComment(cu, declaringTypeName, methodName,
+ fieldName, fieldType, paramName, bareFieldName, lineDelimiter);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IContextMenuConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IContextMenuConstants.java
new file mode 100644
index 0000000..40fcd3c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IContextMenuConstants.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import org.eclipse.ui.IWorkbenchActionConstants;
+
+/**
+ * Constants for menu groups used in context menus for Java views and editors.
+ *
+ * This interface declares constants only; it is not intended to be implemented.
+ *
+ */
+public interface IContextMenuConstants {
+
+ /**
+ * Type hierarchy view part: pop-up menu target ID for type hierarchy viewer
+ * (value
+ * "net.sourceforge.phpdt.ui.TypeHierarchy.typehierarchy"
).
+ *
+ * @since 2.0
+ */
+ public static final String TARGET_ID_HIERARCHY_VIEW = JavaUI.ID_TYPE_HIERARCHY
+ + ".typehierarchy"; //$NON-NLS-1$
+
+ /**
+ * Type hierarchy view part: pop-up menu target ID for supertype hierarchy
+ * viewer (value
+ * "net.sourceforge.phpdt.ui.TypeHierarchy.supertypes"
).
+ *
+ * @since 2.0
+ */
+ public static final String TARGET_ID_SUPERTYPES_VIEW = JavaUI.ID_TYPE_HIERARCHY
+ + ".supertypes"; //$NON-NLS-1$
+
+ /**
+ * Type hierarchy view part: Pop-up menu target ID for the subtype hierarchy
+ * viewer (value
+ * "net.sourceforge.phpdt.ui.TypeHierarchy.subtypes"
).
+ *
+ * @since 2.0
+ */
+ public static final String TARGET_ID_SUBTYPES_VIEW = JavaUI.ID_TYPE_HIERARCHY
+ + ".subtypes"; //$NON-NLS-1$
+
+ /**
+ * Type hierarchy view part: pop-up menu target ID for the meber viewer
+ * (value "net.sourceforge.phpdt.ui.TypeHierarchy.members"
).
+ *
+ * @since 2.0
+ */
+ public static final String TARGET_ID_MEMBERS_VIEW = JavaUI.ID_TYPE_HIERARCHY
+ + ".members"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for goto actions (value
+ * "group.open"
).
+ *
+ * Examples for open actions are:
+ *
+ * - Go Into
+ * - Go To
+ *
+ *
+ */
+ public static final String GROUP_GOTO = "group.goto"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for open actions (value
+ * "group.open"
).
+ *
+ * Examples for open actions are:
+ *
+ * - Open To
+ * - Open With
+ *
+ *
+ */
+ public static final String GROUP_OPEN = "group.open"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for show actions (value
+ * "group.show"
).
+ *
+ * Examples for show actions are:
+ *
+ * - Show in Navigator
+ * - Show in Type Hierarchy
+ *
+ *
+ */
+ public static final String GROUP_SHOW = "group.show"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for new actions (value
+ * "group.new"
).
+ *
+ * Examples for new actions are:
+ *
+ * - Create new class
+ * - Create new interface
+ *
+ *
+ */
+ public static final String GROUP_NEW = "group.new"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for build actions (value
+ * "group.build"
).
+ */
+ public static final String GROUP_BUILD = "group.build"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for reorganize actions (value
+ * "group.reorganize"
).
+ */
+ public static final String GROUP_REORGANIZE = IWorkbenchActionConstants.GROUP_REORGANIZE;
+
+ /**
+ * Pop-up menu: name of group for code generation actions ( value
+ * "group.generate"
).
+ */
+ public static final String GROUP_GENERATE = "group.generate"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for source actions. This is an alias for
+ * GROUP_GENERATE
to be more consistent with main menu bar
+ * structure.
+ *
+ * @since 2.0
+ */
+ public static final String GROUP_SOURCE = GROUP_GENERATE;
+
+ /**
+ * Pop-up menu: name of group for search actions (value
+ * "group.search"
).
+ */
+ public static final String GROUP_SEARCH = "group.search"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for additional actions (value
+ * "additions"
).
+ */
+ public static final String GROUP_ADDITIONS = "additions"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for viewer setup actions (value
+ * "group.viewerSetup"
).
+ */
+ public static final String GROUP_VIEWER_SETUP = "group.viewerSetup"; //$NON-NLS-1$
+
+ /**
+ * Pop-up menu: name of group for properties actions (value
+ * "group.properties"
).
+ */
+ public static final String GROUP_PROPERTIES = "group.properties"; //$NON-NLS-1$
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IJavaElementSearchConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IJavaElementSearchConstants.java
new file mode 100644
index 0000000..699d33e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IJavaElementSearchConstants.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+/**
+ * Search scope constants for Java selection dialogs.
+ *
+ * This interface declares constants only; it is not intended to be implemented.
+ *
+ *
+ * @see JavaUI
+ */
+public interface IJavaElementSearchConstants {
+
+ /**
+ * Search scope constant (bit mask) indicating that classes should be
+ * considered. Used when opening certain kinds of selection dialogs.
+ */
+ public static final int CONSIDER_CLASSES = 1 << 1;
+
+ /**
+ * Search scope constant (bit mask) indicating that interfaces should be
+ * considered. Used when opening certain kinds of selection dialogs.
+ */
+ public static final int CONSIDER_INTERFACES = 1 << 2;
+
+ /**
+ * Search scope constant (bit mask) indicating that both classes and
+ * interfaces should be considered. Equivalent to
+ * CONSIDER_CLASSES | CONSIDER_INTERFACES
.
+ */
+ public static final int CONSIDER_TYPES = CONSIDER_CLASSES
+ | CONSIDER_INTERFACES;
+
+ /**
+ * Search scope constant (bit mask) indicating that binaries should be
+ * considered. Used when opening certain kinds of selection dialogs.
+ */
+ public static final int CONSIDER_BINARIES = 1 << 3;
+
+ /**
+ * Search scope constant (bit mask) indicating that external JARs should be
+ * considered. Used when opening certain kinds of selection dialogs.
+ */
+ public static final int CONSIDER_EXTERNAL_JARS = 1 << 4;
+
+ /**
+ * Search scope constant (bit mask) indicating that required projects should
+ * be considered. Used when opening certain kinds of selection dialogs.
+ *
+ * @since 2.0
+ */
+ public static final int CONSIDER_REQUIRED_PROJECTS = 1 << 5;
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IPackagesViewPart.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IPackagesViewPart.java
new file mode 100644
index 0000000..5bb16f4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IPackagesViewPart.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.IViewPart;
+
+/**
+ * The standard Packages view presents a Java-centric view of the workspace.
+ * Within Java projects, the resource hierarchy is organized into Java packages
+ * as described by the project's classpath. Note that this view shows both Java
+ * elements and ordinary resources.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see JavaUI#ID_PACKAGES
+ */
+public interface IPackagesViewPart extends IViewPart {
+ /**
+ * Selects and reveals the given element in this packages view. The tree
+ * will be expanded as needed to show the element.
+ *
+ * @param element
+ * the element to be revealed
+ */
+ void selectAndReveal(Object element);
+
+ /**
+ * Returns the TreeViewer shown in the Packages view.
+ *
+ * @return the tree viewer used in the Packages view
+ *
+ * @since 2.0
+ */
+ TreeViewer getTreeViewer();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/ITypeHierarchyViewPart.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/ITypeHierarchyViewPart.java
new file mode 100644
index 0000000..950238d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/ITypeHierarchyViewPart.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IType;
+
+import org.eclipse.ui.IViewPart;
+
+/**
+ * The standard type hierarchy view presents a type hierarchy for a given input
+ * class or interface. Visually, this view consists of a pair of viewers, one
+ * showing the type hierarchy, the other showing the members of the type
+ * selected in the first.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see JavaUI#ID_TYPE_HIERARCHY
+ */
+public interface ITypeHierarchyViewPart extends IViewPart {
+
+ /**
+ * Sets the input element of this type hierarchy view to a type.
+ *
+ * @param type
+ * the input element of this type hierarchy view, or
+ * null
to clear any input element
+ * @deprecated use setInputElement instead
+ */
+ public void setInput(IType type);
+
+ /**
+ * Sets the input element of this type hierarchy view. The following input
+ * types are possible IMember
(types, methods, fields..),
+ * IPackageFragment
, IPackageFragmentRoot
and
+ * IJavaProject
.
+ *
+ * @param element
+ * the input element of this type hierarchy view, or
+ * null
to clear any input
+ *
+ * @since 2.0
+ */
+ public void setInputElement(IJavaElement element);
+
+ /**
+ * Returns the input element of this type hierarchy view.
+ *
+ * @return the input element, or null
if no input element is
+ * set
+ * @see #setInput(IType)
+ * @deprecated use getInputElement instead
+ */
+ public IType getInput();
+
+ /**
+ * Returns the input element of this type hierarchy view.
+ *
+ * @return the input element, or null
if no input element is
+ * set
+ * @see #setInputElement(IJavaElement)
+ *
+ * @since 2.0
+ */
+ public IJavaElement getInputElement();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyManager.java
new file mode 100644
index 0000000..e0be2c6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyManager.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.ui.IEditorInput;
+
+/**
+ * Interface for accessing working copies of ICompilationUnit
+ * objects. The original compilation unit is only given indirectly by means of
+ * an IEditorInput
. The life cycle is as follows:
+ *
+ * -
connect
creates and remembers a working copy of the
+ * compilation unit which is encoded in the given editor input
+ * -
getWorkingCopy
returns the working copy remembered on
+ * connect
+ * -
disconnect
destroys the working copy remembered on
+ * connect
+ *
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see JavaUI#getWorkingCopyManager
+ */
+public interface IWorkingCopyManager {
+
+ /**
+ * Connects the given editor input to this manager. After calling this
+ * method, a working copy will be available for the compilation unit encoded
+ * in the given editor input (does nothing if there is no encoded
+ * compilation unit).
+ *
+ * @param input
+ * the editor input
+ * @exception CoreException
+ * if the working copy cannot be created for the compilation
+ * unit
+ */
+ void connect(IEditorInput input) throws CoreException;
+
+ /**
+ * Disconnects the given editor input from this manager. After calling this
+ * method, a working copy for the compilation unit encoded in the given
+ * editor input will no longer be available. Does nothing if there is no
+ * encoded compilation unit, or if there is no remembered working copy for
+ * the compilation unit.
+ *
+ * @param input
+ * the editor input
+ */
+ void disconnect(IEditorInput input);
+
+ /**
+ * Returns the working copy remembered for the compilation unit encoded in
+ * the given editor input.
+ *
+ * @param input
+ * the editor input
+ * @return the working copy of the compilation unit, or null
+ * if the input does not encode an editor input, or if there is no
+ * remembered working copy for this compilation unit
+ */
+ ICompilationUnit getWorkingCopy(IEditorInput input);
+
+ /**
+ * Shuts down this working copy manager. All working copies still remembered
+ * by this manager are destroyed.
+ */
+ void shutdown();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyManagerExtension.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyManagerExtension.java
new file mode 100644
index 0000000..1e354a9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyManagerExtension.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.ui.IEditorInput;
+
+/**
+ * Extension interface for IWorkingCopyManager
.
+ *
+ * @since 2.1
+ */
+public interface IWorkingCopyManagerExtension {
+
+ /**
+ * Sets the given working copy for the given editor input. If the given
+ * editor input is not connected to this working copy manager, this call has
+ * no effect.
+ *
+ * This working copy manager does not assume the ownership of this working
+ * copy, i.e., the given working copy is not automatically be freed when
+ * this manager is shut down.
+ *
+ * @param input
+ * the editor input
+ * @param workingCopy
+ * the working copy
+ */
+ void setWorkingCopy(IEditorInput input, ICompilationUnit workingCopy);
+
+ /**
+ * Removes the working copy set for the given editor input. If there is no
+ * working copy set for this input or this input is not connected to this
+ * working copy manager, this call has no effect.
+ *
+ * @param input
+ * the editor input
+ */
+ void removeWorkingCopy(IEditorInput input);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyProvider.java
new file mode 100644
index 0000000..7f0a3e0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/IWorkingCopyProvider.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+/**
+ * Interface used for Java element content providers to indicate that the
+ * content provider can return working copy elements for members below
+ * compilation units.
+ *
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see net.sourceforge.phpdt.ui.StandardJavaElementContentProvider
+ * @see net.sourceforge.phpdt.core.IWorkingCopy
+ *
+ * @since 2.0
+ */
+public interface IWorkingCopyProvider {
+
+ /**
+ * Returns true
if the content provider returns working copy
+ * elements; otherwise false
is returned.
+ *
+ * @return whether working copy elements are provided.
+ */
+ public boolean providesWorkingCopies();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementImageDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementImageDescriptor.java
new file mode 100644
index 0000000..e008eff
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementImageDescriptor.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * A JavaImageDescriptor consists of a base image and several adornments. The
+ * adornments are computed according to the flags either passed during creation
+ * or set via the method setAdornments
.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class JavaElementImageDescriptor extends CompositeImageDescriptor {
+
+ /** Flag to render the abstract adornment */
+ public final static int ABSTRACT = 0x001;
+
+ /** Flag to render the final adornment */
+ public final static int FINAL = 0x002;
+
+ /** Flag to render the synchronized adornment */
+ public final static int SYNCHRONIZED = 0x004;
+
+ /** Flag to render the static adornment */
+ public final static int STATIC = 0x008;
+
+ /** Flag to render the runnable adornment */
+ public final static int RUNNABLE = 0x010;
+
+ /** Flag to render the waring adornment */
+ public final static int WARNING = 0x020;
+
+ /** Flag to render the error adornment */
+ public final static int ERROR = 0x040;
+
+ /** Flag to render the 'override' adornment */
+ public final static int OVERRIDES = 0x080;
+
+ /** Flag to render the 'implements' adornment */
+ public final static int IMPLEMENTS = 0x100;
+
+ /** Flag to render the 'constructor' adornment */
+ public final static int CONSTRUCTOR = 0x200;
+
+ private ImageDescriptor fBaseImage;
+
+ private int fFlags;
+
+ private Point fSize;
+
+ /**
+ * Creates a new JavaElementImageDescriptor.
+ *
+ * @param baseImage
+ * an image descriptor used as the base image
+ * @param flags
+ * flags indicating which adornments are to be rendered. See
+ * setAdornments
for valid values.
+ * @param size
+ * the size of the resulting image
+ * @see #setAdornments(int)
+ */
+ public JavaElementImageDescriptor(ImageDescriptor baseImage, int flags,
+ Point size) {
+ fBaseImage = baseImage;
+ Assert.isNotNull(fBaseImage);
+ fFlags = flags;
+ Assert.isTrue(fFlags >= 0);
+ fSize = size;
+ Assert.isNotNull(fSize);
+ }
+
+ /**
+ * Sets the descriptors adornments. Valid values are: ABSTRACT
,
+ * FINAL
, SYNCHRONIZED
,
STATIC,
+ *
RUNNABLE,
WARNING,
ERROR,
+ *
OVERRIDDES, IMPLEMENTS
,
+ * CONSTRUCTOR
, or any combination of those.
+ *
+ * @param adornments
+ * the image descritpors adornments
+ */
+ public void setAdornments(int adornments) {
+ Assert.isTrue(adornments >= 0);
+ fFlags = adornments;
+ }
+
+ /**
+ * Returns the current adornments.
+ *
+ * @return the current adornments
+ */
+ public int getAdronments() {
+ return fFlags;
+ }
+
+ /**
+ * Sets the size of the image created by calling createImage()
.
+ *
+ * @param size
+ * the size of the image returned from calling
+ * createImage()
+ * @see ImageDescriptor#createImage()
+ */
+ public void setImageSize(Point size) {
+ Assert.isNotNull(size);
+ Assert.isTrue(size.x >= 0 && size.y >= 0);
+ fSize = size;
+ }
+
+ /**
+ * Returns the size of the image created by calling
+ * createImage()
.
+ *
+ * @return the size of the image created by calling
+ * createImage()
+ * @see ImageDescriptor#createImage()
+ */
+ public Point getImageSize() {
+ return new Point(fSize.x, fSize.y);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in CompositeImageDescriptor
+ */
+ protected Point getSize() {
+ return fSize;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Object.
+ */
+ public boolean equals(Object object) {
+ if (object == null
+ || !JavaElementImageDescriptor.class.equals(object.getClass()))
+ return false;
+
+ JavaElementImageDescriptor other = (JavaElementImageDescriptor) object;
+ return (fBaseImage.equals(other.fBaseImage) && fFlags == other.fFlags && fSize
+ .equals(other.fSize));
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Object.
+ */
+ public int hashCode() {
+ return fBaseImage.hashCode() | fFlags | fSize.hashCode();
+ }
+
+ /*
+ * (non-Javadoc) Method declared in CompositeImageDescriptor
+ */
+ protected void drawCompositeImage(int width, int height) {
+ ImageData bg;
+ if ((bg = fBaseImage.getImageData()) == null)
+ bg = DEFAULT_IMAGE_DATA;
+
+ drawImage(bg, 0, 0);
+ drawTopRight();
+ drawBottomRight();
+ drawBottomLeft();
+ }
+
+ private void drawTopRight() {
+ int x = getSize().x;
+ ImageData data = null;
+ if ((fFlags & ABSTRACT) != 0) {
+ data = PHPUiImages.DESC_OVR_ABSTRACT.getImageData();
+ x -= data.width;
+ drawImage(data, x, 0);
+ }
+ if ((fFlags & CONSTRUCTOR) != 0) {
+ data = PHPUiImages.DESC_OVR_CONSTRUCTOR.getImageData();
+ x -= data.width;
+ drawImage(data, x, 0);
+ }
+ if ((fFlags & FINAL) != 0) {
+ data = PHPUiImages.DESC_OVR_FINAL.getImageData();
+ x -= data.width;
+ drawImage(data, x, 0);
+ }
+ if ((fFlags & STATIC) != 0) {
+ data = PHPUiImages.DESC_OVR_STATIC.getImageData();
+ x -= data.width;
+ drawImage(data, x, 0);
+ }
+ }
+
+ private void drawBottomRight() {
+ Point size = getSize();
+ int x = size.x;
+ ImageData data = null;
+ if ((fFlags & OVERRIDES) != 0) {
+ data = PHPUiImages.DESC_OVR_OVERRIDES.getImageData();
+ x -= data.width;
+ drawImage(data, x, size.y - data.height);
+ }
+ if ((fFlags & IMPLEMENTS) != 0) {
+ data = PHPUiImages.DESC_OVR_IMPLEMENTS.getImageData();
+ x -= data.width;
+ drawImage(data, x, size.y - data.height);
+ }
+ if ((fFlags & SYNCHRONIZED) != 0) {
+ data = PHPUiImages.DESC_OVR_SYNCH.getImageData();
+ x -= data.width;
+ drawImage(data, x, size.y - data.height);
+ }
+ if ((fFlags & RUNNABLE) != 0) {
+ data = PHPUiImages.DESC_OVR_RUN.getImageData();
+ x -= data.width;
+ drawImage(data, x, size.y - data.height);
+ }
+ }
+
+ private void drawBottomLeft() {
+ Point size = getSize();
+ int x = 0;
+ ImageData data = null;
+ if ((fFlags & ERROR) != 0) {
+ data = PHPUiImages.DESC_OVR_ERROR.getImageData();
+ drawImage(data, x, size.y - data.height);
+ x += data.width;
+ }
+ if ((fFlags & WARNING) != 0) {
+ data = PHPUiImages.DESC_OVR_WARNING.getImageData();
+ drawImage(data, x, size.y - data.height);
+ x += data.width;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementLabelProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementLabelProvider.java
new file mode 100644
index 0000000..44eb464
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementLabelProvider.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementImageProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels;
+import net.sourceforge.phpdt.internal.ui.viewsupport.StorageLabelProvider;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Standard label provider for Java elements. Use this class when you want to
+ * present the Java elements in a viewer.
+ *
+ * The implementation also handles non-Java elements by forwarding the requests
+ * to the IWorkbenchAdapter
of the element.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ */
+public class JavaElementLabelProvider extends LabelProvider {
+
+ /**
+ * Flag (bit mask) indicating that methods labels include the method return
+ * type. (appended)
+ */
+ public final static int SHOW_RETURN_TYPE = 0x001;
+
+ /**
+ * Flag (bit mask) indicating that method label include method parameter
+ * types.
+ */
+ public final static int SHOW_PARAMETERS = 0x002;
+
+ /**
+ * Flag (bit mask) indicating that the label of a member should include the
+ * container. For example, include the name of the type enclosing a field.
+ *
+ * @deprecated Use SHOW_QUALIFIED or SHOW_ROOT instead
+ */
+ public final static int SHOW_CONTAINER = 0x004;
+
+ /**
+ * Flag (bit mask) indicating that the label of a type should be fully
+ * qualified. For example, include the fully qualified name of the type
+ * enclosing a type.
+ *
+ * @deprecated Use SHOW_QUALIFIED instead
+ */
+ public final static int SHOW_CONTAINER_QUALIFICATION = 0x008;
+
+ /**
+ * Flag (bit mask) indicating that the label should include overlay icons
+ * for element type and modifiers.
+ */
+ public final static int SHOW_OVERLAY_ICONS = 0x010;
+
+ /**
+ * Flag (bit mask) indicating thata field label should include the declared
+ * type.
+ */
+ public final static int SHOW_TYPE = 0x020;
+
+ /**
+ * Flag (bit mask) indicating that the label should include the name of the
+ * package fragment root (appended).
+ */
+ public final static int SHOW_ROOT = 0x040;
+
+ /**
+ * Flag (bit mask) indicating that the label qualification of a type should
+ * be shown after the name.
+ *
+ * @deprecated SHOW_POST_QUALIFIED instead
+ */
+ public final static int SHOW_POSTIFIX_QUALIFICATION = 0x080;
+
+ /**
+ * Flag (bit mask) indicating that the label should show the icons with no
+ * space reserved for overlays.
+ */
+ public final static int SHOW_SMALL_ICONS = 0x100;
+
+ /**
+ * Flag (bit mask) indicating that the packagefragment roots from variables
+ * should be rendered with the variable in the name
+ */
+ public final static int SHOW_VARIABLE = 0x200;
+
+ /**
+ * Flag (bit mask) indicating that Complation Units, Class Files, Types,
+ * Declarations and Members should be rendered qualified. Examples:
+ * java.lang.String, java.util.Vector.size()
+ *
+ * @since 2.0
+ */
+ public final static int SHOW_QUALIFIED = 0x400;
+
+ /**
+ * Flag (bit mask) indicating that Complation Units, Class Files, Types,
+ * Declarations and Members should be rendered qualified. The qualifcation
+ * is appended Examples: String - java.lang, size() - java.util.Vector
+ *
+ * @since 2.0
+ */
+ public final static int SHOW_POST_QUALIFIED = 0x800;
+
+ /**
+ * Constant (value 0
) indicating that the label should show
+ * the basic images only.
+ */
+ public final static int SHOW_BASICS = 0x000;
+
+ /**
+ * Constant indicating the default label rendering. Currently the default is
+ * equivalent to SHOW_PARAMETERS | SHOW_OVERLAY_ICONS
.
+ */
+ public final static int SHOW_DEFAULT = new Integer(SHOW_PARAMETERS
+ | SHOW_OVERLAY_ICONS).intValue();
+
+ private JavaElementImageProvider fImageLabelProvider;
+
+ private StorageLabelProvider fStorageLabelProvider;
+
+ private int fFlags;
+
+ private int fImageFlags;
+
+ private int fTextFlags;
+
+ /**
+ * Creates a new label provider with SHOW_DEFAULT
flag.
+ *
+ * @see #SHOW_DEFAULT
+ * @since 2.0
+ */
+ public JavaElementLabelProvider() {
+ this(SHOW_DEFAULT);
+ }
+
+ /**
+ * Creates a new label provider.
+ *
+ * @param flags
+ * the initial options; a bitwise OR of SHOW_*
+ * constants
+ */
+ public JavaElementLabelProvider(int flags) {
+ fImageLabelProvider = new JavaElementImageProvider();
+ fStorageLabelProvider = new StorageLabelProvider();
+ fFlags = flags;
+ updateImageProviderFlags();
+ updateTextProviderFlags();
+ }
+
+ private boolean getFlag(int flag) {
+ return (fFlags & flag) != 0;
+ }
+
+ /**
+ * Turns on the rendering options specified in the given flags.
+ *
+ * @param flags
+ * the options; a bitwise OR of SHOW_*
constants
+ */
+ public void turnOn(int flags) {
+ fFlags |= flags;
+ updateImageProviderFlags();
+ updateTextProviderFlags();
+ }
+
+ /**
+ * Turns off the rendering options specified in the given flags.
+ *
+ * @param flags
+ * the initial options; a bitwise OR of SHOW_*
+ * constants
+ */
+ public void turnOff(int flags) {
+ fFlags &= (~flags);
+ updateImageProviderFlags();
+ updateTextProviderFlags();
+ }
+
+ private void updateImageProviderFlags() {
+ fImageFlags = 0;
+ if (getFlag(SHOW_OVERLAY_ICONS)) {
+ fImageFlags |= JavaElementImageProvider.OVERLAY_ICONS;
+ }
+ if (getFlag(SHOW_SMALL_ICONS)) {
+ fImageFlags |= JavaElementImageProvider.SMALL_ICONS;
+ }
+ }
+
+ private void updateTextProviderFlags() {
+ fTextFlags = 0;
+ if (getFlag(SHOW_RETURN_TYPE)) {
+ fTextFlags |= JavaElementLabels.M_APP_RETURNTYPE;
+ }
+ if (getFlag(SHOW_PARAMETERS)) {
+ fTextFlags |= JavaElementLabels.M_PARAMETER_TYPES;
+ }
+ if (getFlag(SHOW_CONTAINER)) {
+ fTextFlags |= JavaElementLabels.P_POST_QUALIFIED
+ | JavaElementLabels.T_POST_QUALIFIED
+ | JavaElementLabels.CF_POST_QUALIFIED
+ | JavaElementLabels.CU_POST_QUALIFIED
+ | JavaElementLabels.M_POST_QUALIFIED
+ | JavaElementLabels.F_POST_QUALIFIED;
+ }
+ if (getFlag(SHOW_POSTIFIX_QUALIFICATION)) {
+ fTextFlags |= (JavaElementLabels.T_POST_QUALIFIED
+ | JavaElementLabels.CF_POST_QUALIFIED | JavaElementLabels.CU_POST_QUALIFIED);
+ } else if (getFlag(SHOW_CONTAINER_QUALIFICATION)) {
+ fTextFlags |= (JavaElementLabels.T_FULLY_QUALIFIED
+ | JavaElementLabels.CF_QUALIFIED | JavaElementLabels.CU_QUALIFIED);
+ }
+ if (getFlag(SHOW_TYPE)) {
+ fTextFlags |= JavaElementLabels.F_APP_TYPE_SIGNATURE;
+ }
+ if (getFlag(SHOW_ROOT)) {
+ fTextFlags |= JavaElementLabels.APPEND_ROOT_PATH;
+ }
+ if (getFlag(SHOW_VARIABLE)) {
+ fTextFlags |= JavaElementLabels.ROOT_VARIABLE;
+ }
+ if (getFlag(SHOW_QUALIFIED)) {
+ fTextFlags |= (JavaElementLabels.F_FULLY_QUALIFIED
+ | JavaElementLabels.M_FULLY_QUALIFIED
+ | JavaElementLabels.I_FULLY_QUALIFIED
+ | JavaElementLabels.T_FULLY_QUALIFIED
+ | JavaElementLabels.D_QUALIFIED
+ | JavaElementLabels.CF_QUALIFIED | JavaElementLabels.CU_QUALIFIED);
+ }
+ if (getFlag(SHOW_POST_QUALIFIED)) {
+ fTextFlags |= (JavaElementLabels.F_POST_QUALIFIED
+ | JavaElementLabels.M_POST_QUALIFIED
+ | JavaElementLabels.I_POST_QUALIFIED
+ | JavaElementLabels.T_POST_QUALIFIED
+ | JavaElementLabels.D_POST_QUALIFIED
+ | JavaElementLabels.CF_POST_QUALIFIED | JavaElementLabels.CU_POST_QUALIFIED);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelProvider#getImage
+ */
+ public Image getImage(Object element) {
+ Image result = fImageLabelProvider.getImageLabel(element, fImageFlags);
+ if (result != null) {
+ return result;
+ }
+
+ if (element instanceof IStorage)
+ return fStorageLabelProvider.getImage(element);
+
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelProvider#getText
+ */
+ public String getText(Object element) {
+ String text = JavaElementLabels.getTextLabel(element, fTextFlags);
+ if (text.length() > 0) {
+ return text;
+ }
+
+ if (element instanceof IStorage)
+ return fStorageLabelProvider.getText(element);
+
+ return text;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#dispose
+ */
+ public void dispose() {
+ fStorageLabelProvider.dispose();
+ fImageLabelProvider.dispose();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementSorter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementSorter.java
new file mode 100644
index 0000000..2d66b7d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaElementSorter.java
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import java.text.Collator;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.core.IField;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.Signature;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.corext.util.JdtFlags;
+import net.sourceforge.phpdt.internal.ui.preferences.MembersOrderPreferenceCache;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.ContentViewer;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * Sorter for Java elements. Ordered by element category, then by element name.
+ * Package fragment roots are sorted as ordered on the classpath.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class JavaElementSorter extends ViewerSorter {
+
+ private static final int PROJECTS = 1;
+
+ private static final int PACKAGEFRAGMENTROOTS = 2;
+
+ private static final int PACKAGEFRAGMENT = 3;
+
+ private static final int COMPILATIONUNITS = 4;
+
+ private static final int CLASSFILES = 5;
+
+ private static final int RESOURCEFOLDERS = 7;
+
+ private static final int RESOURCES = 8;
+
+ private static final int STORAGE = 9;
+
+ private static final int PACKAGE_DECL = 10;
+
+ private static final int IMPORT_CONTAINER = 11;
+
+ private static final int IMPORT_DECLARATION = 12;
+
+ // Includes all categories ordered using the OutlineSortOrderPage:
+ // types, initializers, methods & fields
+ private static final int MEMBERSOFFSET = 15;
+
+ private static final int JAVAELEMENTS = 50;
+
+ private static final int OTHERS = 51;
+
+ private MembersOrderPreferenceCache fMemberOrderCache;
+
+ /**
+ * Constructor.
+ */
+ public JavaElementSorter() {
+ super(null); // delay initialization of collator
+ fMemberOrderCache = WebUI.getDefault()
+ .getMemberOrderPreferenceCache();
+ }
+
+ /**
+ * @deprecated Bug 22518. Method never used: does not override
+ * ViewerSorter#isSorterProperty(Object, String). Method could
+ * be removed, but kept for API compatibility.
+ */
+ public boolean isSorterProperty(Object element, Object property) {
+ return true;
+ }
+
+ /*
+ * @see ViewerSorter#category
+ */
+ public int category(Object element) {
+ if (element instanceof IJavaElement) {
+ try {
+ IJavaElement je = (IJavaElement) element;
+
+ switch (je.getElementType()) {
+ case IJavaElement.METHOD: {
+ IMethod method = (IMethod) je;
+ if (method.isConstructor()) {
+ return getMemberCategory(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX);
+ }
+ int flags = method.getFlags();
+ if (Flags.isStatic(flags))
+ return getMemberCategory(MembersOrderPreferenceCache.STATIC_METHODS_INDEX);
+ else
+ return getMemberCategory(MembersOrderPreferenceCache.METHOD_INDEX);
+ }
+ case IJavaElement.FIELD: {
+ int flags = ((IField) je).getFlags();
+ if (Flags.isStatic(flags))
+ return getMemberCategory(MembersOrderPreferenceCache.STATIC_FIELDS_INDEX);
+ else
+ return getMemberCategory(MembersOrderPreferenceCache.FIELDS_INDEX);
+ }
+ // case IJavaElement.INITIALIZER :
+ // {
+ // int flags= ((IInitializer) je).getFlags();
+ // if (Flags.isStatic(flags))
+ // return
+ // getMemberCategory(MembersOrderPreferenceCache.STATIC_INIT_INDEX);
+ // else
+ // return
+ // getMemberCategory(MembersOrderPreferenceCache.INIT_INDEX);
+ // }
+ case IJavaElement.TYPE:
+ return getMemberCategory(MembersOrderPreferenceCache.TYPE_INDEX);
+ case IJavaElement.PACKAGE_DECLARATION:
+ return PACKAGE_DECL;
+ case IJavaElement.IMPORT_CONTAINER:
+ return IMPORT_CONTAINER;
+ case IJavaElement.IMPORT_DECLARATION:
+ return IMPORT_DECLARATION;
+ case IJavaElement.PACKAGE_FRAGMENT:
+ IPackageFragment pack = (IPackageFragment) je;
+ if (pack.getParent().getResource() instanceof IProject) {
+ return PACKAGEFRAGMENTROOTS;
+ }
+ return PACKAGEFRAGMENT;
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+ return PACKAGEFRAGMENTROOTS;
+ case IJavaElement.JAVA_PROJECT:
+ return PROJECTS;
+ case IJavaElement.CLASS_FILE:
+ return CLASSFILES;
+ case IJavaElement.COMPILATION_UNIT:
+ return COMPILATIONUNITS;
+ }
+
+ } catch (JavaModelException e) {
+ if (!e.isDoesNotExist())
+ PHPeclipsePlugin.log(e);
+ }
+ return JAVAELEMENTS;
+ } else if (element instanceof IFile) {
+ return RESOURCES;
+ } else if (element instanceof IProject) {
+ return PROJECTS;
+ } else if (element instanceof IContainer) {
+ return RESOURCEFOLDERS;
+ } else if (element instanceof IStorage) {
+ return STORAGE;
+ }
+ // else if (element instanceof ClassPathContainer) {
+ // return PACKAGEFRAGMENTROOTS;
+ // }
+ return OTHERS;
+ }
+
+ private int getMemberCategory(int kind) {
+ int offset = fMemberOrderCache.getCategoryIndex(kind);
+ return offset + MEMBERSOFFSET;
+ }
+
+ /*
+ * @see ViewerSorter#compare
+ */
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ int cat1 = category(e1);
+ int cat2 = category(e2);
+
+ if (cat1 != cat2)
+ return cat1 - cat2;
+
+ if (cat1 == PROJECTS) {
+ IWorkbenchAdapter a1 = (IWorkbenchAdapter) ((IAdaptable) e1)
+ .getAdapter(IWorkbenchAdapter.class);
+ IWorkbenchAdapter a2 = (IWorkbenchAdapter) ((IAdaptable) e2)
+ .getAdapter(IWorkbenchAdapter.class);
+ return getCollator().compare(a1.getLabel(e1), a2.getLabel(e2));
+ }
+
+ if (cat1 == PACKAGEFRAGMENTROOTS) {
+ IPackageFragmentRoot root1 = getPackageFragmentRoot(e1);
+ IPackageFragmentRoot root2 = getPackageFragmentRoot(e2);
+ if (root1 == null) {
+ if (root2 == null) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if (root2 == null) {
+ return -1;
+ }
+ if (!root1.getPath().equals(root2.getPath())) {
+ int p1 = getClassPathIndex(root1);
+ int p2 = getClassPathIndex(root2);
+ if (p1 != p2) {
+ return p1 - p2;
+ }
+ }
+ e1 = root1; // normalize classpath container to root
+ e2 = root2;
+ }
+ // non - java resources are sorted using the label from the viewers
+ // label provider
+ if (cat1 == PROJECTS || cat1 == RESOURCES || cat1 == RESOURCEFOLDERS
+ || cat1 == STORAGE || cat1 == OTHERS) {
+ return compareWithLabelProvider(viewer, e1, e2);
+ }
+
+ if (e1 instanceof IMember) {
+ if (fMemberOrderCache.isSortByVisibility()) {
+ try {
+ int flags1 = JdtFlags.getVisibilityCode((IMember) e1);
+ int flags2 = JdtFlags.getVisibilityCode((IMember) e2);
+ int vis = fMemberOrderCache.getVisibilityIndex(flags1)
+ - fMemberOrderCache.getVisibilityIndex(flags2);
+ if (vis != 0) {
+ return vis;
+ }
+ } catch (JavaModelException ignore) {
+ }
+ }
+ }
+
+ String name1 = ((IJavaElement) e1).getElementName();
+ String name2 = ((IJavaElement) e2).getElementName();
+
+ if (e1 instanceof IType) { // handle anonymous types
+ if (name1.length() == 0) {
+ if (name2.length() == 0) {
+ try {
+ return getCollator().compare(
+ ((IType) e1).getSuperclassName(),
+ ((IType) e2).getSuperclassName());
+ } catch (JavaModelException e) {
+ return 0;
+ }
+ } else {
+ return 1;
+ }
+ } else if (name2.length() == 0) {
+ return -1;
+ }
+ }
+
+ int cmp = getCollator().compare(name1, name2);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ if (e1 instanceof IMethod) {
+ String[] params1 = ((IMethod) e1).getParameterTypes();
+ String[] params2 = ((IMethod) e2).getParameterTypes();
+ int len = Math.min(params1.length, params2.length);
+ for (int i = 0; i < len; i++) {
+ cmp = getCollator().compare(Signature.toString(params1[i]),
+ Signature.toString(params2[i]));
+ if (cmp != 0) {
+ return cmp;
+ }
+ }
+ return params1.length - params2.length;
+ }
+ return 0;
+ }
+
+ private IPackageFragmentRoot getPackageFragmentRoot(Object element) {
+ // if (element instanceof ClassPathContainer) {
+ // // return first package fragment root from the container
+ // ClassPathContainer cp= (ClassPathContainer)element;
+ // Object[] roots= cp.getPackageFragmentRoots();
+ // if (roots.length > 0)
+ // return (IPackageFragmentRoot)roots[0];
+ // // non resolvable - return null
+ // return null;
+ // }
+ return JavaModelUtil.getPackageFragmentRoot((IJavaElement) element);
+ }
+
+ private int compareWithLabelProvider(Viewer viewer, Object e1, Object e2) {
+ if (viewer == null || !(viewer instanceof ContentViewer)) {
+ IBaseLabelProvider prov = ((ContentViewer) viewer)
+ .getLabelProvider();
+ if (prov instanceof ILabelProvider) {
+ ILabelProvider lprov = (ILabelProvider) prov;
+ String name1 = lprov.getText(e1);
+ String name2 = lprov.getText(e2);
+ if (name1 != null && name2 != null) {
+ return getCollator().compare(name1, name2);
+ }
+ }
+ }
+ return 0; // can't compare
+ }
+
+ private int getClassPathIndex(IPackageFragmentRoot root) {
+ try {
+ IPath rootPath = root.getPath();
+ IPackageFragmentRoot[] roots = root.getJavaProject()
+ .getPackageFragmentRoots();
+ for (int i = 0; i < roots.length; i++) {
+ if (roots[i].getPath().equals(rootPath)) {
+ return i;
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+
+ return Integer.MAX_VALUE;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ViewerSorter#getCollator()
+ */
+ public final Collator getCollator() {
+ if (collator == null) {
+ collator = Collator.getInstance();
+ }
+ return collator;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaUI.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaUI.java
new file mode 100644
index 0000000..ae2fecf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/JavaUI.java
@@ -0,0 +1,809 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.core.IBufferFactory;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IWorkingCopy;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.EditorUtility;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.internal.SharedImages;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+
+/**
+ * Central access point for the Java UI plug-in (id
+ * "net.sourceforge.phpdt.ui"
). This class provides static
+ * methods for:
+ *
+ * - creating various kinds of selection dialogs to present a collection of
+ * Java elements to the user and let them make a selection.
+ * - opening a Java editor on a compilation unit.
+ *
+ *
+ * This class provides static methods and fields only; it is not intended to be
+ * instantiated or subclassed by clients.
+ *
+ */
+public final class JavaUI {
+
+ private static ISharedImages fgSharedImages = null;
+
+ private JavaUI() {
+ // prevent instantiation of JavaUI.
+ }
+
+ /**
+ * The id of the Java plugin (value "net.sourceforge.phpdt.ui"
).
+ */
+ // public static final String ID_PLUGIN= "net.sourceforge.phpdt.ui";
+ // //$NON-NLS-1$
+ /**
+ * The id of the Java perspective (value
+ * "net.sourceforge.phpdt.ui.JavaPerspective"
).
+ */
+ public static final String ID_PERSPECTIVE=
+ "net.sourceforge.phpdt.ui.JavaPerspective"; //$NON-NLS-1$
+ /**
+ * The id of the Java hierarchy perspective (value
+ * "net.sourceforge.phpdt.ui.JavaHierarchyPerspective"
).
+ */
+ // public static final String ID_HIERARCHYPERSPECTIVE=
+ // "net.sourceforge.phpdt.ui.JavaHierarchyPerspective"; //$NON-NLS-1$
+ /**
+ * The id of the Java action set (value
+ * "net.sourceforge.phpdt.ui.JavaActionSet"
).
+ */
+ // public static final String ID_ACTION_SET=
+ // "net.sourceforge.phpdt.ui.JavaActionSet"; //$NON-NLS-1$
+ /**
+ * The id of the Java Element Creation action set (value
+ * "net.sourceforge.phpdt.ui.JavaElementCreationActionSet"
).
+ *
+ * @since 2.0
+ */
+ // public static final String ID_ELEMENT_CREATION_ACTION_SET=
+ // "net.sourceforge.phpdt.ui.JavaElementCreationActionSet"; //$NON-NLS-1$
+ /**
+ * The id of the Java Coding action set (value
+ * "net.sourceforge.phpdt.ui.CodingActionSet"
).
+ *
+ * @since 2.0
+ */
+ // public static final String ID_CODING_ACTION_SET=
+ // "net.sourceforge.phpdt.ui.CodingActionSet"; //$NON-NLS-1$
+ /**
+ * The id of the Java action set for open actions (value
+ * "net.sourceforge.phpdt.ui.A_OpenActionSet"
).
+ *
+ * @since 2.0
+ */
+ // public static final String ID_OPEN_ACTION_SET=
+ // "net.sourceforge.phpdt.ui.A_OpenActionSet"; //$NON-NLS-1$
+ /**
+ * The id of the Java Search action set (value
+ * net.sourceforge.phpdt.ui.SearchActionSet"
).
+ *
+ * @since 2.0
+ */
+ // public static final String ID_SEARCH_ACTION_SET=
+ // "net.sourceforge.phpdt.ui.SearchActionSet"; //$NON-NLS-1$
+ /**
+ * The editor part id of the editor that presents Java compilation units
+ * (value "net.sourceforge.phpdt.ui.CompilationUnitEditor"
).
+ */
+ // public static final String ID_CU_EDITOR=
+ // "net.sourceforge.phpdt.ui.PHPUnitEditor"; //$NON-NLS-1$
+ /**
+ * The editor part id of the editor that presents Java binary class files
+ * (value "net.sourceforge.phpdt.ui.ClassFileEditor"
).
+ */
+ // public static final String ID_CF_EDITOR=
+ // "net.sourceforge.phpdt.ui.ClassFileEditor"; //$NON-NLS-1$
+ /**
+ * The editor part id of the code snippet editor (value
+ * "net.sourceforge.phpdt.ui.SnippetEditor"
).
+ */
+ // public static final String ID_SNIPPET_EDITOR=
+ // "net.sourceforge.phpdt.ui.SnippetEditor"; //$NON-NLS-1$
+ /**
+ * The view part id of the Packages view (value
+ * "net.sourceforge.phpdt.ui.PackageExplorer"
).
+ *
+ * When this id is used to access a view part with
+ * IWorkbenchPage.findView
or showView
, the
+ * returned IViewPart
can be safely cast to an
+ * IPackagesViewPart
.
+ *
+ *
+ * @see IPackagesViewPart
+ * @see org.eclipse.ui.IWorkbenchPage#findView(java.lang.String)
+ * @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String)
+ */
+ public static final String ID_PACKAGES = "net.sourceforge.phpdt.ui.PackageExplorer"; //$NON-NLS-1$
+
+ /**
+ * The view part id of the type hierarchy part. (value
+ * "net.sourceforge.phpdt.ui.TypeHierarchy"
).
+ *
+ * When this id is used to access a view part with
+ * IWorkbenchPage.findView
or showView
, the
+ * returned IViewPart
can be safely cast to an
+ * ITypeHierarchyViewPart
.
+ *
+ *
+ * @see ITypeHierarchyViewPart
+ * @see org.eclipse.ui.IWorkbenchPage#findView(java.lang.String)
+ * @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String)
+ */
+ public static final String ID_TYPE_HIERARCHY = "net.sourceforge.phpdt.ui.TypeHierarchy"; //$NON-NLS-1$
+
+ /**
+ * The id of the Java Browsing Perspective (value
+ * "net.sourceforge.phpdt.ui.JavaBrowsingPerspective"
).
+ *
+ * @since 2.0
+ */
+ // public static String ID_BROWSING_PERSPECTIVE=
+ // "net.sourceforge.phpdt.ui.JavaBrowsingPerspective"; //$NON-NLS-1$
+ /**
+ * The view part id of the Java Browsing Projects view (value
+ * "net.sourceforge.phpdt.ui.ProjectsView"
).
+ *
+ * @since 2.0
+ */
+ // public static String ID_PROJECTS_VIEW=
+ // "net.sourceforge.phpdt.ui.ProjectsView"; //$NON-NLS-1$
+ /**
+ * The view part id of the Java Browsing Packages view (value
+ * "net.sourceforge.phpdt.ui.PackagesView"
).
+ *
+ * @since 2.0
+ */
+ // public static String ID_PACKAGES_VIEW=
+ // "net.sourceforge.phpdt.ui.PackagesView"; //$NON-NLS-1$
+ /**
+ * The view part id of the Java Browsing Types view (value
+ * "net.sourceforge.phpdt.ui.TypesView"
).
+ *
+ * @since 2.0
+ */
+ // public static String ID_TYPES_VIEW= "net.sourceforge.phpdt.ui.TypesView";
+ // //$NON-NLS-1$
+ /**
+ * The view part id of the Java Browsing Members view (value
+ * "net.sourceforge.phpdt.ui.MembersView"
).
+ *
+ * @since 2.0
+ */
+ // public static String ID_MEMBERS_VIEW=
+ // "net.sourceforge.phpdt.ui.MembersView"; //$NON-NLS-1$
+ /**
+ * The class org.eclipse.debug.core.model.IProcess allows attaching String
+ * properties to processes. The Java UI contributes a property page for
+ * IProcess that will show the contents of the property with this key. The
+ * intent of this property is to show the command line a process was
+ * launched with.
+ *
+ * @deprecated
+ */
+ // public final static String ATTR_CMDLINE=
+ // "net.sourceforge.phpdt.ui.launcher.cmdLine"; //$NON-NLS-1$
+ /**
+ * Returns the shared images for the Java UI.
+ *
+ * @return the shared images manager
+ */
+ public static ISharedImages getSharedImages() {
+ if (fgSharedImages == null)
+ fgSharedImages = new SharedImages();
+
+ return fgSharedImages;
+ }
+
+ /**
+ * Creates a selection dialog that lists all packages of the given Java
+ * project. The caller is responsible for opening the dialog with
+ * Window.open
, and subsequently extracting the selected
+ * package (of type IPackageFragment
) via
+ * SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param project
+ * the Java project
+ * @param style
+ * flags defining the style of the dialog; the valid flags are:
+ * IJavaElementSearchConstants.CONSIDER_BINARIES
,
+ * indicating that packages from binary package fragment roots
+ * should be included in addition to those from source package
+ * fragment roots;
+ * IJavaElementSearchConstants.CONSIDER_REQUIRED_PROJECTS
,
+ * indicating that packages from required projects should be
+ * included as well.
+ * @param filter
+ * the initial pattern to filter the set of packages. For example
+ * "com" shows all packages starting with "com". The meta
+ * character '?' representing any character and '*' representing
+ * any string are supported. Clients can pass an empty string if
+ * no filtering is required.
+ * @return a new selection dialog
+ * @exception JavaModelException
+ * if the selection dialog could not be opened
+ *
+ * @since 2.0
+ */
+ // public static SelectionDialog createPackageDialog(Shell parent,
+ // IJavaProject project, int style, String filter) throws JavaModelException
+ // {
+ // Assert.isTrue((style | IJavaElementSearchConstants.CONSIDER_BINARIES |
+ // IJavaElementSearchConstants.CONSIDER_REQUIRED_PROJECTS) ==
+ // (IJavaElementSearchConstants.CONSIDER_BINARIES |
+ // IJavaElementSearchConstants.CONSIDER_REQUIRED_PROJECTS));
+ //
+ // IPackageFragmentRoot[] roots= null;
+ // if ((style & IJavaElementSearchConstants.CONSIDER_REQUIRED_PROJECTS) !=
+ // 0) {
+ // roots= project.getAllPackageFragmentRoots();
+ // } else {
+ // roots= project.getPackageFragmentRoots();
+ // }
+ //
+ // List consideredRoots= null;
+ // if ((style & IJavaElementSearchConstants.CONSIDER_BINARIES) != 0) {
+ // consideredRoots= Arrays.asList(roots);
+ // } else {
+ // consideredRoots= new ArrayList(roots.length);
+ // for (int i= 0; i < roots.length; i++) {
+ // IPackageFragmentRoot root= roots[i];
+ // if (root.getKind() != IPackageFragmentRoot.K_BINARY)
+ // consideredRoots.add(root);
+ //
+ // }
+ // }
+ //
+ // int flags= JavaElementLabelProvider.SHOW_DEFAULT;
+ // if (consideredRoots.size() > 1)
+ // flags= flags | JavaElementLabelProvider.SHOW_ROOT;
+ //
+ // List packages= new ArrayList();
+ // Iterator iter= consideredRoots.iterator();
+ // while(iter.hasNext()) {
+ // IPackageFragmentRoot root= (IPackageFragmentRoot)iter.next();
+ // packages.addAll(Arrays.asList(root.getChildren()));
+ // }
+ // ElementListSelectionDialog dialog= new ElementListSelectionDialog(parent,
+ // new JavaElementLabelProvider(flags));
+ // dialog.setIgnoreCase(false);
+ // dialog.setElements(packages.toArray()); // XXX inefficient
+ // dialog.setFilter(filter);
+ // return dialog;
+ // }
+ /**
+ * Creates a selection dialog that lists all packages of the given Java
+ * project. The caller is responsible for opening the dialog with
+ * Window.open
, and subsequently extracting the selected
+ * package (of type IPackageFragment
) via
+ * SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param project
+ * the Java project
+ * @param style
+ * flags defining the style of the dialog; the valid flags are:
+ * IJavaElementSearchConstants.CONSIDER_BINARIES
,
+ * indicating that packages from binary package fragment roots
+ * should be included in addition to those from source package
+ * fragment roots;
+ * IJavaElementSearchConstants.CONSIDER_REQUIRED_PROJECTS
,
+ * indicating that packages from required projects should be
+ * included as well.
+ * @return a new selection dialog
+ * @exception JavaModelException
+ * if the selection dialog could not be opened
+ */
+ // public static SelectionDialog createPackageDialog(Shell parent,
+ // IJavaProject project, int style) throws JavaModelException {
+ // return createPackageDialog(parent, project, style, ""); //$NON-NLS-1$
+ // }
+ /**
+ * Creates a selection dialog that lists all packages under the given
+ * package fragment root. The caller is responsible for opening the dialog
+ * with Window.open
, and subsequently extracting the
+ * selected package (of type IPackageFragment
) via
+ * SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param root
+ * the package fragment root
+ * @param filter
+ * the initial pattern to filter the set of packages. For example
+ * "com" shows all packages starting with "com". The meta
+ * character '?' representing any character and '*' representing
+ * any string are supported. Clients can pass an empty string if
+ * no filtering is required.
+ * @return a new selection dialog
+ * @exception JavaModelException
+ * if the selection dialog could not be opened
+ *
+ * @since 2.0
+ */
+ // public static SelectionDialog createPackageDialog(Shell parent,
+ // IPackageFragmentRoot root, String filter) throws JavaModelException {
+ // ElementListSelectionDialog dialog= new ElementListSelectionDialog(parent,
+ // new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT));
+ // dialog.setIgnoreCase(false);
+ // dialog.setElements(root.getChildren());
+ // dialog.setFilter(filter);
+ // return dialog;
+ // }
+ /**
+ * Creates a selection dialog that lists all packages under the given
+ * package fragment root. The caller is responsible for opening the dialog
+ * with Window.open
, and subsequently extracting the
+ * selected package (of type IPackageFragment
) via
+ * SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param root
+ * the package fragment root
+ * @return a new selection dialog
+ * @exception JavaModelException
+ * if the selection dialog could not be opened
+ */
+ // public static SelectionDialog createPackageDialog(Shell parent,
+ // IPackageFragmentRoot root) throws JavaModelException {
+ // return createPackageDialog(parent, root, ""); //$NON-NLS-1$
+ // }
+ /**
+ * Creates a selection dialog that lists all types in the given scope. The
+ * caller is responsible for opening the dialog with
+ * Window.open
, and subsequently extracting the selected
+ * type(s) (of type IType
) via
+ * SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param context
+ * the runnable context used to show progress when the dialog is
+ * being populated
+ * @param scope
+ * the scope that limits which types are included
+ * @param style
+ * flags defining the style of the dialog; the only valid values
+ * are IJavaElementSearchConstants.CONSIDER_CLASSES
,
+ * CONSIDER_INTERFACES
, or their bitwise OR
+ * (equivalent to CONSIDER_TYPES
)
+ * @param multipleSelection
+ * true
if multiple selection is allowed
+ * @param filter
+ * the initial pattern to filter the set of types. For example
+ * "Abstract" shows all types starting with "abstract". The meta
+ * character '?' representing any character and '*' representing
+ * any string are supported. Clients can pass an empty string if
+ * no filtering is required.
+ * @exception JavaModelException
+ * if the selection dialog could not be opened
+ *
+ * @since 2.0
+ */
+ // public static SelectionDialog createTypeDialog(Shell parent,
+ // IRunnableContext context, IJavaSearchScope scope, int style, boolean
+ // multipleSelection, String filter) throws JavaModelException {
+ // int elementKinds= 0;
+ // if (style == IJavaElementSearchConstants.CONSIDER_TYPES) {
+ // elementKinds= IJavaSearchConstants.TYPE;
+ // } else if (style == IJavaElementSearchConstants.CONSIDER_INTERFACES) {
+ // elementKinds= IJavaSearchConstants.INTERFACE;
+ // } else if (style == IJavaElementSearchConstants.CONSIDER_CLASSES) {
+ // elementKinds= IJavaSearchConstants.CLASS;
+ // } else {
+ // Assert.isTrue(false, "illegal style"); //$NON-NLS-1$
+ // }
+ // if (multipleSelection) {
+ // MultiTypeSelectionDialog dialog= new MultiTypeSelectionDialog(parent,
+ // context, elementKinds, scope);
+ // dialog.setMessage(JavaUIMessages.getString("JavaUI.defaultDialogMessage"));
+ // //$NON-NLS-1$
+ // dialog.setFilter(filter);
+ // return dialog;
+ // } else {
+ // TypeSelectionDialog dialog= new TypeSelectionDialog(parent, context,
+ // elementKinds, scope);
+ // dialog.setMessage(JavaUIMessages.getString("JavaUI.defaultDialogMessage"));
+ // //$NON-NLS-1$
+ // dialog.setFilter(filter);
+ // return dialog;
+ // }
+ // }
+ /**
+ * Creates a selection dialog that lists all types in the given scope. The
+ * caller is responsible for opening the dialog with
+ * Window.open
, and subsequently extracting the selected
+ * type(s) (of type IType
) via
+ * SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param context
+ * the runnable context used to show progress when the dialog is
+ * being populated
+ * @param scope
+ * the scope that limits which types are included
+ * @param style
+ * flags defining the style of the dialog; the only valid values
+ * are IJavaElementSearchConstants.CONSIDER_CLASSES
,
+ * CONSIDER_INTERFACES
, or their bitwise OR
+ * (equivalent to CONSIDER_TYPES
)
+ * @param multipleSelection
+ * true
if multiple selection is allowed
+ * @return a new selection dialog
+ * @exception JavaModelException
+ * if the selection dialog could not be opened
+ */
+ // public static SelectionDialog createTypeDialog(Shell parent,
+ // IRunnableContext context, IJavaSearchScope scope, int style, boolean
+ // multipleSelection) throws JavaModelException {
+ // return createTypeDialog(parent, context, scope, style, multipleSelection,
+ // "");//$NON-NLS-1$
+ // }
+ /**
+ * Creates a selection dialog that lists all types in the given scope
+ * containing a standard main
method. The caller is
+ * responsible for opening the dialog with Window.open
, and
+ * subsequently extracting the selected type(s) (of type IType
)
+ * via SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param context
+ * the runnable context used to show progress when the dialog is
+ * being populated
+ * @param scope
+ * the scope that limits which types are included
+ * @param style
+ * flags defining the style of the dialog; the only valid values
+ * are IJavaElementSearchConstants.CONSIDER_BINARIES
,
+ * CONSIDER_EXTERNAL_JARS
, or their bitwise OR,
+ * or 0
+ * @param multipleSelection
+ * true
if multiple selection is allowed
+ * @param filter
+ * the initial pattern to filter the set of types containg a main
+ * method. For example "App" shows all types starting with "app".
+ * The meta character '?' representing any character and '*'
+ * representing any string are supported. Clients can pass an
+ * empty string if no filtering is required.
+ * @return a new selection dialog
+ *
+ * @since 2.0
+ */
+ // public static SelectionDialog createMainTypeDialog(Shell parent,
+ // IRunnableContext context, IJavaSearchScope scope, int style, boolean
+ // multipleSelection, String filter) {
+ // if (multipleSelection) {
+ // MultiMainTypeSelectionDialog dialog= new
+ // MultiMainTypeSelectionDialog(parent, context, scope, style);
+ // dialog.setFilter(filter);
+ // return dialog;
+ // } else {
+ // MainTypeSelectionDialog dialog= new MainTypeSelectionDialog(parent,
+ // context, scope, style);
+ // dialog.setFilter(filter);
+ // return dialog;
+ // }
+ // }
+ /**
+ * Creates a selection dialog that lists all types in the given scope
+ * containing a standard main
method. The caller is
+ * responsible for opening the dialog with Window.open
, and
+ * subsequently extracting the selected type(s) (of type IType
)
+ * via SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param context
+ * the runnable context used to show progress when the dialog is
+ * being populated
+ * @param scope
+ * the scope that limits which types are included
+ * @param style
+ * flags defining the style of the dialog; the only valid values
+ * are IJavaElementSearchConstants.CONSIDER_BINARIES
,
+ * CONSIDER_EXTERNAL_JARS
, or their bitwise OR,
+ * or 0
+ * @param multipleSelection
+ * true
if multiple selection is allowed
+ * @return a new selection dialog
+ */
+ // public static SelectionDialog createMainTypeDialog(Shell parent,
+ // IRunnableContext context, IJavaSearchScope scope, int style, boolean
+ // multipleSelection) {
+ // return createMainTypeDialog(parent, context, scope, style,
+ // multipleSelection, "");//$NON-NLS-1$
+ // }
+ /**
+ * Creates a selection dialog that lists all types in the given project. The
+ * caller is responsible for opening the dialog with
+ * Window.open
, and subsequently extracting the selected
+ * type(s) (of type IType
) via
+ * SelectionDialog.getResult
.
+ *
+ * @param parent
+ * the parent shell of the dialog to be created
+ * @param context
+ * the runnable context used to show progress when the dialog is
+ * being populated
+ * @param project
+ * the Java project
+ * @param style
+ * flags defining the style of the dialog; the only valid values
+ * are IJavaElementSearchConstants.CONSIDER_CLASSES
,
+ * CONSIDER_INTERFACES
, or their bitwise OR
+ * (equivalent to CONSIDER_TYPES
)
+ * @param multipleSelection
+ * true
if multiple selection is allowed
+ * @return a new selection dialog
+ * @exception JavaModelException
+ * if the selection dialog could not be opened
+ */
+ // public static SelectionDialog createTypeDialog(Shell parent,
+ // IRunnableContext context, IProject project, int style, boolean
+ // multipleSelection) throws JavaModelException {
+ // IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new
+ // IJavaProject[] { JavaCore.create(project) });
+ // return createTypeDialog(parent, context, scope, style,
+ // multipleSelection);
+ // }
+ /**
+ * Opens a Java editor on the given Java element. The element can be a
+ * compilation unit or class file. If there already is an open Java editor
+ * for the given element, it is returned.
+ *
+ * @param element
+ * the input element; either a compilation unit (ICompilationUnit
)
+ * or a class file (
IClassFile)
+ * @return the editor, or null if wrong element type or
+ * opening failed
+ * @exception PartInitException
+ * if the editor could not be initialized
+ * @exception JavaModelException
+ * if this element does not exist or if an exception occurs
+ * while accessing its underlying resource
+ */
+ public static IEditorPart openInEditor(IJavaElement element)
+ throws JavaModelException, PartInitException {
+ return EditorUtility.openInEditor(element);
+ }
+
+ /**
+ * Reveals the source range of the given source reference element in the
+ * given editor. No checking is done if the editor displays a compilation
+ * unit or class file that contains the given source reference. The editor
+ * simply reveals the source range denoted by the given source reference.
+ *
+ * @param part
+ * the editor displaying the compilation unit or class file
+ * @param element
+ * the source reference element defining the source range to be
+ * revealed
+ *
+ * @deprecated use revealInEditor(IEditorPart, IJavaElement)
+ * instead
+ */
+ // public static void revealInEditor(IEditorPart part, ISourceReference
+ // element) {
+ // if (element instanceof IJavaElement)
+ // revealInEditor(part, (IJavaElement) element);
+ // }
+ /**
+ * Reveals the given java element in the given editor. If the element is not
+ * an instance of ISourceReference
this method result in a
+ * NOP. If it is a source reference no checking is done if the editor
+ * displays a compilation unit or class file that contains the source
+ * reference element. The editor simply reveals the source range denoted by
+ * the given element.
+ *
+ * @param part
+ * the editor displaying a compilation unit or class file
+ * @param element
+ * the element to be revealed
+ *
+ * @since 2.0
+ */
+ // public static void revealInEditor(IEditorPart part, IJavaElement element)
+ // {
+ // EditorUtility.revealInEditor(part, element);
+ // }
+ /**
+ * Returns the working copy manager for the Java UI plug-in.
+ *
+ * @return the working copy manager for the Java UI plug-in
+ */
+ public static IWorkingCopyManager getWorkingCopyManager() {
+ return WebUI.getDefault().getWorkingCopyManager();
+ }
+
+ /**
+ * Answers the shared working copies currently registered for the Java
+ * plug-in. Note that the returned array can include working copies that are
+ * not on the class path of a Java project.
+ *
+ * @return the list of shared working copies
+ *
+ * @see net.sourceforge.phpdt.core.JavaCore#getSharedWorkingCopies(net.sourceforge.phpdt.core.IBufferFactory)
+ * @since 2.0
+ */
+ public static IWorkingCopy[] getSharedWorkingCopies() {
+ return JavaCore.getSharedWorkingCopies(getBufferFactory());
+ }
+
+ /**
+ * Answers the shared working copies that are on the class path of a Java
+ * project currently registered for the Java plug-in.
+ *
+ *
+ * @return the list of shared working copies
+ *
+ * @see #getSharedWorkingCopies()
+ * @since 2.1
+ */
+ // public static IWorkingCopy[] getSharedWorkingCopiesOnClasspath() {
+ // IWorkingCopy[] wcs= getSharedWorkingCopies();
+ // List result= new ArrayList(wcs.length);
+ // for (int i = 0; i < wcs.length; i++) {
+ // IWorkingCopy wc= wcs[i];
+ // if (wc instanceof IJavaElement) {
+ // IJavaElement je= (IJavaElement)wc;
+ // if (je.getJavaProject().isOnClasspath(je)) {
+ // result.add(wc);
+ // }
+ // }
+ // }
+ // return (IWorkingCopy[])result.toArray(new IWorkingCopy[result.size()]);
+ // }
+ /**
+ * Returns the BufferFactory for the Java UI plug-in.
+ *
+ * @return the BufferFactory for the Java UI plug-in
+ *
+ * @see net.sourceforge.phpdt.core.IBufferFactory
+ * @since 2.0
+ * @deprecated {@link IBufferFactory} has been replaced by
+ * {@link net.sourceforge.phpdt.core.WorkingCopyOwner}. The
+ * Java UI plug-in uses the primary working copy owner
+ * that can be accessed with null
in API's that
+ * require an owner
+ */
+ public static IBufferFactory getBufferFactory() {
+ return PHPeclipsePlugin.getDefault().getBufferFactory();
+ }
+
+ /**
+ * Returns the DocumentProvider used for Java compilation units.
+ *
+ * @return the DocumentProvider for Java compilation units.
+ *
+ * @see IDocumentProvider
+ * @since 2.0
+ */
+ public static IDocumentProvider getDocumentProvider() {
+ return WebUI.getDefault()
+ .getCompilationUnitDocumentProvider();
+ }
+
+ /**
+ * Sets the Javadoc location for an archive with the given path.
+ *
+ * @param archivePath
+ * the path of the library; this can be an workspace path or an
+ * external path in case of an external library.
+ * @param url
+ * The Javadoc location to set. This location should contain
+ * index.html and a file 'package-list'. null
+ * clears the current documentation location.
+ *
+ * @since 2.0
+ */
+ // public static void setLibraryJavadocLocation(IPath archivePath, URL url)
+ // {
+ // JavaDocLocations.setLibraryJavadocLocation(archivePath, url);
+ // }
+ /**
+ * Returns the Javadoc location for an archive or null
if no
+ * location is available.
+ *
+ * @param archivePath
+ * the path of the library. This can be an workspace path or an
+ * external path in case of an external library.
+ *
+ * @since 2.0
+ */
+ // public static URL getLibraryJavadocLocation(IPath archivePath) {
+ // return JavaDocLocations.getLibraryJavadocLocation(archivePath);
+ // }
+ /**
+ * Sets the Javadoc location for a Java project. This location is used for
+ * all types located in the project's source folders.
+ *
+ * @param project
+ * the project
+ * @param url
+ * The Javadoc location to set. This location should contain
+ * index.html and a file 'package-list'. null
+ * clears the current documentation location.
+ *
+ * @since 2.1
+ */
+ // public static void setProjectJavadocLocation(IJavaProject project, URL
+ // url) {
+ // JavaDocLocations.setProjectJavadocLocation(project, url);
+ // }
+ /**
+ * Returns the Javadoc location for a Java project or null
if
+ * no location is available. This location is used for all types located in
+ * the project's source folders.
+ *
+ * @param project
+ * the project
+ *
+ * @since 2.1
+ */
+ // public static URL getProjectJavadocLocation(IJavaProject project) {
+ // return JavaDocLocations.getProjectJavadocLocation(project);
+ // }
+ /**
+ * Returns the Javadoc base URL for an element. The base location contains
+ * the index file. This location doesn't have to exist. Returns
+ * null
if no javadoc location has been attached to the
+ * element's library or project. Example of a returned URL is http://www.
+ * junit. org/junit/javadoc.
+ *
+ * @param The
+ * element for which the doc URL is requested.
+ *
+ * @since 2.0
+ */
+ // public static URL getJavadocBaseLocation(IJavaElement element) throws
+ // JavaModelException {
+ // return JavaDocLocations.getJavadocBaseLocation(element);
+ // }
+ /**
+ * Returns the Javadoc URL for an element. Example of a returned URL is
+ * http://www.junit.org/junit/javadoc/junit/extensions/TestSetup.html.
+ * This returned location doesn't have to exist. Returns null
+ * if no javadoc location has been attached to the element's library or
+ * project.
+ *
+ * @param The
+ * element for which the doc URL is requested.
+ * @param includeAnchor
+ * If set, the URL contains an anchor for member references:
+ * http://www.junit.org/junit/javadoc/junit/extensions/TestSetup.html#run(junit.framework.TestResult).
+ * Note that this involves type resolving and is a more expensive
+ * call than without anchor.
+ *
+ * @since 2.0
+ */
+ // public static URL getJavadocLocation(IJavaElement element, boolean
+ // includeAnchor) throws JavaModelException {
+ // return JavaDocLocations.getJavadocLocation(element, includeAnchor);
+ // }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/OverrideIndicatorLabelDecorator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/OverrideIndicatorLabelDecorator.java
new file mode 100644
index 0000000..db7385e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/OverrideIndicatorLabelDecorator.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ImageDescriptorRegistry;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ImageImageDescriptor;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+
+/**
+ * LabelDecorator that decorates an method's image with override or implements
+ * overlays. The viewer using this decorator is responsible for updating the
+ * images on element changes.
+ *
+ * + * This class may be instantiated; it is not intended to be subclassed. + *
+ * + * @since 2.0 + */ +public class OverrideIndicatorLabelDecorator implements ILabelDecorator, + ILightweightLabelDecorator { + + private ImageDescriptorRegistry fRegistry; + + private boolean fUseNewRegistry = false; + + /** + * Creates a decorator. The decorator creates an own image registry to cache + * images. + */ + public OverrideIndicatorLabelDecorator() { + this(null); + fUseNewRegistry = true; + } + + /* + * Creates decorator with a shared image registry. + * + * @param registry The registry to use ornull
to use the
+ * Java plugin's image registry.
+ */
+ /**
+ * Note: This constructor is for internal use only. Clients should not call
+ * this constructor.
+ */
+ public OverrideIndicatorLabelDecorator(ImageDescriptorRegistry registry) {
+ fRegistry = registry;
+ }
+
+ private ImageDescriptorRegistry getRegistry() {
+ if (fRegistry == null) {
+ fRegistry = fUseNewRegistry ? new ImageDescriptorRegistry()
+ : WebUI.getImageDescriptorRegistry();
+ }
+ return fRegistry;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelDecorator#decorateText(String, Object)
+ */
+ public String decorateText(String text, Object element) {
+ return text;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelDecorator#decorateImage(Image, Object)
+ */
+ public Image decorateImage(Image image, Object element) {
+ int adornmentFlags = computeAdornmentFlags(element);
+ if (adornmentFlags != 0) {
+ ImageDescriptor baseImage = new ImageImageDescriptor(image);
+ Rectangle bounds = image.getBounds();
+ return getRegistry().get(
+ new JavaElementImageDescriptor(baseImage, adornmentFlags,
+ new Point(bounds.width, bounds.height)));
+ }
+ return image;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ public int computeAdornmentFlags(Object element) {
+ if (element instanceof IMethod) {
+ if (!PreferenceConstants.getPreferenceStore().getBoolean(
+ PreferenceConstants.APPEARANCE_OVERRIDE_INDICATOR)) {
+ return 0;
+ }
+
+ try {
+ IMethod method = (IMethod) element;
+ // if (!method.getJavaProject().isOnClasspath(method)) {
+ // return 0;
+ // }
+
+ int flags = method.getFlags();
+ IType type = method.getDeclaringType();// jsurfer INSERT
+ if (type != null && type.isClass() && !method.isConstructor()
+ && !Flags.isPrivate(flags) && !Flags.isStatic(flags)) {
+ return getOverrideIndicators(method);
+ }
+ } catch (JavaModelException e) {
+ if (!e.isDoesNotExist()) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected int getOverrideIndicators(IMethod method)
+ throws JavaModelException {
+ IType type = method.getDeclaringType();
+ // ITypeHierarchy hierarchy=
+ // SuperTypeHierarchyCache.getTypeHierarchy(type);
+ // if (hierarchy != null) {
+ // return findInHierarchy(type, hierarchy, method.getElementName(),
+ // method.getParameterTypes());
+ // }
+ return 0;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ // protected int findInHierarchy(IType type, ITypeHierarchy hierarchy,
+ // String name, String[] paramTypes) throws JavaModelException {
+ // IMethod impl= JavaModelUtil.findMethodDeclarationInHierarchy(hierarchy,
+ // type, name, paramTypes, false);
+ // if (impl != null) {
+ // IMethod overridden=
+ // JavaModelUtil.findMethodImplementationInHierarchy(hierarchy, type, name,
+ // paramTypes, false);
+ // if (overridden != null) {
+ // return JavaElementImageDescriptor.OVERRIDES;
+ // } else {
+ // return JavaElementImageDescriptor.IMPLEMENTS;
+ // }
+ // }
+ // return 0;
+ // }
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#addListener(ILabelProviderListener)
+ */
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#dispose()
+ */
+ public void dispose() {
+ if (fRegistry != null && fUseNewRegistry) {
+ fRegistry.dispose();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#isLabelProperty(Object, String)
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object,
+ * org.eclipse.jface.viewers.IDecoration)
+ */
+ public void decorate(Object element, IDecoration decoration) {
+ int adornmentFlags = computeAdornmentFlags(element);
+ if (adornmentFlags != 0) {
+ decoration.addOverlay(PHPUiImages.DESC_OVR_OVERRIDES);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/PreferenceConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/PreferenceConstants.java
new file mode 100644
index 0000000..41a16c8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/PreferenceConstants.java
@@ -0,0 +1,3071 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import net.sourceforge.phpdt.core.IClasspathEntry;
+import net.sourceforge.phpdt.internal.ui.text.spelling.SpellCheckEngine;
+import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+//
+// import org.phpeclipse.phpdt.internal.ui.JavaPlugin;
+// import
+// org.phpeclipse.phpdt.internal.ui.preferences.NewJavaProjectPreferencePage;
+
+/**
+ * Preference constants used in the JDT-UI preference store. Clients should only
+ * read the JDT-UI preference store using these values. Clients are not allowed
+ * to modify the preference store programmatically.
+ *
+ * @since 2.0
+ */
+public class PreferenceConstants {
+
+ private PreferenceConstants() {
+ }
+
+ /**
+ * A named preference that controls return type rendering of methods in the
+ * UI.
+ *
+ * Value is of type Boolean
: if true
return
+ * types are rendered
+ *
+ * Value is of type Boolean
: if true
override
+ * indicators are rendered
+ *
+ * Value is of type String
. For example foe the given
+ * package name 'net.sourceforge.phpdt' pattern '.' will compress it to
+ * '..jdt', '1~' to 'o~.e~.jdt'.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
: if true
empty
+ * inner packages are folded.
+ *
JavaElementSorter
.
+ *
+ * Value is of type String
: A comma separated list of the
+ * following entries. Each entry must be in the list, no duplication. List
+ * order defines the sort order.
+ *
JavaElementSorter
.
+ *
+ * Value is of type String
: A comma separated list of the
+ * following entries. Each entry must be in the list, no duplication. List
+ * order defines the sort order.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
: comma separated list of prefixed
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
: comma separated list of suffixes
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
: semicolon separated list of
+ * package names
+ *
+ * Value is of type Int
: positive value specifing the number
+ * of non star-import is used
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
. if true
new
+ * projects are created with a source and output folder. If
+ * false
source and output folder equals to the project.
+ *
SRCBIN_FOLDERS_IN_NEWPROJ
is set to false
.
+ *
+ * Value is of type String
.
+ *
SRCBIN_FOLDERS_IN_NEWPROJ
is set to false
.
+ *
+ * Value is of type String
.
+ *
IClasspathEntry
s, that will represent
+ * the JRE on the new project's classpath.
+ *
+ * Value is of type String
: a semicolon separated list of
+ * encoded JRE libraries. NEWPROJECT_JRELIBRARY_INDEX
defines
+ * the currently used library. Clients should use the method
+ * encodeJRELibrary
to encode a JRE library into a string and
+ * the methods decodeJRELibraryDescription(String)
and
+ * decodeJRELibraryClasspathEntries(String)
+ * to decode the description and the array of classpath entries from an
+ * encoded string.
+ *
+ * Value is of type Int
: an index into the list of possible
+ * JRE libraries.
+ *
+ * Value is of type String
: possible values are
+ * OPEN_TYPE_HIERARCHY_IN_PERSPECTIVE
+ * or
+ * OPEN_TYPE_HIERARCHY_IN_VIEW_PART
.
+ *
OPEN_TYPE_HIERARCHY
.
+ *
+ * @see #OPEN_TYPE_HIERARCHY
+ */
+ public static final String OPEN_TYPE_HIERARCHY_IN_PERSPECTIVE = "perspective"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference
+ * OPEN_TYPE_HIERARCHY
.
+ *
+ * @see #OPEN_TYPE_HIERARCHY
+ */
+ public static final String OPEN_TYPE_HIERARCHY_IN_VIEW_PART = "viewPart"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the behaviour when double clicking on a
+ * container in the packages view.
+ *
+ * Value is of type String
: possible values are
+ * DOUBLE_CLICK_GOES_INTO
+ * or
+ * DOUBLE_CLICK_EXPANDS
.
+ *
DOUBLE_CLICK
.
+ *
+ * @see #DOUBLE_CLICK
+ */
+ public static final String DOUBLE_CLICK_GOES_INTO = "packageview.gointo"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference DOUBLE_CLICK
.
+ *
+ * @see #DOUBLE_CLICK
+ */
+ public static final String DOUBLE_CLICK_EXPANDS = "packageview.doubleclick.expands"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether Java views update their
+ * presentation while editing or when saving the content of an editor.
+ *
+ * Value is of type String
: possible values are
+ * UPDATE_ON_SAVE
+ * or
+ * UPDATE_WHILE_EDITING
.
+ *
UPDATE_JAVA_VIEWS
+ *
+ * @see #UPDATE_JAVA_VIEWS
+ */
+ public static final String UPDATE_ON_SAVE = "JavaUI.update.onSave"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference
+ * UPDATE_JAVA_VIEWS
+ *
+ * @see #UPDATE_JAVA_VIEWS
+ */
+ public static final String UPDATE_WHILE_EDITING = "JavaUI.update.whileEditing"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the path of the Javadoc command used by the
+ * Javadoc creation wizard.
+ *
+ * Value is of type String
.
+ *
javaEditorTextHovers
.
+ *
+ * @since 2.1
+ */
+ public static String ID_BESTMATCH_HOVER = "net.sourceforge.phpdt.ui.BestMatchHover"; //$NON-NLS-1$
+
+ /**
+ * The id of the source code hover contributed for extension point
+ * javaEditorTextHovers
.
+ *
+ * @since 2.1
+ */
+ public static String ID_SOURCE_HOVER = "net.sourceforge.phpdt.ui.JavaSourceHover"; //$NON-NLS-1$
+
+ /**
+ * The id of the problem hover contributed for extension point
+ * javaEditorTextHovers
.
+ *
+ * @since 2.1
+ */
+ public static String ID_PROBLEM_HOVER = "net.sourceforge.phpdt.ui.ProblemHover"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether bracket matching highlighting is
+ * turned on or off.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
. If true
spaces
+ * instead of tabs are used in the editor. If false
the
+ * editor inserts a tab character when pressing the tab key.
+ *
+ * Value is of type Int
: positive int value specifying the
+ * number of spaces per tab.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
"net.sourceforge.phpdt.ui.editors.textfont"
).
+ *
+ * @since 2.1
+ */
+ public final static String EDITOR_TEXT_FONT = "net.sourceforge.phpdt.ui.editors.textfont"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether multi line comments are rendered
+ * in bold.
+ *
+ * Value is of type Boolean
. If true
multi
+ * line comments are rendered in bold. If false
the are
+ * rendered using no font style attribute.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
. If true
single
+ * line comments are rendered in bold. If false
the are
+ * rendered using no font style attribute.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
+ * or EDITOR_DEFAULT_HOVER_CONFIGURED_ID
or the hover id of a
+ * hover contributed as phpEditorTextHovers
.
+ *
CTRL
modifier key is pressed.
+ *
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
+ * or EDITOR_DEFAULT_HOVER_CONFIGURED_ID
or the hover id of a
+ * hover contributed as phpEditorTextHovers
.
+ *
SHIFT
modifier key is pressed.
+ *
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
+ * or EDITOR_DEFAULT_HOVER_CONFIGURED_ID
or the hover id of a
+ * hover contributed as phpEditorTextHovers
.
+ *
CTRL + ALT
modifier keys is pressed.
+ *
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
+ * or EDITOR_DEFAULT_HOVER_CONFIGURED_ID
or the hover id of a
+ * hover contributed as phpEditorTextHovers
.
+ *
CTRL + ALT + SHIFT
modifier keys is pressed.
+ *
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
+ * or EDITOR_DEFAULT_HOVER_CONFIGURED_ID
or the hover id of a
+ * hover contributed as phpEditorTextHovers
.
+ *
CTRL + SHIFT
modifier keys is pressed.
+ *
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
+ * or EDITOR_DEFAULT_HOVER_CONFIGURED_ID
or the hover id of a
+ * hover contributed as phpEditorTextHovers
.
+ *
ALT
+ * modifier key is pressed.
+ *
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
,
+ * EDITOR_DEFAULT_HOVER_CONFIGURED_ID
or the hover id of a
+ * hover contributed as phpEditorTextHovers
.
+ *
EDITOR_DEFAULT_HOVER
property.
+ *
+ * @since 2.1
+ */
+ public static final String EDITOR_DEFAULT_HOVER_CONFIGURED_ID = "defaultHoverConfiguredId"; //$NON-NLS-1$
+
+ /**
+ * A named preference that defines the hover named the 'default hover'.
+ * Value is of type String
: possible values are
+ * EDITOR_NO_HOVER_CONFIGURED_ID
+ * or the hover id of a hover
+ * contributed as phpEditorTextHovers
.
+ *
+ *@since 2.1
+ */
+ public static final String EDITOR_DEFAULT_HOVER = "defaultHover"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if segmented view (show selected element
+ * only) is turned on or off.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public static final String EDITOR_SHOW_SEGMENTS = "net.sourceforge.phpdt.ui.editor.showSegments"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if browser like links are turned on or
+ * off.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String EDITOR_BROWSER_LIKE_LINKS = "browserLikeLinks"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the key modifier for browser like links.
+ *
+ * Value is of type String
.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER = "browserLikeLinksKeyModifier"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether occurrences are marked in the
+ * editor.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_MARK_OCCURRENCES = "markOccurrences"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether occurrences are sticky in the
+ * editor.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_STICKY_OCCURRENCES = "stickyOccurrences"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls disabling of the overwrite mode.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_DISABLE_OVERWRITE_MODE = "disable_overwrite_mode"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls saving of a file on loss of editor focus.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_SAVE_ON_BLUR = "save_on_blur"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the "smart semicolon" smart typing
+ * handler
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_SMART_SEMICOLON = "smart_semicolon"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the smart backspace behavior.
+ *
+ * Value is of type Boolean
.
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_SMART_BACKSPACE = "smart_backspace"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the "smart opening brace" smart typing
+ * handler
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_SMART_OPENING_BRACE = "smart_opening_brace"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the smart tab behaviour.
+ *
+ * Value is of type Boolean
.
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_SMART_TAB = "smart_tab"; //$NON-NLS-1$
+
+ public static final String EDITOR_P_RTRIM_ON_SAVE = "editor_p_trim_on_save"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether Java comments should be
+ * spell-checked.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_CHECK_SPELLING = ISpellCheckPreferenceKeys.SPELLING_CHECK_SPELLING;
+
+ /**
+ * A named preference that controls whether words containing digits should
+ * be skipped during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_IGNORE_DIGITS = ISpellCheckPreferenceKeys.SPELLING_IGNORE_DIGITS;
+
+ /**
+ * A named preference that controls whether mixed case words should be
+ * skipped during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_IGNORE_MIXED = ISpellCheckPreferenceKeys.SPELLING_IGNORE_MIXED;
+
+ /**
+ * A named preference that controls whether sentence capitalization should
+ * be ignored during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_IGNORE_SENTENCE = ISpellCheckPreferenceKeys.SPELLING_IGNORE_SENTENCE;
+
+ /**
+ * A named preference that controls whether upper case words should be
+ * skipped during spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_IGNORE_UPPER = ISpellCheckPreferenceKeys.SPELLING_IGNORE_UPPER;
+
+ /**
+ * A named preference that controls whether urls should be ignored during
+ * spell-checking.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_IGNORE_URLS = ISpellCheckPreferenceKeys.SPELLING_IGNORE_URLS;
+
+ /**
+ * A named preference that controls the locale used for spell-checking.
+ *
+ * Value is of type String
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_LOCALE = ISpellCheckPreferenceKeys.SPELLING_LOCALE;
+
+ /**
+ * A named preference that controls the number of proposals offered during
+ * spell-checking.
+ *
+ * Value is of type Integer
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_PROPOSAL_THRESHOLD = ISpellCheckPreferenceKeys.SPELLING_PROPOSAL_THRESHOLD;
+
+ /**
+ * A named preference that specifies the workspace user dictionary.
+ *
+ * Value is of type Integer
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_USER_DICTIONARY = ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY;
+
+ /**
+ * A named preference that specifies whether spelling dictionaries are
+ * available to content assist.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String SPELLING_ENABLE_CONTENTASSIST = ISpellCheckPreferenceKeys.SPELLING_ENABLE_CONTENTASSIST;
+
+ /**
+ * A named preference that controls whether code snippets are formatted in
+ * Javadoc comments.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_FORMATSOURCE = "comment_format_source_code"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether description of Javadoc
+ * parameters are indented.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_INDENTPARAMETERDESCRIPTION = "comment_indent_parameter_description"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether the header comment of a Java
+ * source file is formatted.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_FORMATHEADER = "comment_format_header"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether Javadoc root tags are indented.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_INDENTROOTTAGS = "comment_indent_root_tags"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether Javadoc comments are formatted
+ * by the content formatter.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_FORMAT = "comment_format_comments"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether a new line is inserted after
+ * Javadoc root tag parameters.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_NEWLINEFORPARAMETER = "comment_new_line_for_parameter"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether an empty line is inserted before
+ * the Javadoc root tag block.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_SEPARATEROOTTAGS = "comment_separate_root_tags"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether blank lines are cleared during
+ * formatting
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_CLEARBLANKLINES = "comment_clear_blank_lines"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the line length of comments.
+ *
+ * Value is of type Integer
. The value must be at least 4
+ * for reasonable formatting.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_LINELENGTH = "comment_line_length"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether html tags are formatted.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public final static String FORMATTER_COMMENT_FORMATHTML = "comment_format_html"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if the Java code assist gets auto
+ * activated.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String CODEASSIST_AUTOACTIVATION = "content_assist_autoactivation"; //$NON-NLS-1$
+
+ /**
+ * A name preference that holds the auto activation delay time in milli
+ * seconds.
+ *
+ * Value is of type Int
.
+ *
+ */
+ public final static String CODEASSIST_AUTOACTIVATION_DELAY = "content_assist_autoactivation_delay"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if code assist contains only visible
+ * proposals.
+ *
+ * Value is of type Boolean
. if
+ * true code assist only contains visible members. If
+ * false
all members are included.
+ *
+ */
+ public final static String CODEASSIST_SHOW_VISIBLE_PROPOSALS = "content_assist_show_visible_proposals"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if the Java code assist inserts a
+ * proposal automatically if only one proposal is available.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 2.1
+ */
+ public final static String CODEASSIST_AUTOINSERT = "content_assist_autoinsert"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if the Java code assist adds import
+ * statements.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 2.1
+ */
+ public final static String CODEASSIST_ADDIMPORT = "content_assist_add_import"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if the Java code assist only inserts
+ * completions. If set to false the proposals can also _replace_ code.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 2.1
+ */
+ public final static String CODEASSIST_INSERT_COMPLETION = "content_assist_insert_completion"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether code assist proposals filtering
+ * is case sensitive or not.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String CODEASSIST_CASE_SENSITIVITY = "content_assist_case_sensitivity"; //$NON-NLS-1$
+
+ /**
+ * A named preference that defines if code assist proposals are sorted in
+ * alphabetical order.
+ *
+ * Value is of type Boolean
. If true
that are
+ * sorted in alphabetical order. If false
that are unsorted.
+ *
+ */
+ public final static String CODEASSIST_ORDER_PROPOSALS = "content_assist_order_proposals"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if argument names are filled in when a
+ * method is selected from as list of code assist proposal.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public final static String CODEASSIST_FILL_ARGUMENT_NAMES = "content_assist_fill_method_arguments"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if method arguments are guessed when a
+ * method is selected from as list of code assist proposal.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 2.1
+ */
+ public final static String CODEASSIST_GUESS_METHOD_ARGUMENTS = "content_assist_guess_method_arguments"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the characters that auto activate code
+ * assist in PHP code.
+ *
+ * Value is of type Sring
. All characters that trigger auto
+ * code assist in PHP code.
+ *
+ */
+ public final static String CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA = "content_assist_autoactivation_triggers_php"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the characters that auto activate code
+ * assist in PHPDoc.
+ *
+ * Value is of type Sring
. All characters that trigger auto
+ * code assist in PHPDoc.
+ *
+ */
+ public final static String CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC = "content_assist_autoactivation_triggers_phpdoc"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the characters that auto activate code
+ * assist in HTML.
+ *
+ * Value is of type Sring
. All characters that trigger auto
+ * code assist in HTML.
+ *
+ */
+ public final static String CODEASSIST_AUTOACTIVATION_TRIGGERS_HTML = "content_assist_autoactivation_triggers_html"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the background color used in the code
+ * assist selection dialog.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ *
+ * @see org.eclipse.jface.resource.StringConverter
+ * @see org.eclipse.jface.preference.PreferenceConverter
+ */
+ 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.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ *
+ * @see org.eclipse.jface.resource.StringConverter
+ * @see org.eclipse.jface.preference.PreferenceConverter
+ */
+ public final static String CODEASSIST_PROPOSALS_FOREGROUND = "content_assist_proposals_foreground"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the background color used for parameter
+ * hints.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ *
+ * @see org.eclipse.jface.resource.StringConverter
+ * @see org.eclipse.jface.preference.PreferenceConverter
+ */
+ public final static String CODEASSIST_PARAMETERS_BACKGROUND = "content_assist_parameters_background"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the foreground color used in the code
+ * assist selection dialog
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ *
+ * @see org.eclipse.jface.resource.StringConverter
+ * @see org.eclipse.jface.preference.PreferenceConverter
+ */
+ public final static String CODEASSIST_PARAMETERS_FOREGROUND = "content_assist_parameters_foreground"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the background color used in the code
+ * assist selection dialog to mark replaced code.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ *
+ * @see org.eclipse.jface.resource.StringConverter
+ * @see org.eclipse.jface.preference.PreferenceConverter
+ * @since 2.1
+ */
+ public final static String CODEASSIST_REPLACEMENT_BACKGROUND = "content_assist_completion_replacement_background"; //$NON-NLS-1$
+
+ /**
+ * A named preference that holds the foreground color used in the code
+ * assist selection dialog to mark replaced code.
+ *
+ * Value is of type String
. A RGB color value encoded as a
+ * string using class PreferenceConverter
+ *
+ *
+ * @see org.eclipse.jface.resource.StringConverter
+ * @see org.eclipse.jface.preference.PreferenceConverter
+ * @since 2.1
+ */
+ public final static String CODEASSIST_REPLACEMENT_FOREGROUND = "content_assist_completion_replacement_foreground"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the behaviour of the refactoring wizard
+ * for showing the error page.
+ *
+ * Value is of type String
. Valid values are:
+ * REFACTOR_FATAL_SEVERITY
,
+ * REFACTOR_ERROR_SEVERITY
,REFACTOR_WARNING_SEVERITY
+ * REFACTOR_INFO_SEVERITY
,
+ * REFACTOR_OK_SEVERITY
.
+ *
+ *
+ * @see #REFACTOR_FATAL_SEVERITY
+ * @see #REFACTOR_ERROR_SEVERITY
+ * @see #REFACTOR_WARNING_SEVERITY
+ * @see #REFACTOR_INFO_SEVERITY
+ * @see #REFACTOR_OK_SEVERITY
+ */
+ public static final String REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD = "Refactoring.ErrorPage.severityThreshold"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference
+ * REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
.
+ *
+ * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
+ */
+ public static final String REFACTOR_FATAL_SEVERITY = "4"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference
+ * REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
.
+ *
+ * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
+ */
+ public static final String REFACTOR_ERROR_SEVERITY = "3"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference
+ * REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
.
+ *
+ * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
+ */
+ public static final String REFACTOR_WARNING_SEVERITY = "2"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference
+ * REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
.
+ *
+ * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
+ */
+ public static final String REFACTOR_INFO_SEVERITY = "1"; //$NON-NLS-1$
+
+ /**
+ * A string value used by the named preference
+ * REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
.
+ *
+ * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
+ */
+ public static final String REFACTOR_OK_SEVERITY = "0"; //$NON-NLS-1$
+
+ /**
+ * A named preference thet controls whether all dirty editors are
+ * automatically saved before a refactoring is executed.
+ *
+ * Value is of type Boolean
.
+ *
+ */
+ public static final String REFACTOR_SAVE_ALL_EDITORS = "Refactoring.savealleditors"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if the Java Browsing views are linked to
+ * the active editor.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @see #LINK_PACKAGES_TO_EDITOR
+ */
+ public static final String BROWSING_LINK_VIEW_TO_EDITOR = "net.sourceforge.phpdt.ui.browsing.linktoeditor"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the layout of the Java Browsing views
+ * vertically. Boolean value.
+ *
+ * Value is of type Boolean
. If
+ * true the views are stacked vertical.
+ * If false
they are stacked horizontal.
+ *
+ */
+ public static final String BROWSING_STACK_VERTICALLY = "net.sourceforge.phpdt.ui.browsing.stackVertically"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls if templates are formatted when applied.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String TEMPLATES_USE_CODEFORMATTER = "net.sourceforge.phpdt.ui.template.format"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether annotation roll over is used or
+ * not.
+ *
+ * Value is of type Boolean
. If
+ * true the annotation ruler column
+ * uses a roll over to display multiple annotations
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_ANNOTATION_ROLL_OVER = "editor_annotation_roll_over"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls the key modifier mask for browser like
+ * links. The value is only used if the value of
+ * EDITOR_BROWSER_LIKE_LINKS
cannot be resolved to valid SWT
+ * modifier bits.
+ *
+ * Value is of type String
.
+ *
+ *
+ * @see #EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER
+ * @since 2.1.1
+ */
+ public static final String EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = "browserLikeLinksKeyModifierMask"; //$NON-NLS-1$
+
+ /**
+ * A named preference that defines the key for the hover modifier state
+ * masks. The value is only used if the value of
+ * EDITOR_TEXT_HOVER_MODIFIERS
cannot be resolved to valid
+ * SWT modifier bits.
+ *
+ * @see JavaUI
+ * @see #EDITOR_TEXT_HOVER_MODIFIERS
+ * @since 2.1.1
+ */
+ public static final String EDITOR_TEXT_HOVER_MODIFIER_MASKS = "hoverModifierMasks"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether folding is enabled in the Java
+ * editor.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_FOLDING_ENABLED = "editor_folding_enabled"; //$NON-NLS-1$
+
+ /**
+ * A named preference that stores the configured folding provider.
+ *
+ * Value is of type String
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_FOLDING_PROVIDER = "editor_folding_provider"; //$NON-NLS-1$
+
+ /**
+ * A named preference that stores the value for Javadoc folding for the
+ * default folding provider.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_FOLDING_JAVADOC = "editor_folding_default_javadoc"; //$NON-NLS-1$
+
+ /**
+ * A named preference that stores the value for inner type folding for the
+ * default folding provider.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_FOLDING_INNERTYPES = "editor_folding_default_innertypes"; //$NON-NLS-1$
+
+ /**
+ * A named preference that stores the value for method folding for the
+ * default folding provider.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ public static final String EDITOR_FOLDING_METHODS = "editor_folding_default_methods"; //$NON-NLS-1$
+
+ /**
+ * A named preference that stores the value for imports folding for the
+ * default folding provider.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.0
+ */
+ // public static final String EDITOR_FOLDING_IMPORTS =
+ // "editor_folding_default_imports"; //$NON-NLS-1$
+ /**
+ * A named preference that stores the value for header comment folding for
+ * the default folding provider.
+ *
+ * Value is of type Boolean
.
+ *
+ *
+ * @since 3.1
+ */
+ public static final String EDITOR_FOLDING_HEADERS = "editor_folding_default_headers"; //$NON-NLS-1$
+
+ public static void initializeDefaultValues(IPreferenceStore store) {
+ store.setDefault(PreferenceConstants.EDITOR_SHOW_SEGMENTS, false);
+
+ // JavaBasePreferencePage
+ store.setDefault(PreferenceConstants.LINK_PACKAGES_TO_EDITOR, true);
+ store.setDefault(PreferenceConstants.LINK_TYPEHIERARCHY_TO_EDITOR,
+ false);
+ store
+ .setDefault(PreferenceConstants.LINK_BROWSING_VIEW_TO_EDITOR,
+ true);
+ store.setDefault(PreferenceConstants.OPEN_TYPE_HIERARCHY,
+ PreferenceConstants.OPEN_TYPE_HIERARCHY_IN_VIEW_PART);
+ store.setDefault(PreferenceConstants.DOUBLE_CLICK,
+ PreferenceConstants.DOUBLE_CLICK_EXPANDS);
+ store.setDefault(PreferenceConstants.UPDATE_JAVA_VIEWS,
+ PreferenceConstants.UPDATE_WHILE_EDITING);
+
+ // AppearancePreferencePage
+ store.setDefault(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES,
+ false);
+ store.setDefault(PreferenceConstants.APPEARANCE_METHOD_RETURNTYPE,
+ false);
+ store.setDefault(PreferenceConstants.SHOW_CU_CHILDREN, true);
+ store.setDefault(PreferenceConstants.APPEARANCE_OVERRIDE_INDICATOR,
+ true);
+ store.setDefault(PreferenceConstants.BROWSING_STACK_VERTICALLY, false);
+ store.setDefault(
+ PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW,
+ ""); //$NON-NLS-1$
+ store
+ .setDefault(
+ PreferenceConstants.APPEARANCE_FOLD_PACKAGES_IN_PACKAGE_EXPLORER,
+ true);
+
+ // ImportOrganizePreferencePage
+ // store.setDefault(PreferenceConstants.ORGIMPORTS_IMPORTORDER,
+ // "php;phpx;org;com"); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.ORGIMPORTS_ONDEMANDTHRESHOLD, 99);
+ store.setDefault(PreferenceConstants.ORGIMPORTS_IGNORELOWERCASE, true);
+
+ // ClasspathVariablesPreferencePage
+ // CodeFormatterPreferencePage
+ // CompilerPreferencePage
+ // no initialization needed
+
+ // RefactoringPreferencePage
+ store.setDefault(
+ PreferenceConstants.REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD,
+ PreferenceConstants.REFACTOR_ERROR_SEVERITY);
+ store.setDefault(PreferenceConstants.REFACTOR_SAVE_ALL_EDITORS, false);
+ store.setDefault("RefactoringUI", "dialog");
+
+ // TemplatePreferencePage
+ store.setDefault(PreferenceConstants.TEMPLATES_USE_CODEFORMATTER, true);
+
+ // CodeGenerationPreferencePage
+ store.setDefault(PreferenceConstants.CODEGEN_USE_GETTERSETTER_PREFIX,
+ false);
+ store.setDefault(PreferenceConstants.CODEGEN_USE_GETTERSETTER_SUFFIX,
+ false);
+ store.setDefault(PreferenceConstants.CODEGEN_GETTERSETTER_PREFIX,
+ "fg, f, _$, _, m_"); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.CODEGEN_GETTERSETTER_SUFFIX, "_"); //$NON-NLS-1$
+
+ store.setDefault(PreferenceConstants.CODEGEN_KEYWORD_THIS, false);
+ store.setDefault(PreferenceConstants.CODEGEN_IS_FOR_GETTERS, true);
+ store.setDefault(PreferenceConstants.CODEGEN_EXCEPTION_VAR_NAME, "e"); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.CODEGEN_ADD_COMMENTS, true);
+ store.setDefault(PreferenceConstants.CODEGEN__NON_JAVADOC_COMMENTS,
+ false);
+ store.setDefault(PreferenceConstants.CODEGEN__FILE_COMMENTS, false);
+
+ // MembersOrderPreferencePage
+ store.setDefault(PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER,
+ "T,SF,SI,SM,I,F,C,M"); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER,
+ "B,V,R,D"); //$NON-NLS-1$
+ store.setDefault(
+ PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER,
+ false);
+ // must add here to guarantee that it is the first in the listener list
+ store.addPropertyChangeListener(WebUI.getDefault()
+ .getMemberOrderPreferenceCache());
+
+ store.setDefault(PreferenceConstants.EDITOR_MATCHING_BRACKETS, true);
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR, new RGB(
+ 192, 192, 192));
+
+ store.setDefault(PreferenceConstants.EDITOR_CURRENT_LINE, true);
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_CURRENT_LINE_COLOR, new RGB(225,
+ 235, 224));
+
+ store.setDefault(PreferenceConstants.EDITOR_PRINT_MARGIN, false);
+ store.setDefault(PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN, 80);
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR, new RGB(176,
+ 180, 185));
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_FIND_SCOPE_COLOR, new RGB(185, 176,
+ 180));
+
+ // store.setDefault(PreferenceConstants.EDITOR_PROBLEM_INDICATION,
+ // true);
+ // PreferenceConverter.setDefault(store,
+ // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR, new RGB(255, 0,
+ // 128));
+ // store.setDefault(PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER,
+ // true);
+ //
+ // store.setDefault(PreferenceConstants.EDITOR_WARNING_INDICATION,
+ // true);
+ // PreferenceConverter.setDefault(store,
+ // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR, new RGB(244,
+ // 200, 45));
+ // store.setDefault(PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER,
+ // true);
+ //
+ // store.setDefault(PreferenceConstants.EDITOR_TASK_INDICATION, false);
+ // PreferenceConverter.setDefault(store,
+ // PreferenceConstants.EDITOR_TASK_INDICATION_COLOR, new RGB(0, 128,
+ // 255));
+ // store.setDefault(PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER,
+ // false);
+ //
+ // store.setDefault(PreferenceConstants.EDITOR_BOOKMARK_INDICATION,
+ // false);
+ // PreferenceConverter.setDefault(store,
+ // PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR, new RGB(34,
+ // 164, 99));
+ // store.setDefault(PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
+ // false);
+ //
+ // store.setDefault(PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION,
+ // false);
+ // PreferenceConverter.setDefault(store,
+ // PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR, new
+ // RGB(192, 192, 192));
+ // store.setDefault(PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
+ // false);
+ //
+ // store.setDefault(PreferenceConstants.EDITOR_UNKNOWN_INDICATION,
+ // false);
+ // PreferenceConverter.setDefault(store,
+ // PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR, new RGB(0, 0,
+ // 0));
+ // store.setDefault(PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
+ // false);
+
+ store
+ .setDefault(PreferenceConstants.EDITOR_CORRECTION_INDICATION,
+ true);
+ store.setDefault(
+ PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE, true);
+
+ store.setDefault(PreferenceConstants.EDITOR_EVALUTE_TEMPORARY_PROBLEMS,
+ true);
+
+ store.setDefault(PreferenceConstants.EDITOR_OVERVIEW_RULER, true);
+
+ // WorkbenchChainedTextFontFieldEditor.startPropagate(store,
+ // JFaceResources.TEXT_FONT);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_LINKED_POSITION_COLOR, new RGB(0,
+ 200, 100));
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_LINK_COLOR, new RGB(0, 0, 255));
+
+ store.setDefault(PreferenceConstants.EDITOR_FOREGROUND_DEFAULT_COLOR,
+ true);
+
+ store.setDefault(PreferenceConstants.EDITOR_BACKGROUND_DEFAULT_COLOR,
+ true);
+
+ store.setDefault(PreferenceConstants.EDITOR_TAB_WIDTH, 4);
+ store.setDefault(PreferenceConstants.EDITOR_SPACES_FOR_TABS, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_COLOR, new RGB(
+ 63, 127, 95));
+ store.setDefault(PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_BOLD,
+ false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_COLOR, new RGB(
+ 63, 127, 95));
+ store.setDefault(PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_BOLD,
+ false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_PHP_TAG_COLOR, new RGB(255, 0, 128));
+ store.setDefault(PreferenceConstants.EDITOR_PHP_TAG_BOLD, true);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_JAVA_KEYWORD_COLOR, new RGB(127, 0,
+ 85));
+ store.setDefault(PreferenceConstants.EDITOR_JAVA_KEYWORD_BOLD, true);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_PHP_FUNCTIONNAME_COLOR, new RGB(127,
+ 127, 159));
+ store.setDefault(PreferenceConstants.EDITOR_PHP_FUNCTIONNAME_BOLD,
+ false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_PHP_VARIABLE_COLOR, new RGB(127,
+ 159, 191));
+ store.setDefault(PreferenceConstants.EDITOR_PHP_VARIABLE_BOLD, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_PHP_VARIABLE_DOLLAR_COLOR, new RGB(
+ 127, 159, 191));
+ store.setDefault(PreferenceConstants.EDITOR_PHP_VARIABLE_DOLLAR_BOLD,
+ false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_PHP_CONSTANT_COLOR, new RGB(127, 0,
+ 85));
+ store.setDefault(PreferenceConstants.EDITOR_PHP_CONSTANT_BOLD, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_PHP_TYPE_COLOR, new RGB(127, 0, 85));
+ store.setDefault(PreferenceConstants.EDITOR_PHP_TYPE_BOLD, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_STRING_COLOR_DQ,
+ PHPColorProvider.STRING_DQ);
+ store.setDefault(PreferenceConstants.EDITOR_STRING_BOLD_DQ, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_STRING_COLOR_SQ,
+ PHPColorProvider.STRING_SQ);
+ store.setDefault(PreferenceConstants.EDITOR_STRING_BOLD_SQ, true);
+
+ PreferenceConverter
+ .setDefault(store,
+ PreferenceConstants.EDITOR_JAVA_DEFAULT_COLOR, new RGB(
+ 0, 0, 0));
+ store.setDefault(PreferenceConstants.EDITOR_JAVA_DEFAULT_BOLD, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_JAVADOC_KEYWORD_COLOR, new RGB(127,
+ 159, 191));
+ store.setDefault(PreferenceConstants.EDITOR_JAVADOC_KEYWORD_BOLD, true);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_JAVADOC_TAG_COLOR, new RGB(127, 127,
+ 159));
+ store.setDefault(PreferenceConstants.EDITOR_JAVADOC_TAG_BOLD, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_JAVADOC_LINKS_COLOR, new RGB(63, 63,
+ 191));
+ store.setDefault(PreferenceConstants.EDITOR_JAVADOC_LINKS_BOLD, false);
+
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.EDITOR_JAVADOC_DEFAULT_COLOR, new RGB(63,
+ 95, 191));
+ store
+ .setDefault(PreferenceConstants.EDITOR_JAVADOC_DEFAULT_BOLD,
+ false);
+
+ store.setDefault(PreferenceConstants.CODEASSIST_AUTOACTIVATION, true);
+ store.setDefault(PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY,
+ 500);
+
+ store.setDefault(PreferenceConstants.CODEASSIST_AUTOINSERT, true);
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND, new RGB(
+ 254, 241, 233));
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND, new RGB(0,
+ 0, 0));
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.CODEASSIST_PARAMETERS_BACKGROUND, new RGB(
+ 254, 241, 233));
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.CODEASSIST_PARAMETERS_FOREGROUND, new RGB(
+ 0, 0, 0));
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.CODEASSIST_REPLACEMENT_BACKGROUND, new RGB(
+ 255, 255, 0));
+ PreferenceConverter.setDefault(store,
+ PreferenceConstants.CODEASSIST_REPLACEMENT_FOREGROUND, new RGB(
+ 255, 0, 0));
+ store.setDefault(
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA,
+ "$>"); //$NON-NLS-1$
+ store.setDefault(
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC,
+ "@"); //$NON-NLS-1$
+ store.setDefault(
+ PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_HTML,
+ "<"); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS,
+ true);
+ store
+ .setDefault(PreferenceConstants.CODEASSIST_CASE_SENSITIVITY,
+ false);
+ store.setDefault(PreferenceConstants.CODEASSIST_ORDER_PROPOSALS, false);
+ store.setDefault(PreferenceConstants.CODEASSIST_ADDIMPORT, true);
+ store
+ .setDefault(PreferenceConstants.CODEASSIST_INSERT_COMPLETION,
+ true);
+ store.setDefault(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES,
+ false);
+ store.setDefault(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS,
+ true);
+ store.setDefault(PreferenceConstants.CODEASSIST_PREFIX_COMPLETION,
+ false);
+
+ store.setDefault(PreferenceConstants.EDITOR_SMART_HOME_END, true);
+ store.setDefault(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION, true);
+ store.setDefault(PreferenceConstants.EDITOR_SMART_PASTE, true);
+ store.setDefault(PreferenceConstants.EDITOR_CLOSE_STRINGS_DQ_PHP, true);
+ store.setDefault(PreferenceConstants.EDITOR_CLOSE_STRINGS_SQ_PHP, true);
+ store.setDefault(PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP, true);
+ store.setDefault(PreferenceConstants.EDITOR_CLOSE_BRACES, true);
+ store.setDefault(PreferenceConstants.EDITOR_CLOSE_JAVADOCS, true);
+ store.setDefault(PreferenceConstants.EDITOR_WRAP_WORDS, false);
+ store.setDefault(PreferenceConstants.EDITOR_WRAP_STRINGS_DQ, true);
+ store.setDefault(PreferenceConstants.EDITOR_ESCAPE_STRINGS_DQ, false);
+ store.setDefault(PreferenceConstants.EDITOR_WRAP_STRINGS_SQ, true);
+ store.setDefault(PreferenceConstants.EDITOR_ESCAPE_STRINGS_SQ, false);
+ store.setDefault(PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS, true);
+ store.setDefault(PreferenceConstants.EDITOR_FORMAT_JAVADOCS, false);
+ store.setDefault(PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE,
+ false);
+
+ store.setDefault(PreferenceConstants.EDITOR_CLOSE_STRINGS_HTML, true);
+ store.setDefault(PreferenceConstants.EDITOR_CLOSE_BRACKETS_HTML, true);
+
+ // store.setDefault(PreferenceConstants.EDITOR_DEFAULT_HOVER,
+ // JavaPlugin.ID_BESTMATCH_HOVER);
+ store.setDefault(PreferenceConstants.EDITOR_NONE_HOVER,
+ PreferenceConstants.EDITOR_DEFAULT_HOVER_CONFIGURED_ID);
+ // store.setDefault(PreferenceConstants.EDITOR_CTRL_HOVER,
+ // JavaPlugin.ID_SOURCE_HOVER);
+ store.setDefault(PreferenceConstants.EDITOR_SHIFT_HOVER,
+ PreferenceConstants.EDITOR_DEFAULT_HOVER_CONFIGURED_ID);
+ store.setDefault(PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER,
+ PreferenceConstants.EDITOR_DEFAULT_HOVER_CONFIGURED_ID);
+ store.setDefault(PreferenceConstants.EDITOR_CTRL_ALT_HOVER,
+ PreferenceConstants.EDITOR_DEFAULT_HOVER_CONFIGURED_ID);
+ store.setDefault(PreferenceConstants.EDITOR_ALT_SHIFT_HOVER,
+ PreferenceConstants.EDITOR_DEFAULT_HOVER_CONFIGURED_ID);
+ store.setDefault(PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER,
+ PreferenceConstants.EDITOR_DEFAULT_HOVER_CONFIGURED_ID);
+
+ int modifier = SWT.CTRL;
+ if (Platform.getOS().equals(Platform.OS_MACOSX))
+ modifier = SWT.COMMAND;
+ String ctrl = Action.findModifierString(modifier);
+ store
+ .setDefault(
+ PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS,
+ "net.sourceforge.phpdt.ui.BestMatchHover;0;net.sourceforge.phpdt.ui.JavaSourceHover;" + ctrl); //$NON-NLS-1$
+ store
+ .setDefault(
+ PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS,
+ "net.sourceforge.phpdt.ui.BestMatchHover;0;net.sourceforge.phpdt.ui.JavaSourceHover;" + modifier); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE,
+ true);
+
+ store.setDefault(PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS, true);
+ store.setDefault(
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER,
+ ctrl);
+ store
+ .setDefault(
+ PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK,
+ modifier);
+
+ // mark occurrences
+ store.setDefault(PreferenceConstants.EDITOR_MARK_OCCURRENCES, true);
+ store.setDefault(PreferenceConstants.EDITOR_STICKY_OCCURRENCES, true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES,
+ // true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES,
+ // true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES,
+ // true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES,
+ // true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES,
+ // true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES,
+ // true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS,
+ // true);
+ // store.setDefault(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS, true);
+
+ // spell checking
+ store.setDefault(PreferenceConstants.SPELLING_CHECK_SPELLING, false);
+ store.setDefault(PreferenceConstants.SPELLING_LOCALE, SpellCheckEngine
+ .getDefaultLocale().toString());
+ store.setDefault(PreferenceConstants.SPELLING_IGNORE_DIGITS, true);
+ store.setDefault(PreferenceConstants.SPELLING_IGNORE_MIXED, true);
+ store.setDefault(PreferenceConstants.SPELLING_IGNORE_SENTENCE, true);
+ store.setDefault(PreferenceConstants.SPELLING_IGNORE_UPPER, true);
+ store.setDefault(PreferenceConstants.SPELLING_IGNORE_URLS, true);
+ store.setDefault(PreferenceConstants.SPELLING_USER_DICTIONARY, ""); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD, 20);
+ store.setDefault(PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST,
+ false);
+
+ // folding
+ store.setDefault(PreferenceConstants.EDITOR_FOLDING_ENABLED, true);
+ store.setDefault(PreferenceConstants.EDITOR_FOLDING_PROVIDER,
+ "net.sourceforge.phpdt.ui.text.defaultFoldingProvider"); //$NON-NLS-1$
+ store.setDefault(PreferenceConstants.EDITOR_FOLDING_JAVADOC, true);
+ store.setDefault(PreferenceConstants.EDITOR_FOLDING_INNERTYPES, true);
+ store.setDefault(PreferenceConstants.EDITOR_FOLDING_METHODS, false);
+ // store.setDefault(PreferenceConstants.EDITOR_FOLDING_IMPORTS, false);
+ store.setDefault(PreferenceConstants.EDITOR_FOLDING_HEADERS, true);
+
+ store.setDefault(PreferenceConstants.EDITOR_SMART_BACKSPACE, true);
+ store.setDefault(PreferenceConstants.EDITOR_P_RTRIM_ON_SAVE, false);
+ // do more complicated stuff
+ // NewJavaProjectPreferencePage.initDefaults(store);
+ }
+
+ /**
+ * Returns the JDT-UI preference store.
+ *
+ * @return the JDT-UI preference store
+ */
+ public static IPreferenceStore getPreferenceStore() {
+ return WebUI.getDefault().getPreferenceStore();
+ }
+
+ // /**
+ // * Encodes a JRE library to be used in the named preference
+ // NEWPROJECT_JRELIBRARY_LIST
.
+ // *
+ // * @param description a string value describing the JRE library. The
+ // description is used
+ // * to indentify the JDR library in the UI
+ // * @param entries an array of classpath entries to be encoded
+ // *
+ // * @return the encoded string.
+ // */
+ // public static String encodeJRELibrary(String description,
+ // IClasspathEntry[] entries) {
+ // return NewJavaProjectPreferencePage.encodeJRELibrary(description,
+ // entries);
+ // }
+ //
+ // /**
+ // * Decodes an encoded JRE library and returns its description string.
+ // *
+ // * @return the description of an encoded JRE library
+ // *
+ // * @see #encodeJRELibrary(String, IClasspathEntry[])
+ // */
+ // public static String decodeJRELibraryDescription(String encodedLibrary) {
+ // return
+ // NewJavaProjectPreferencePage.decodeJRELibraryDescription(encodedLibrary);
+ // }
+ //
+ // /**
+ // * Decodes an encoded JRE library and returns its classpath entries.
+ // *
+ // * @return the array of classpath entries of an encoded JRE library.
+ // *
+ // * @see #encodeJRELibrary(String, IClasspathEntry[])
+ // */
+ // public static IClasspathEntry[] decodeJRELibraryClasspathEntries(String
+ // encodedLibrary) {
+ // return
+ // NewJavaProjectPreferencePage.decodeJRELibraryClasspathEntries(encodedLibrary);
+ // }
+ //
+ // /**
+ // * Returns the current configuration for the JRE to be used as default in
+ // new Java projects.
+ // * This is a convenience method to access the named preference
+ // NEWPROJECT_JRELIBRARY_LIST
+ // *
with the index defined by
+ // NEWPROJECT_JRELIBRARY_INDEX
.
+ // *
+ // * @return the current default set of classpath entries
+ // *
+ // * @see #NEWPROJECT_JRELIBRARY_LIST
+ // * @see #NEWPROJECT_JRELIBRARY_INDEX
+ // */
+ // public static IClasspathEntry[] getDefaultJRELibrary() {
+ // return NewJavaProjectPreferencePage.getDefaultJRELibrary();
+ // }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/ProblemsLabelDecorator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/ProblemsLabelDecorator.java
new file mode 100644
index 0000000..2a48670
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/ProblemsLabelDecorator.java
@@ -0,0 +1,420 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.viewsupport.IProblemChangedListener;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ImageDescriptorRegistry;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ImageImageDescriptor;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+
+/**
+ * LabelDecorator that decorates an element's image with error and warning
+ * overlays that represent the severity of markers attached to the element's
+ * underlying resource. To see a problem decoration for a marker, the marker
+ * needs to be a subtype of IMarker.PROBLEM
.
+ *
+ * Note: Only images for elements in Java projects are currently updated on
+ * marker changes.
+ *
+ *
+ * @since 2.0
+ */
+public class ProblemsLabelDecorator implements ILabelDecorator,
+ ILightweightLabelDecorator {
+
+ /**
+ * This is a special LabelProviderChangedEvent
carring
+ * additional information whether the event orgins from a maker change.
+ *
+ * ProblemsLabelChangedEvent
s are only generated by
+ * ProblemsLabelDecorator
s.
+ *
+ */
+ public static class ProblemsLabelChangedEvent extends
+ LabelProviderChangedEvent {
+
+ private boolean fMarkerChange;
+
+ /**
+ * Note: This constructor is for internal use only. Clients should not
+ * call this constructor.
+ */
+ public ProblemsLabelChangedEvent(IBaseLabelProvider source,
+ IResource[] changedResource, boolean isMarkerChange) {
+ super(source, changedResource);
+ fMarkerChange = isMarkerChange;
+ }
+
+ /**
+ * Returns whether this event origins from marker changes. If
+ * false
an annotation model change is the origin. In
+ * this case viewers not displaying working copies can ignore these
+ * events.
+ *
+ * @return if this event origins from a marker change.
+ */
+ public boolean isMarkerChange() {
+ return fMarkerChange;
+ }
+
+ }
+
+ private static final int ERRORTICK_WARNING = JavaElementImageDescriptor.WARNING;
+
+ private static final int ERRORTICK_ERROR = JavaElementImageDescriptor.ERROR;
+
+ private ImageDescriptorRegistry fRegistry;
+
+ private boolean fUseNewRegistry = false;
+
+ private IProblemChangedListener fProblemChangedListener;
+
+ private ListenerList fListeners;
+
+ /**
+ * Creates a new ProblemsLabelDecorator
.
+ */
+ public ProblemsLabelDecorator() {
+ this(null);
+ fUseNewRegistry = true;
+ }
+
+ /*
+ * Creates decorator with a shared image registry.
+ *
+ * @param registry The registry to use or null
to use the
+ * Java plugin's image registry.
+ */
+ /**
+ * Note: This constructor is for internal use only. Clients should not call
+ * this constructor.
+ */
+ public ProblemsLabelDecorator(ImageDescriptorRegistry registry) {
+ fRegistry = registry;
+ fProblemChangedListener = null;
+ }
+
+ private ImageDescriptorRegistry getRegistry() {
+ if (fRegistry == null) {
+ fRegistry = fUseNewRegistry ? new ImageDescriptorRegistry()
+ : WebUI.getImageDescriptorRegistry();
+ }
+ return fRegistry;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelDecorator#decorateText(String, Object)
+ */
+ public String decorateText(String text, Object element) {
+ return text;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ILabelDecorator#decorateImage(Image, Object)
+ */
+ public Image decorateImage(Image image, Object obj) {
+ int adornmentFlags = computeAdornmentFlags(obj);
+ if (adornmentFlags != 0) {
+ ImageDescriptor baseImage = new ImageImageDescriptor(image);
+ Rectangle bounds = image.getBounds();
+ return getRegistry().get(
+ new JavaElementImageDescriptor(baseImage, adornmentFlags,
+ new Point(bounds.width, bounds.height)));
+ }
+ return image;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected int computeAdornmentFlags(Object obj) {
+ try {
+ if (obj instanceof IJavaElement) {
+ IJavaElement element = (IJavaElement) obj;
+ int type = element.getElementType();
+ switch (type) {
+ case IJavaElement.JAVA_PROJECT:
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+ return getErrorTicksFromMarkers(element.getResource(),
+ IResource.DEPTH_INFINITE, null);
+ case IJavaElement.PACKAGE_FRAGMENT:
+ case IJavaElement.CLASS_FILE:
+ return getErrorTicksFromMarkers(element.getResource(),
+ IResource.DEPTH_ONE, null);
+ case IJavaElement.COMPILATION_UNIT:
+ case IJavaElement.PACKAGE_DECLARATION:
+ case IJavaElement.IMPORT_DECLARATION:
+ case IJavaElement.IMPORT_CONTAINER:
+ case IJavaElement.TYPE:
+ case IJavaElement.INITIALIZER:
+ case IJavaElement.METHOD:
+ case IJavaElement.FIELD:
+ ICompilationUnit cu = (ICompilationUnit) element
+ .getAncestor(IJavaElement.COMPILATION_UNIT);
+ if (cu != null) {
+ ISourceReference ref = (type == IJavaElement.COMPILATION_UNIT) ? null
+ : (ISourceReference) element;
+ // The assumption is that only source elements in
+ // compilation unit can have markers
+ if (cu.isWorkingCopy()) {
+ // working copy: look at annotation model
+ return getErrorTicksFromWorkingCopy(
+ (ICompilationUnit) cu.getOriginalElement(),
+ ref);
+ }
+ return getErrorTicksFromMarkers(cu.getResource(),
+ IResource.DEPTH_ONE, ref);
+ }
+ break;
+ default:
+ }
+ } else if (obj instanceof IResource) {
+ return getErrorTicksFromMarkers((IResource) obj,
+ IResource.DEPTH_INFINITE, null);
+ }
+ } catch (CoreException e) {
+ if (e instanceof JavaModelException) {
+ if (((JavaModelException) e).isDoesNotExist()) {
+ return 0;
+ }
+ }
+ PHPeclipsePlugin.log(e);
+ }
+ return 0;
+ }
+
+ private int getErrorTicksFromMarkers(IResource res, int depth,
+ ISourceReference sourceElement) throws CoreException {
+ if (res == null || !res.isAccessible()) {
+ return 0;
+ }
+ int info = 0;
+
+ IMarker[] markers = res.findMarkers(IMarker.PROBLEM, true, depth);
+ if (markers != null) {
+ for (int i = 0; i < markers.length && (info != ERRORTICK_ERROR); i++) {
+ IMarker curr = markers[i];
+ if (sourceElement == null
+ || isMarkerInRange(curr, sourceElement)) {
+ int priority = curr.getAttribute(IMarker.SEVERITY, -1);
+ if (priority == IMarker.SEVERITY_WARNING) {
+ info = ERRORTICK_WARNING;
+ } else if (priority == IMarker.SEVERITY_ERROR) {
+ info = ERRORTICK_ERROR;
+ }
+ }
+ }
+ }
+ return info;
+ }
+
+ private boolean isMarkerInRange(IMarker marker,
+ ISourceReference sourceElement) throws CoreException {
+ if (marker.isSubtypeOf(IMarker.TEXT)) {
+ int pos = marker.getAttribute(IMarker.CHAR_START, -1);
+ return isInside(pos, sourceElement);
+ }
+ return false;
+ }
+
+ private int getErrorTicksFromWorkingCopy(ICompilationUnit original,
+ ISourceReference sourceElement) throws CoreException {
+ int info = 0;
+ FileEditorInput editorInput = new FileEditorInput((IFile) original
+ .getResource());
+ IAnnotationModel model = WebUI.getDefault()
+ .getCompilationUnitDocumentProvider().getAnnotationModel(
+ editorInput);
+ if (model != null) {
+ Iterator iter = model.getAnnotationIterator();
+ while ((info != ERRORTICK_ERROR) && iter.hasNext()) {
+ Annotation curr = (Annotation) iter.next();
+ IMarker marker = isAnnotationInRange(model, curr, sourceElement);
+ if (marker != null) {
+ int priority = marker.getAttribute(IMarker.SEVERITY, -1);
+ if (priority == IMarker.SEVERITY_WARNING) {
+ info = ERRORTICK_WARNING;
+ } else if (priority == IMarker.SEVERITY_ERROR) {
+ info = ERRORTICK_ERROR;
+ }
+ }
+ }
+ }
+ return info;
+ }
+
+ private IMarker isAnnotationInRange(IAnnotationModel model,
+ Annotation annot, ISourceReference sourceElement)
+ throws CoreException {
+ if (annot instanceof MarkerAnnotation) {
+ IMarker marker = ((MarkerAnnotation) annot).getMarker();
+ if (marker.exists() && marker.isSubtypeOf(IMarker.PROBLEM)) {
+ Position pos = model.getPosition(annot);
+ if (sourceElement == null
+ || isInside(pos.getOffset(), sourceElement)) {
+ return marker;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Tests if a position is inside the source range of an element.
+ *
+ * @param pos
+ * Position to be tested.
+ * @param sourceElement
+ * Source element (must be a IJavaElement)
+ * @return boolean Return true
if position is located inside
+ * the source element.
+ * @throws CoreException
+ * Exception thrown if element range could not be accessed.
+ *
+ * @since 2.1
+ */
+ protected boolean isInside(int pos, ISourceReference sourceElement)
+ throws CoreException {
+ ISourceRange range = sourceElement.getSourceRange();
+ if (range != null) {
+ int rangeOffset = range.getOffset();
+ return (rangeOffset <= pos && rangeOffset + range.getLength() > pos);
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#dispose()
+ */
+ public void dispose() {
+ if (fProblemChangedListener != null) {
+ WebUI.getDefault().getProblemMarkerManager()
+ .removeListener(fProblemChangedListener);
+ fProblemChangedListener = null;
+ }
+ if (fRegistry != null && fUseNewRegistry) {
+ fRegistry.dispose();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#isLabelProperty(Object, String)
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#addListener(ILabelProviderListener)
+ */
+ public void addListener(ILabelProviderListener listener) {
+ if (fListeners == null) {
+ fListeners = new ListenerList();
+ }
+ fListeners.add(listener);
+ if (fProblemChangedListener == null) {
+ fProblemChangedListener = new IProblemChangedListener() {
+ public void problemsChanged(IResource[] changedResources,
+ boolean isMarkerChange) {
+ fireProblemsChanged(changedResources, isMarkerChange);
+ }
+ };
+ WebUI.getDefault().getProblemMarkerManager()
+ .addListener(fProblemChangedListener);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ if (fListeners != null) {
+ fListeners.remove(listener);
+ if (fListeners.isEmpty() && fProblemChangedListener != null) {
+ WebUI.getDefault().getProblemMarkerManager()
+ .removeListener(fProblemChangedListener);
+ fProblemChangedListener = null;
+ }
+ }
+ }
+
+ private void fireProblemsChanged(IResource[] changedResources,
+ boolean isMarkerChange) {
+ if (fListeners != null && !fListeners.isEmpty()) {
+ LabelProviderChangedEvent event = new ProblemsLabelChangedEvent(
+ this, changedResources, isMarkerChange);
+ Object[] listeners = fListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ ((ILabelProviderListener) listeners[i])
+ .labelProviderChanged(event);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object,
+ * org.eclipse.jface.viewers.IDecoration)
+ */
+ public void decorate(Object element, IDecoration decoration) {
+ int adornmentFlags = computeAdornmentFlags(element);
+ if (adornmentFlags == ERRORTICK_ERROR) {
+ decoration.addOverlay(PHPUiImages.DESC_OVR_ERROR);
+ } else if (adornmentFlags == ERRORTICK_WARNING) {
+ decoration.addOverlay(PHPUiImages.DESC_OVR_WARNING);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/StandardJavaElementContentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/StandardJavaElementContentProvider.java
new file mode 100644
index 0000000..87d461c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/StandardJavaElementContentProvider.java
@@ -0,0 +1,511 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaElementDelta;
+import net.sourceforge.phpdt.core.IJavaModel;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * A base content provider for Java elements. It provides access to the Java
+ * element hierarchy without listening to changes in the Java model. If updating
+ * the presentation on Java model change is required than clients have to
+ * subclass, listen to Java model changes and have to update the UI using
+ * corresponding methods provided by the JFace viewers or their own UI
+ * presentation.
+ *
+ * The following Java element hierarchy is surfaced by this content provider:
+ *
+ *
+ *
+ * Java model (
+ *
+ * IJavaModel
+ *
+ * )
+ * Java project (
+ *
+ * IJavaProject
+ *
+ * )
+ * package fragment root (
+ *
+ * IPackageFragmentRoot
+ *
+ * )
+ * package fragment (
+ *
+ * IPackageFragment
+ *
+ * )
+ * compilation unit (
+ *
+ * ICompilationUnit
+ *
+ * )
+ * binary class file (
+ *
+ * IClassFile
+ *
+ * )
+ *
+ *
+ *
+ *
+ * Note that when the entire Java project is declared to be package fragment
+ * root, the corresponding package fragment root element that normally appears
+ * between the Java project and the package fragments is automatically filtered
+ * out.
+ *
+ * This content provider can optionally return working copy elements for members
+ * below compilation units. If enabled, working copy members are returned for
+ * those compilation units in the Java element hierarchy for which a shared
+ * working copy exists in JDT core.
+ *
+ * @see net.sourceforge.phpdt.ui.IWorkingCopyProvider
+ * @see JavaCore#getSharedWorkingCopies(net.sourceforge.phpdt.core.IBufferFactory)
+ *
+ * @since 2.0
+ */
+public class StandardJavaElementContentProvider implements
+ ITreeContentProvider, IWorkingCopyProvider {
+
+ protected static final Object[] NO_CHILDREN = new Object[0];
+
+ protected boolean fProvideMembers = false;
+
+ protected boolean fProvideWorkingCopy = false;
+
+ /**
+ * Creates a new content provider. The content provider does not provide
+ * members of compilation units or class files and it does not provide
+ * working copy elements.
+ */
+ public StandardJavaElementContentProvider() {
+ }
+
+ /**
+ * Creates a new StandardJavaElementContentProvider
.
+ *
+ * @param provideMembers
+ * if true
members below compilation units and
+ * class files are provided.
+ * @param provideWorkingCopy
+ * if true
the element provider provides working
+ * copies members of compilation units which have an associated
+ * working copy in JDT core. Otherwise only original elements are
+ * provided.
+ */
+ public StandardJavaElementContentProvider(boolean provideMembers,
+ boolean provideWorkingCopy) {
+ fProvideMembers = provideMembers;
+ fProvideWorkingCopy = provideWorkingCopy;
+ }
+
+ /**
+ * Returns whether members are provided when asking for a compilation units
+ * or class file for its children.
+ *
+ * @return true
if the content provider provides members;
+ * otherwise false
is returned
+ */
+ public boolean getProvideMembers() {
+ return fProvideMembers;
+ }
+
+ /**
+ * Sets whether the content provider is supposed to return members when
+ * asking a compilation unit or class file for its children.
+ *
+ * @param b
+ * if true
then members are provided. If
+ * false
compilation units and class files are the
+ * leaves provided by this content provider.
+ */
+ public void setProvideMembers(boolean b) {
+ fProvideMembers = b;
+ }
+
+ /**
+ * Returns whether the provided members are from a working copy or the
+ * original compilation unit.
+ *
+ * @return true
if the content provider provides working copy
+ * members; otherwise false
is returned
+ *
+ * @see #setProvideWorkingCopy(boolean)
+ */
+ public boolean getProvideWorkingCopy() {
+ return fProvideWorkingCopy;
+ }
+
+ /**
+ * Sets whether the members are provided from a shared working copy that
+ * exists for a original compilation unit in the Java element hierarchy.
+ *
+ * @param b
+ * if true
members are provided from a working
+ * copy if one exists in JDT core. If false
the
+ * provider always returns original elements.
+ */
+ public void setProvideWorkingCopy(boolean b) {
+ fProvideWorkingCopy = b;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IWorkingCopyProvider#providesWorkingCopies()
+ */
+ public boolean providesWorkingCopies() {
+ return fProvideWorkingCopy;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IStructuredContentProvider.
+ */
+ public Object[] getElements(Object parent) {
+ return getChildren(parent);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentProvider.
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentProvider.
+ */
+ public void dispose() {
+ }
+
+ /*
+ * (non-Javadoc) Method declared on ITreeContentProvider.
+ */
+ public Object[] getChildren(Object element) {
+ if (!exists(element))
+ return NO_CHILDREN;
+
+ try {
+ if (element instanceof IJavaModel)
+ return getJavaProjects((IJavaModel) element);
+
+ // if (element instanceof IJavaProject)
+ // return getPackageFragmentRoots((IJavaProject)element);
+ //
+ if (element instanceof IPackageFragmentRoot)
+ return getPackageFragments((IPackageFragmentRoot) element);
+
+ // if (element instanceof IPackageFragment)
+ // return getPackageContents((IPackageFragment)element);
+
+ if (element instanceof IFolder)
+ return getResources((IFolder) element);
+
+ if (fProvideMembers && element instanceof ISourceReference
+ && element instanceof IParent) {
+ if (fProvideWorkingCopy && element instanceof ICompilationUnit) {
+ element = JavaModelUtil
+ .toWorkingCopy((ICompilationUnit) element);
+ }
+ return ((IParent) element).getChildren();
+ }
+ } catch (JavaModelException e) {
+ return NO_CHILDREN;
+ }
+ return NO_CHILDREN;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ITreeContentProvider
+ */
+ public boolean hasChildren(Object element) {
+ if (fProvideMembers) {
+ // assume CUs and class files are never empty
+ if (element instanceof ICompilationUnit) {
+ // ||
+ // element instanceof IClassFile) {
+ return true;
+ }
+ } else {
+ // don't allow to drill down into a compilation unit or class file
+ if (element instanceof ICompilationUnit ||
+ // element instanceof IClassFile ||
+ element instanceof IFile)
+ return false;
+ }
+
+ if (element instanceof IJavaProject) {
+ IJavaProject jp = (IJavaProject) element;
+ if (!jp.getProject().isOpen()) {
+ return false;
+ }
+ }
+
+ if (element instanceof IParent) {
+ try {
+ // when we have Java children return true, else we fetch all the
+ // children
+ if (((IParent) element).hasChildren())
+ return true;
+ } catch (JavaModelException e) {
+ return true;
+ }
+ }
+ Object[] children = getChildren(element);
+ return (children != null) && children.length > 0;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on ITreeContentProvider.
+ */
+ public Object getParent(Object element) {
+ if (!exists(element))
+ return null;
+ return internalGetParent(element);
+ }
+
+ private Object[] getPackageFragments(IPackageFragmentRoot root)
+ throws JavaModelException {
+ IJavaElement[] fragments = root.getChildren();
+ // Object[] nonJavaResources= root.getNonJavaResources();
+ // if (nonJavaResources == null)
+ return fragments;
+ // return concatenate(fragments, nonJavaResources);
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ // protected Object[] getPackageFragmentRoots(IJavaProject project) throws
+ // JavaModelException {
+ // if (!project.getProject().isOpen())
+ // return NO_CHILDREN;
+ //
+ // IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
+ // List list= new ArrayList(roots.length);
+ // // filter out package fragments that correspond to projects and
+ // // replace them with the package fragments directly
+ // for (int i= 0; i < roots.length; i++) {
+ // IPackageFragmentRoot root= (IPackageFragmentRoot)roots[i];
+ // if (isProjectPackageFragmentRoot(root)) {
+ // Object[] children= root.getChildren();
+ // for (int k= 0; k < children.length; k++)
+ // list.add(children[k]);
+ // }
+ // else if (hasChildren(root)) {
+ // list.add(root);
+ // }
+ // }
+ // return concatenate(list.toArray(), project.getNonJavaResources());
+ // }
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected Object[] getJavaProjects(IJavaModel jm) throws JavaModelException {
+ return jm.getJavaProjects();
+ }
+
+ // private Object[] getPackageContents(IPackageFragment fragment) throws
+ // JavaModelException {
+ // if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
+ // return concatenate(fragment.getCompilationUnits(),
+ // fragment.getNonJavaResources());
+ // }
+ // return concatenate(fragment.getClassFiles(),
+ // fragment.getNonJavaResources());
+ // }
+
+ private Object[] getResources(IFolder folder) {
+ try {
+ // filter out folders that are package fragment roots
+ Object[] members = folder.members();
+ List nonJavaResources = new ArrayList();
+ for (int i = 0; i < members.length; i++) {
+ Object o = members[i];
+ // A folder can also be a package fragement root in the
+ // following case
+ // Project
+ // + src <- source folder
+ // + excluded <- excluded from class path
+ // + included <- a new source folder.
+ // Included is a member of excluded, but since it is rendered as
+ // a source
+ // folder we have to exclude it as a normal child.
+ if (o instanceof IFolder) {
+ IJavaElement element = JavaCore.create((IFolder) o);
+ if (element instanceof IPackageFragmentRoot
+ && element.exists()) {
+ continue;
+ }
+ }
+ nonJavaResources.add(o);
+ }
+ return nonJavaResources.toArray();
+ } catch (CoreException e) {
+ return NO_CHILDREN;
+ }
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected boolean isClassPathChange(IJavaElementDelta delta) {
+
+ // need to test the flags only for package fragment roots
+ if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT)
+ return false;
+
+ int flags = delta.getFlags();
+ return (delta.getKind() == IJavaElementDelta.CHANGED
+ && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0)
+ || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REORDER) != 0));
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected Object skipProjectPackageFragmentRoot(IPackageFragmentRoot root) {
+ try {
+ if (isProjectPackageFragmentRoot(root))
+ return root.getParent();
+ return root;
+ } catch (JavaModelException e) {
+ return root;
+ }
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected boolean isPackageFragmentEmpty(IJavaElement element)
+ throws JavaModelException {
+ if (element instanceof IPackageFragment) {
+ IPackageFragment fragment = (IPackageFragment) element;
+ if (!(fragment.hasChildren()))
+ // ||
+ // fragment.getNonJavaResources().length > 0) &&
+ // fragment.hasSubpackages())
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected boolean isProjectPackageFragmentRoot(IPackageFragmentRoot root)
+ throws JavaModelException {
+ IResource resource = root.getResource();
+ return (resource instanceof IProject);
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected boolean exists(Object element) {
+ if (element == null) {
+ return false;
+ }
+ if (element instanceof IResource) {
+ return ((IResource) element).exists();
+ }
+ if (element instanceof IJavaElement) {
+ return ((IJavaElement) element).exists();
+ }
+ return true;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected Object internalGetParent(Object element) {
+ if (element instanceof IJavaProject) {
+ return ((IJavaProject) element).getJavaModel();
+ }
+ // try to map resources to the containing package fragment
+ if (element instanceof IResource) {
+ IResource parent = ((IResource) element).getParent();
+ IJavaElement jParent = JavaCore.create(parent);
+ // http://bugs.eclipse.org/bugs/show_bug.cgi?id=31374
+ if (jParent != null && jParent.exists())
+ return jParent;
+ return parent;
+ }
+
+ // for package fragments that are contained in a project package
+ // fragment
+ // we have to skip the package fragment root as the parent.
+ if (element instanceof IPackageFragment) {
+ IPackageFragmentRoot parent = (IPackageFragmentRoot) ((IPackageFragment) element)
+ .getParent();
+ return skipProjectPackageFragmentRoot(parent);
+ }
+ if (element instanceof IJavaElement) {
+ IJavaElement candidate = ((IJavaElement) element).getParent();
+ // If the parent is a CU we might have shown working copy elements
+ // below CU level. If so
+ // return the original element instead of the working copy.
+ if (candidate != null
+ && candidate.getElementType() == IJavaElement.COMPILATION_UNIT) {
+ candidate = JavaModelUtil
+ .toOriginal((ICompilationUnit) candidate);
+ }
+ return candidate;
+ }
+ return null;
+ }
+
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ protected static Object[] concatenate(Object[] a1, Object[] a2) {
+ int a1Len = a1.length;
+ int a2Len = a2.length;
+ Object[] res = new Object[a1Len + a2Len];
+ System.arraycopy(a1, 0, res, 0, a1Len);
+ System.arraycopy(a2, 0, res, a1Len, a2Len);
+ return res;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/CustomFiltersActionGroup.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/CustomFiltersActionGroup.java
new file mode 100644
index 0000000..f4ed17d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/CustomFiltersActionGroup.java
@@ -0,0 +1,811 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.actions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.Stack;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+import net.sourceforge.phpdt.core.IJavaModel;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.filters.CustomFiltersDialog;
+import net.sourceforge.phpdt.internal.ui.filters.FilterDescriptor;
+import net.sourceforge.phpdt.internal.ui.filters.FilterMessages;
+import net.sourceforge.phpdt.internal.ui.filters.NamePatternFilter;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+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.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.actions.ActionGroup;
+
+/**
+ * Action group to add the filter action to a view part's tool bar menu.
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class CustomFiltersActionGroup extends ActionGroup {
+
+ class ShowFilterDialogAction extends Action {
+ ShowFilterDialogAction() {
+ setText(FilterMessages
+ .getString("OpenCustomFiltersDialogAction.text")); //$NON-NLS-1$
+ setImageDescriptor(PHPUiImages.DESC_ELCL_FILTER);
+ setDisabledImageDescriptor(PHPUiImages.DESC_DLCL_FILTER);
+ }
+
+ public void run() {
+ openDialog();
+ }
+ }
+
+ /**
+ * Menu contribution item which shows and lets check and uncheck filters.
+ *
+ * @since 3.0
+ */
+ class FilterActionMenuContributionItem extends ContributionItem {
+
+ private int fItemNumber;
+
+ private boolean fState;
+
+ private String fFilterId;
+
+ private String fFilterName;
+
+ private CustomFiltersActionGroup fActionGroup;
+
+ /**
+ * Constructor for FilterActionMenuContributionItem.
+ *
+ * @param actionGroup
+ * the action group
+ * @param filterId
+ * the id of the filter
+ * @param filterName
+ * the name of the filter
+ * @param state
+ * the initial state of the filter
+ * @param itemNumber
+ * the menu item index
+ */
+ public FilterActionMenuContributionItem(
+ CustomFiltersActionGroup actionGroup, String filterId,
+ String filterName, boolean state, int itemNumber) {
+ super(filterId);
+ Assert.isNotNull(actionGroup);
+ Assert.isNotNull(filterId);
+ Assert.isNotNull(filterName);
+ fActionGroup = actionGroup;
+ fFilterId = filterId;
+ fFilterName = filterName;
+ fState = state;
+ fItemNumber = itemNumber;
+ }
+
+ /*
+ * Overrides method from ContributionItem.
+ */
+ public void fill(Menu menu, int index) {
+ MenuItem mi = new MenuItem(menu, SWT.CHECK, index);
+ mi.setText("&" + fItemNumber + " " + fFilterName); //$NON-NLS-1$ //$NON-NLS-2$
+ /*
+ * XXX: Don't set the image - would look bad because other menu
+ * items don't provide image XXX: Get working set specific image
+ * name from XML - would need to cache icons
+ */
+ // mi.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_JAVA_WORKING_SET));
+ mi.setSelection(fState);
+ mi.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ fState = !fState;
+ fActionGroup.setFilter(fFilterId, fState);
+ }
+ });
+ }
+
+ /*
+ * @see org.eclipse.jface.action.IContributionItem#isDynamic()
+ */
+ public boolean isDynamic() {
+ return true;
+ }
+ }
+
+ private static final String TAG_CUSTOM_FILTERS = "customFilters"; //$NON-NLS-1$
+
+ private static final String TAG_USER_DEFINED_PATTERNS_ENABLED = "userDefinedPatternsEnabled"; //$NON-NLS-1$
+
+ private static final String TAG_USER_DEFINED_PATTERNS = "userDefinedPatterns"; //$NON-NLS-1$
+
+ private static final String TAG_XML_DEFINED_FILTERS = "xmlDefinedFilters"; //$NON-NLS-1$
+
+ private static final String TAG_LRU_FILTERS = "lastRecentlyUsedFilters"; //$NON-NLS-1$
+
+ private static final String TAG_CHILD = "child"; //$NON-NLS-1$
+
+ private static final String TAG_PATTERN = "pattern"; //$NON-NLS-1$
+
+ private static final String TAG_FILTER_ID = "filterId"; //$NON-NLS-1$
+
+ private static final String TAG_IS_ENABLED = "isEnabled"; //$NON-NLS-1$
+
+ private static final String SEPARATOR = ","; //$NON-NLS-1$
+
+ private static final int MAX_FILTER_MENU_ENTRIES = 3;
+
+ private static final String RECENT_FILTERS_GROUP_NAME = "recentFiltersGroup"; //$NON-NLS-1$
+
+ private StructuredViewer fViewer;
+
+ private NamePatternFilter fPatternFilter;
+
+ private Map fInstalledBuiltInFilters;
+
+ private Map fEnabledFilterIds;
+
+ private boolean fUserDefinedPatternsEnabled;
+
+ private String[] fUserDefinedPatterns;
+
+ /**
+ * Recently changed filter Ids stack with oldest on top (i.e. at the end).
+ *
+ * @since 3.0
+ */
+ private Stack fLRUFilterIdsStack;
+
+ /**
+ * Handle to menu manager to dynamically update the last recently used
+ * filters.
+ *
+ * @since 3.0
+ */
+ private IMenuManager fMenuManager;
+
+ /**
+ * The menu listener which dynamically updates the last recently used
+ * filters.
+ *
+ * @since 3.0
+ */
+ private IMenuListener fMenuListener;
+
+ /**
+ * Filter Ids used in the last view menu invocation.
+ *
+ * @since 3.0
+ */
+ private String[] fFilterIdsUsedInLastViewMenu;
+
+ private HashMap fFilterDescriptorMap;
+
+ private String fTargetId;
+
+ /**
+ * Creates a new CustomFiltersActionGroup
.
+ *
+ * @param part
+ * the view part that owns this action group
+ * @param viewer
+ * the viewer to be filtered
+ */
+ public CustomFiltersActionGroup(IViewPart part, StructuredViewer viewer) {
+ this(part.getViewSite().getId(), viewer);
+ }
+
+ /**
+ * Creates a new CustomFiltersActionGroup
.
+ *
+ * @param ownerId
+ * the id of this action group's owner
+ * @param viewer
+ * the viewer to be filtered
+ */
+ public CustomFiltersActionGroup(String ownerId, StructuredViewer viewer) {
+ Assert.isNotNull(ownerId);
+ Assert.isNotNull(viewer);
+ fTargetId = ownerId;
+ fViewer = viewer;
+
+ fLRUFilterIdsStack = new Stack();
+
+ initializeWithPluginContributions();
+ initializeWithViewDefaults();
+
+ installFilters();
+ }
+
+ /*
+ * Method declared on ActionGroup.
+ */
+ public void fillActionBars(IActionBars actionBars) {
+ fillToolBar(actionBars.getToolBarManager());
+ fillViewMenu(actionBars.getMenuManager());
+ }
+
+ public String[] removeFiltersFor(Object parent, Object element,
+ IContentProvider contentProvider) {
+ String[] enabledFilters = getEnabledFilterIds();
+ Set newFilters = new HashSet();
+ for (int i = 0; i < enabledFilters.length; i++) {
+ String filterName = enabledFilters[i];
+ ViewerFilter filter = (ViewerFilter) fInstalledBuiltInFilters
+ .get(filterName);
+ if (filter == null)
+ newFilters.add(filterName);
+ else if (isSelected(parent, element, contentProvider, filter))
+ newFilters.add(filterName);
+ }
+ if (newFilters.size() == enabledFilters.length)
+ return new String[0];
+ return (String[]) newFilters.toArray(new String[newFilters.size()]);
+ }
+
+ public void setFilters(String[] newFilters) {
+ setEnabledFilterIds(newFilters);
+ updateViewerFilters(true);
+ }
+
+ private boolean isSelected(Object parent, Object element,
+ IContentProvider contentProvider, ViewerFilter filter) {
+ if (contentProvider instanceof ITreeContentProvider) {
+ // the element and all its parents have to be selected
+ ITreeContentProvider provider = (ITreeContentProvider) contentProvider;
+ while (element != null && !(element instanceof IJavaModel)) {
+ if (!filter.select(fViewer, parent, element))
+ return false;
+ element = provider.getParent(element);
+ }
+ return true;
+ }
+ return filter.select(fViewer, parent, element);
+ }
+
+ /**
+ * Sets the enable state of the given filter.
+ *
+ * @param filterId
+ * the id of the filter
+ * @param state
+ * the filter state
+ */
+ private void setFilter(String filterId, boolean state) {
+ // Renew filter id in LRU stack
+ fLRUFilterIdsStack.remove(filterId);
+ fLRUFilterIdsStack.add(0, filterId);
+
+ fEnabledFilterIds.put(filterId, new Boolean(state));
+ storeViewDefaults();
+
+ updateViewerFilters(true);
+ }
+
+ private String[] getEnabledFilterIds() {
+ Set enabledFilterIds = new HashSet(fEnabledFilterIds.size());
+ Iterator iter = fEnabledFilterIds.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String id = (String) entry.getKey();
+ boolean isEnabled = ((Boolean) entry.getValue()).booleanValue();
+ if (isEnabled)
+ enabledFilterIds.add(id);
+ }
+ return (String[]) enabledFilterIds.toArray(new String[enabledFilterIds
+ .size()]);
+ }
+
+ private void setEnabledFilterIds(String[] enabledIds) {
+ Iterator iter = fEnabledFilterIds.keySet().iterator();
+ while (iter.hasNext()) {
+ String id = (String) iter.next();
+ fEnabledFilterIds.put(id, Boolean.FALSE);
+ }
+ for (int i = 0; i < enabledIds.length; i++)
+ fEnabledFilterIds.put(enabledIds[i], Boolean.TRUE);
+ }
+
+ private void setUserDefinedPatterns(String[] patterns) {
+ fUserDefinedPatterns = patterns;
+ cleanUpPatternDuplicates();
+ }
+
+ /**
+ * Sets the recently changed filters.
+ *
+ * @param changeHistory
+ * the change history
+ * @since 3.0
+ */
+ private void setRecentlyChangedFilters(Stack changeHistory) {
+ Stack oldestFirstStack = new Stack();
+
+ int length = Math.min(changeHistory.size(), MAX_FILTER_MENU_ENTRIES);
+ for (int i = 0; i < length; i++)
+ oldestFirstStack.push(((FilterDescriptor) changeHistory.pop())
+ .getId());
+
+ length = Math.min(fLRUFilterIdsStack.size(), MAX_FILTER_MENU_ENTRIES
+ - oldestFirstStack.size());
+ int NEWEST = 0;
+ for (int i = 0; i < length; i++) {
+ Object filter = fLRUFilterIdsStack.remove(NEWEST);
+ if (!oldestFirstStack.contains(filter))
+ oldestFirstStack.push(filter);
+ }
+ fLRUFilterIdsStack = oldestFirstStack;
+ }
+
+ private boolean areUserDefinedPatternsEnabled() {
+ return fUserDefinedPatternsEnabled;
+ }
+
+ private void setUserDefinedPatternsEnabled(boolean state) {
+ fUserDefinedPatternsEnabled = state;
+ }
+
+ private void fillToolBar(IToolBarManager tooBar) {
+ }
+
+ /**
+ * Fills the given view menu with the entries managed by the group.
+ *
+ * @param viewMenu
+ * the menu to fill
+ */
+ public void fillViewMenu(IMenuManager viewMenu) {
+ /*
+ * Don't change the separator group name. Using this name ensures that
+ * other filters get contributed to the same group.
+ */
+ viewMenu.add(new Separator("filters")); //$NON-NLS-1$
+ viewMenu.add(new GroupMarker(RECENT_FILTERS_GROUP_NAME));
+ viewMenu.add(new ShowFilterDialogAction());
+
+ fMenuManager = viewMenu;
+ fMenuListener = new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ removePreviousLRUFilterActions(manager);
+ addLRUFilterActions(manager);
+ }
+ };
+ fMenuManager.addMenuListener(fMenuListener);
+ }
+
+ private void removePreviousLRUFilterActions(IMenuManager mm) {
+ if (fFilterIdsUsedInLastViewMenu == null)
+ return;
+
+ for (int i = 0; i < fFilterIdsUsedInLastViewMenu.length; i++)
+ mm.remove(fFilterIdsUsedInLastViewMenu[i]);
+ }
+
+ private void addLRUFilterActions(IMenuManager mm) {
+ if (fLRUFilterIdsStack.isEmpty()) {
+ fFilterIdsUsedInLastViewMenu = null;
+ return;
+ }
+
+ SortedSet sortedFilters = new TreeSet(fLRUFilterIdsStack);
+ String[] recentlyChangedFilterIds = (String[]) sortedFilters
+ .toArray(new String[sortedFilters.size()]);
+
+ fFilterIdsUsedInLastViewMenu = new String[recentlyChangedFilterIds.length];
+ for (int i = 0; i < recentlyChangedFilterIds.length; i++) {
+ String id = recentlyChangedFilterIds[i];
+ fFilterIdsUsedInLastViewMenu[i] = id;
+ boolean state = fEnabledFilterIds.containsKey(id)
+ && ((Boolean) fEnabledFilterIds.get(id)).booleanValue();
+ FilterDescriptor filterDesc = (FilterDescriptor) fFilterDescriptorMap
+ .get(id);
+ if (filterDesc != null) {
+ IContributionItem item = new FilterActionMenuContributionItem(
+ this, id, filterDesc.getName(), state, i + 1);
+ mm.insertBefore(RECENT_FILTERS_GROUP_NAME, item);
+ }
+ }
+ }
+
+ /*
+ * Method declared on ActionGroup.
+ */
+ public void dispose() {
+ if (fMenuManager != null)
+ fMenuManager.removeMenuListener(fMenuListener);
+ super.dispose();
+ }
+
+ private void initializeWithPluginContributions() {
+ fUserDefinedPatterns = new String[0];
+ fUserDefinedPatternsEnabled = false;
+
+ FilterDescriptor[] filterDescs = FilterDescriptor
+ .getFilterDescriptors(fTargetId);
+ fFilterDescriptorMap = new HashMap(filterDescs.length);
+ fEnabledFilterIds = new HashMap(filterDescs.length);
+ for (int i = 0; i < filterDescs.length; i++) {
+ String id = filterDescs[i].getId();
+ Boolean isEnabled = new Boolean(filterDescs[i].isEnabled());
+ if (fEnabledFilterIds.containsKey(id))
+ WebUI
+ .logErrorMessage("WARNING: Duplicate id for extension-point \"net.sourceforge.phpdt.ui.javaElementFilters\""); //$NON-NLS-1$
+ fEnabledFilterIds.put(id, isEnabled);
+ fFilterDescriptorMap.put(id, filterDescs[i]);
+ }
+ }
+
+ // ---------- viewer filter handling ----------
+
+ private void installFilters() {
+ fInstalledBuiltInFilters = new HashMap(fEnabledFilterIds.size());
+ fPatternFilter = new NamePatternFilter();
+ fPatternFilter.setPatterns(getUserAndBuiltInPatterns());
+ fViewer.addFilter(fPatternFilter);
+ updateBuiltInFilters();
+ }
+
+ private void updateViewerFilters(boolean refresh) {
+ String[] patterns = getUserAndBuiltInPatterns();
+ fPatternFilter.setPatterns(patterns);
+ fViewer.getControl().setRedraw(false);
+ updateBuiltInFilters();
+ if (refresh)
+ fViewer.refresh();
+ fViewer.getControl().setRedraw(true);
+ }
+
+ private void updateBuiltInFilters() {
+ Set installedFilters = fInstalledBuiltInFilters.keySet();
+ Set filtersToAdd = new HashSet(fEnabledFilterIds.size());
+ Set filtersToRemove = new HashSet(fEnabledFilterIds.size());
+ Iterator iter = fEnabledFilterIds.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String id = (String) entry.getKey();
+ boolean isEnabled = ((Boolean) entry.getValue()).booleanValue();
+ if (isEnabled && !installedFilters.contains(id))
+ filtersToAdd.add(id);
+ else if (!isEnabled && installedFilters.contains(id))
+ filtersToRemove.add(id);
+ }
+
+ // Install the filters
+ FilterDescriptor[] filterDescs = FilterDescriptor
+ .getFilterDescriptors(fTargetId);
+ for (int i = 0; i < filterDescs.length; i++) {
+ String id = filterDescs[i].getId();
+ // just to double check - id should denote a custom filter anyway
+ boolean isCustomFilter = filterDescs[i].isCustomFilter();
+ if (isCustomFilter) {
+ if (filtersToAdd.contains(id)) {
+ ViewerFilter filter = filterDescs[i].createViewerFilter();
+ if (filter != null) {
+ fViewer.addFilter(filter);
+ fInstalledBuiltInFilters.put(id, filter);
+ }
+ }
+ if (filtersToRemove.contains(id)) {
+ fViewer
+ .removeFilter((ViewerFilter) fInstalledBuiltInFilters
+ .get(id));
+ fInstalledBuiltInFilters.remove(id);
+ }
+ }
+ }
+ }
+
+ private String[] getUserAndBuiltInPatterns() {
+ List patterns = new ArrayList(fUserDefinedPatterns.length);
+ if (areUserDefinedPatternsEnabled())
+ patterns.addAll(Arrays.asList(fUserDefinedPatterns));
+ FilterDescriptor[] filterDescs = FilterDescriptor
+ .getFilterDescriptors(fTargetId);
+ for (int i = 0; i < filterDescs.length; i++) {
+ String id = filterDescs[i].getId();
+ boolean isPatternFilter = filterDescs[i].isPatternFilter();
+ Object isEnabled = fEnabledFilterIds.get(id);
+ if (isEnabled != null && isPatternFilter
+ && ((Boolean) isEnabled).booleanValue())
+ patterns.add(filterDescs[i].getPattern());
+ }
+ return (String[]) patterns.toArray(new String[patterns.size()]);
+ }
+
+ // ---------- view kind/defaults persistency ----------
+
+ private void initializeWithViewDefaults() {
+ // get default values for view
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+
+ // XXX: can be removed once bug 22533 is fixed.
+ if (!store.contains(getPreferenceKey("TAG_DUMMY_TO_TEST_EXISTENCE")))//$NON-NLS-1$
+ return;
+
+ // XXX: Uncomment once bug 22533 is fixed.
+ // if
+ // (!store.contains(getPreferenceKey(TAG_USER_DEFINED_PATTERNS_ENABLED)))
+ // return;
+
+ fUserDefinedPatternsEnabled = store
+ .getBoolean(getPreferenceKey(TAG_USER_DEFINED_PATTERNS_ENABLED));
+ setUserDefinedPatterns(CustomFiltersDialog.convertFromString(store
+ .getString(getPreferenceKey(TAG_USER_DEFINED_PATTERNS)),
+ SEPARATOR));
+
+ Iterator iter = fEnabledFilterIds.keySet().iterator();
+ while (iter.hasNext()) {
+ String id = (String) iter.next();
+ Boolean isEnabled = new Boolean(store.getBoolean(id));
+ fEnabledFilterIds.put(id, isEnabled);
+ }
+
+ fLRUFilterIdsStack.clear();
+ String lruFilterIds = store.getString(TAG_LRU_FILTERS);
+ StringTokenizer tokenizer = new StringTokenizer(lruFilterIds, SEPARATOR);
+ while (tokenizer.hasMoreTokens()) {
+ String id = tokenizer.nextToken();
+ if (fFilterDescriptorMap.containsKey(id)
+ && !fLRUFilterIdsStack.contains(id))
+ fLRUFilterIdsStack.push(id);
+ }
+ }
+
+ private void storeViewDefaults() {
+ // get default values for view
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+
+ // XXX: can be removed once bug 22533 is fixed.
+ store
+ .setValue(
+ getPreferenceKey("TAG_DUMMY_TO_TEST_EXISTENCE"), "storedViewPreferences");//$NON-NLS-1$//$NON-NLS-2$
+
+ store.setValue(getPreferenceKey(TAG_USER_DEFINED_PATTERNS_ENABLED),
+ fUserDefinedPatternsEnabled);
+ store.setValue(getPreferenceKey(TAG_USER_DEFINED_PATTERNS),
+ CustomFiltersDialog.convertToString(fUserDefinedPatterns,
+ SEPARATOR));
+
+ Iterator iter = fEnabledFilterIds.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String id = (String) entry.getKey();
+ boolean isEnabled = ((Boolean) entry.getValue()).booleanValue();
+ store.setValue(id, isEnabled);
+ }
+
+ StringBuffer buf = new StringBuffer(fLRUFilterIdsStack.size() * 20);
+ iter = fLRUFilterIdsStack.iterator();
+ while (iter.hasNext()) {
+ buf.append((String) iter.next());
+ buf.append(SEPARATOR);
+ }
+ store.setValue(TAG_LRU_FILTERS, buf.toString());
+ }
+
+ private String getPreferenceKey(String tag) {
+ return "CustomFiltersActionGroup." + fTargetId + '.' + tag; //$NON-NLS-1$
+ }
+
+ // ---------- view instance persistency ----------
+
+ /**
+ * Saves the state of the custom filters in a memento.
+ *
+ * @param memento
+ * the memento into which the state is saved
+ */
+ public void saveState(IMemento memento) {
+ IMemento customFilters = memento.createChild(TAG_CUSTOM_FILTERS);
+ customFilters.putString(TAG_USER_DEFINED_PATTERNS_ENABLED, new Boolean(
+ fUserDefinedPatternsEnabled).toString());
+ saveUserDefinedPatterns(customFilters);
+ saveXmlDefinedFilters(customFilters);
+ saveLRUFilters(customFilters);
+ }
+
+ private void saveXmlDefinedFilters(IMemento memento) {
+ if (fEnabledFilterIds != null && !fEnabledFilterIds.isEmpty()) {
+ IMemento xmlDefinedFilters = memento
+ .createChild(TAG_XML_DEFINED_FILTERS);
+ Iterator iter = fEnabledFilterIds.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String id = (String) entry.getKey();
+ Boolean isEnabled = (Boolean) entry.getValue();
+ IMemento child = xmlDefinedFilters.createChild(TAG_CHILD);
+ child.putString(TAG_FILTER_ID, id);
+ child.putString(TAG_IS_ENABLED, isEnabled.toString());
+ }
+ }
+ }
+
+ /**
+ * Stores the last recently used filter Ids into the given memento
+ *
+ * @param memento
+ * the memento into which to store the LRU filter Ids
+ * @since 3.0
+ */
+ private void saveLRUFilters(IMemento memento) {
+ if (fLRUFilterIdsStack != null && !fLRUFilterIdsStack.isEmpty()) {
+ IMemento lruFilters = memento.createChild(TAG_LRU_FILTERS);
+ Iterator iter = fLRUFilterIdsStack.iterator();
+ while (iter.hasNext()) {
+ String id = (String) iter.next();
+ IMemento child = lruFilters.createChild(TAG_CHILD);
+ child.putString(TAG_FILTER_ID, id);
+ }
+ }
+ }
+
+ private void saveUserDefinedPatterns(IMemento memento) {
+ if (fUserDefinedPatterns != null && fUserDefinedPatterns.length > 0) {
+ IMemento userDefinedPatterns = memento
+ .createChild(TAG_USER_DEFINED_PATTERNS);
+ for (int i = 0; i < fUserDefinedPatterns.length; i++) {
+ IMemento child = userDefinedPatterns.createChild(TAG_CHILD);
+ child.putString(TAG_PATTERN, fUserDefinedPatterns[i]);
+ }
+ }
+ }
+
+ /**
+ * Restores the state of the filter actions from a memento.
+ *
+ * Note: This method does not refresh the viewer.
+ *
+ *
+ * @param memento
+ * the memento from which the state is restored
+ */
+ public void restoreState(IMemento memento) {
+ if (memento == null)
+ return;
+ IMemento customFilters = memento.getChild(TAG_CUSTOM_FILTERS);
+ if (customFilters == null)
+ return;
+ String userDefinedPatternsEnabled = customFilters
+ .getString(TAG_USER_DEFINED_PATTERNS_ENABLED);
+ if (userDefinedPatternsEnabled == null)
+ return;
+
+ fUserDefinedPatternsEnabled = Boolean.valueOf(
+ userDefinedPatternsEnabled).booleanValue();
+ restoreUserDefinedPatterns(customFilters);
+ restoreXmlDefinedFilters(customFilters);
+ restoreLRUFilters(customFilters);
+
+ updateViewerFilters(false);
+ }
+
+ private void restoreUserDefinedPatterns(IMemento memento) {
+ IMemento userDefinedPatterns = memento
+ .getChild(TAG_USER_DEFINED_PATTERNS);
+ if (userDefinedPatterns != null) {
+ IMemento children[] = userDefinedPatterns.getChildren(TAG_CHILD);
+ String[] patterns = new String[children.length];
+ for (int i = 0; i < children.length; i++)
+ patterns[i] = children[i].getString(TAG_PATTERN);
+
+ setUserDefinedPatterns(patterns);
+ } else
+ setUserDefinedPatterns(new String[0]);
+ }
+
+ private void restoreXmlDefinedFilters(IMemento memento) {
+ IMemento xmlDefinedFilters = memento.getChild(TAG_XML_DEFINED_FILTERS);
+ if (xmlDefinedFilters != null) {
+ IMemento[] children = xmlDefinedFilters.getChildren(TAG_CHILD);
+ for (int i = 0; i < children.length; i++) {
+ String id = children[i].getString(TAG_FILTER_ID);
+ Boolean isEnabled = new Boolean(children[i]
+ .getString(TAG_IS_ENABLED));
+ fEnabledFilterIds.put(id, isEnabled);
+ }
+ }
+ }
+
+ private void restoreLRUFilters(IMemento memento) {
+ IMemento lruFilters = memento.getChild(TAG_LRU_FILTERS);
+ fLRUFilterIdsStack.clear();
+ if (lruFilters != null) {
+ IMemento[] children = lruFilters.getChildren(TAG_CHILD);
+ for (int i = 0; i < children.length; i++) {
+ String id = children[i].getString(TAG_FILTER_ID);
+ if (fFilterDescriptorMap.containsKey(id)
+ && !fLRUFilterIdsStack.contains(id))
+ fLRUFilterIdsStack.push(id);
+ }
+ }
+ }
+
+ private void cleanUpPatternDuplicates() {
+ if (!areUserDefinedPatternsEnabled())
+ return;
+ List userDefinedPatterns = new ArrayList(Arrays
+ .asList(fUserDefinedPatterns));
+ FilterDescriptor[] filters = FilterDescriptor
+ .getFilterDescriptors(fTargetId);
+
+ for (int i = 0; i < filters.length; i++) {
+ if (filters[i].isPatternFilter()) {
+ String pattern = filters[i].getPattern();
+ if (userDefinedPatterns.contains(pattern)) {
+ fEnabledFilterIds.put(filters[i].getId(), Boolean.TRUE);
+ boolean hasMore = true;
+ while (hasMore)
+ hasMore = userDefinedPatterns.remove(pattern);
+ }
+ }
+ }
+ fUserDefinedPatterns = (String[]) userDefinedPatterns
+ .toArray(new String[userDefinedPatterns.size()]);
+ setUserDefinedPatternsEnabled(fUserDefinedPatternsEnabled
+ && fUserDefinedPatterns.length > 0);
+ }
+
+ // ---------- dialog related code ----------
+
+ private void openDialog() {
+ CustomFiltersDialog dialog = new CustomFiltersDialog(fViewer
+ .getControl().getShell(), fTargetId,
+ areUserDefinedPatternsEnabled(), fUserDefinedPatterns,
+ getEnabledFilterIds());
+
+ if (dialog.open() == Window.OK) {
+ setEnabledFilterIds(dialog.getEnabledFilterIds());
+ setUserDefinedPatternsEnabled(dialog
+ .areUserDefinedPatternsEnabled());
+ setUserDefinedPatterns(dialog.getUserDefinedPatterns());
+ setRecentlyChangedFilters(dialog.getFilterDescriptorChangeHistory());
+
+ storeViewDefaults();
+
+ updateViewerFilters(true);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/GenerateActionGroup.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/GenerateActionGroup.java
new file mode 100644
index 0000000..f627deb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/GenerateActionGroup.java
@@ -0,0 +1,395 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui.actions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.actions.ActionMessages;
+import net.sourceforge.phpdt.internal.ui.actions.AddTaskAction;
+import net.sourceforge.phpdt.ui.IContextMenuConstants;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.actions.AddBookmarkAction;
+import org.eclipse.ui.ide.IDEActionFactory;
+import org.eclipse.ui.part.Page;
+import org.eclipse.ui.texteditor.IUpdate;
+
+/**
+ * Action group that adds the source and generate actions to a part's context
+ * menu and installs handlers for the corresponding global menu actions.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class GenerateActionGroup extends ActionGroup {
+ /**
+ * Pop-up menu: id of the source sub menu (value
+ * net.sourceforge.phpdt.ui.source.menu
).
+ *
+ * @since 3.0
+ */
+ public static final String MENU_ID = "net.sourceforge.pheclipse.ui.source.menu"; //$NON-NLS-1$
+
+ private PHPEditor fEditor;
+
+ // private boolean fEditorIsOwner;
+ private IWorkbenchSite fSite;
+
+ private String fGroupName = IContextMenuConstants.GROUP_SOURCE;
+
+ private List fRegisteredSelectionListeners;
+
+ // private AddImportOnSelectionAction fAddImport;
+ // private OverrideMethodsAction fOverrideMethods;
+ // private AddGetterSetterAction fAddGetterSetter;
+ // private AddUnimplementedConstructorsAction fAddUnimplementedConstructors;
+ // private AddJavaDocStubAction fAddJavaDocStub;
+ private AddBookmarkAction fAddBookmark;
+
+ private AddTaskAction fAddTaskAction;
+
+ // private ExternalizeStringsAction fExternalizeStrings;
+ // private FindStringsToExternalizeAction fFindStringsToExternalize;
+ // private SurroundWithTryCatchAction fSurroundWithTryCatch;
+
+ // private OrganizeImportsAction fOrganizeImports;
+
+ /**
+ * Note: This constructor is for internal use only. Clients should not call
+ * this constructor.
+ */
+ public GenerateActionGroup(PHPEditor editor, String groupName) {
+ fSite = editor.getSite();
+ fEditor = editor;
+ fGroupName = groupName;
+
+ ISelectionProvider provider = fSite.getSelectionProvider();
+ ISelection selection = provider.getSelection();
+
+ // fAddImport= new AddImportOnSelectionAction(editor);
+ // fAddImport.setActionDefinitionId(IJavaEditorActionDefinitionIds.ADD_IMPORT);
+ // fAddImport.update();
+ // editor.setAction("AddImport", fAddImport); //$NON-NLS-1$
+
+ // fOrganizeImports= new OrganizeImportsAction(editor);
+ // fOrganizeImports.setActionDefinitionId(IJavaEditorActionDefinitionIds.ORGANIZE_IMPORTS);
+ // fOrganizeImports.editorStateChanged();
+ // editor.setAction("OrganizeImports", fOrganizeImports); //$NON-NLS-1$
+
+ // fOverrideMethods= new OverrideMethodsAction(editor);
+ // fOverrideMethods.setActionDefinitionId(IJavaEditorActionDefinitionIds.OVERRIDE_METHODS);
+ // fOverrideMethods.editorStateChanged();
+ // editor.setAction("OverrideMethods", fOverrideMethods); //$NON-NLS-1$
+
+ // fAddGetterSetter= new AddGetterSetterAction(editor);
+ // fAddGetterSetter.setActionDefinitionId(IJavaEditorActionDefinitionIds.CREATE_GETTER_SETTER);
+ // fAddGetterSetter.editorStateChanged();
+ // editor.setAction("AddGetterSetter", fAddGetterSetter); //$NON-NLS-1$
+
+ // fAddUnimplementedConstructors= new
+ // AddUnimplementedConstructorsAction(editor);
+ // fAddUnimplementedConstructors.setActionDefinitionId(IJavaEditorActionDefinitionIds.ADD_UNIMPLEMENTED_CONTRUCTORS);
+ // fAddUnimplementedConstructors.editorStateChanged();
+ // editor.setAction("AddUnimplementedConstructors",
+ // fAddUnimplementedConstructors); //$NON-NLS-1$
+
+ // fAddJavaDocStub= new AddJavaDocStubAction(editor);
+ // fAddJavaDocStub.editorStateChanged();
+ //
+ // fSurroundWithTryCatch= new SurroundWithTryCatchAction(editor);
+ // fSurroundWithTryCatch.setActionDefinitionId(IJavaEditorActionDefinitionIds.SURROUND_WITH_TRY_CATCH);
+ // fSurroundWithTryCatch.update(selection);
+ // provider.addSelectionChangedListener(fSurroundWithTryCatch);
+ // editor.setAction("SurroundWithTryCatch", fSurroundWithTryCatch);
+ // //$NON-NLS-1$
+ //
+ // fExternalizeStrings= new ExternalizeStringsAction(editor);
+ // fExternalizeStrings.setActionDefinitionId(IJavaEditorActionDefinitionIds.EXTERNALIZE_STRINGS);
+ // fExternalizeStrings.editorStateChanged();
+ // editor.setAction("ExternalizeStrings", fExternalizeStrings);
+ // //$NON-NLS-1$
+
+ }
+
+ /**
+ * Creates a new GenerateActionGroup
. The group requires
+ * that the selection provided by the page's selection provider is of type
+ * org.eclipse.jface.viewers.IStructuredSelection
.
+ *
+ * @param page
+ * the page that owns this action group
+ */
+ public GenerateActionGroup(Page page) {
+ this(page.getSite());
+ }
+
+ /**
+ * Creates a new GenerateActionGroup
. The group requires
+ * that the selection provided by the part's selection provider is of type
+ * org.eclipse.jface.viewers.IStructuredSelection
.
+ *
+ * @param part
+ * the view part that owns this action group
+ */
+ public GenerateActionGroup(IViewPart part) {
+ this(part.getSite());
+ }
+
+ private GenerateActionGroup(IWorkbenchSite site) {
+ fSite = site;
+ ISelectionProvider provider = fSite.getSelectionProvider();
+ ISelection selection = provider.getSelection();
+
+ // fOverrideMethods= new OverrideMethodsAction(site);
+ // fAddGetterSetter= new AddGetterSetterAction(site);
+ // fAddUnimplementedConstructors= new
+ // AddUnimplementedConstructorsAction(site);
+ // fAddJavaDocStub= new AddJavaDocStubAction(site);
+ fAddBookmark = new AddBookmarkAction(site.getShell());
+ fAddTaskAction = new AddTaskAction(site);
+ // fExternalizeStrings= new ExternalizeStringsAction(site);
+ // fFindStringsToExternalize= new FindStringsToExternalizeAction(site);
+ // fOrganizeImports= new OrganizeImportsAction(site);
+ //
+ // fOverrideMethods.update(selection);
+ // fAddGetterSetter.update(selection);
+ // fAddUnimplementedConstructors.update(selection);
+ // fAddJavaDocStub.update(selection);
+ // fExternalizeStrings.update(selection);
+ // fFindStringsToExternalize.update(selection);
+ fAddTaskAction.update(selection);
+ // fOrganizeImports.update(selection);
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ss = (IStructuredSelection) selection;
+ fAddBookmark.selectionChanged(ss);
+ } else {
+ fAddBookmark.setEnabled(false);
+ }
+
+ // registerSelectionListener(provider, fOverrideMethods);
+ // registerSelectionListener(provider, fAddGetterSetter);
+ // registerSelectionListener(provider, fAddUnimplementedConstructors);
+ // registerSelectionListener(provider, fAddJavaDocStub);
+ registerSelectionListener(provider, fAddBookmark);
+ // registerSelectionListener(provider, fExternalizeStrings);
+ // registerSelectionListener(provider, fFindStringsToExternalize);
+ // registerSelectionListener(provider, fOrganizeImports);
+ registerSelectionListener(provider, fAddTaskAction);
+ }
+
+ private void registerSelectionListener(ISelectionProvider provider,
+ ISelectionChangedListener listener) {
+ if (fRegisteredSelectionListeners == null)
+ fRegisteredSelectionListeners = new ArrayList(12);
+ provider.addSelectionChangedListener(listener);
+ fRegisteredSelectionListeners.add(listener);
+ }
+
+ /*
+ * The state of the editor owning this action group has changed. This method
+ * does nothing if the group's owner isn't an editor.
+ */
+ /**
+ * Note: This method is for internal use only. Clients should not call this
+ * method.
+ */
+ public void editorStateChanged() {
+ Assert.isTrue(isEditorOwner());
+
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=17709
+ }
+
+ /*
+ * (non-Javadoc) Method declared in ActionGroup
+ */
+ public void fillActionBars(IActionBars actionBar) {
+ super.fillActionBars(actionBar);
+ setGlobalActionHandlers(actionBar);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in ActionGroup
+ */
+ // public void fillContextMenu(IMenuManager menu) {
+ // super.fillContextMenu(menu);
+ // if (fEditorIsOwner) {
+ // IMenuManager subMenu= createEditorSubMenu(menu);
+ // if (subMenu != null)
+ // menu.appendToGroup(fGroupName, subMenu);
+ // } else {
+ // // appendToGroup(menu, fOrganizeImports);
+ // // appendToGroup(menu, fOverrideMethods);
+ // // appendToGroup(menu, fAddGetterSetter);
+ // // appendToGroup(menu, fAddUnimplementedConstructors);
+ // // appendToGroup(menu, fAddJavaDocStub);
+ // appendToGroup(menu, fAddBookmark);
+ // }
+ // }
+ /*
+ * (non-Javadoc) Method declared in ActionGroup
+ */
+ // public void fillContextMenu(IMenuManager menu) {
+ // super.fillContextMenu(menu);
+ // IMenuManager subMenu= null;
+ // if (isEditorOwner()) {
+ // subMenu= fillEditorSubMenu(menu);
+ // } else {
+ // // subMenu= createViewSubMenu(menu);
+ // }
+ // if (subMenu != null)
+ // menu.appendToGroup(fGroupName, subMenu);
+ // }
+ public void fillContextMenu(IMenuManager menu) {
+ super.fillContextMenu(menu);
+ String shortCut = null; //$NON-NLS-1$
+ // if (fQuickAccessAction != null) {
+ // shortCut= fQuickAccessAction.getShortCutString(); //$NON-NLS-1$
+ // }
+ IMenuManager subMenu = new MenuManager(
+ ActionMessages.getString("SourceMenu.label") + (shortCut != null ? "\t" + shortCut : ""), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ MENU_ID);
+ int added = 0;
+ if (isEditorOwner()) {
+ added = fillEditorSubMenu(subMenu);
+ }
+ // else {
+ // added= fillViewSubMenu(subMenu);
+ // }
+ if (added > 0)
+ menu.appendToGroup(fGroupName, subMenu);
+ }
+
+ private int fillEditorSubMenu(IMenuManager source) {
+ // IMenuManager result= new
+ // MenuManager(ActionMessages.getString("SourceMenu.label"));
+ // //$NON-NLS-1$
+ int added = 0;
+ added += addEditorAction(source, "Comment"); //$NON-NLS-1$
+ added += addEditorAction(source, "Uncomment"); //$NON-NLS-1$
+ added += addEditorAction(source, "ToggleComment"); //$NON-NLS-1$
+ added += addEditorAction(source, "AddBlockComment"); //$NON-NLS-1$
+ added += addEditorAction(source, "RemoveBlockComment"); //$NON-NLS-1$
+ added += addEditorAction(source, "Format"); //$NON-NLS-1$
+ added += addEditorAction(source, "Indent"); //$NON-NLS-1$
+ // result.add(new Separator());
+ // added+= addAction(result, fOrganizeImports);
+ // added+= addAction(result, fAddImport);
+ // result.add(new Separator());
+ // added+= addAction(result, fOverrideMethods);
+ // added+= addAction(result, fAddGetterSetter);
+ // added+= addAction(result, fAddUnimplementedConstructors);
+ // added+= addAction(result, fAddJavaDocStub);
+ // added+= addAction(result, fAddBookmark);
+ // result.add(new Separator());
+ // added+= addAction(result, fSurroundWithTryCatch);
+ // added+= addAction(result, fExternalizeStrings);
+ // if (added == 0)
+ // result= null;
+ return added;
+ }
+
+ /*
+ * (non-Javadoc) Method declared in ActionGroup
+ */
+ public void dispose() {
+ if (fRegisteredSelectionListeners != null) {
+ ISelectionProvider provider = fSite.getSelectionProvider();
+ for (Iterator iter = fRegisteredSelectionListeners.iterator(); iter
+ .hasNext();) {
+ ISelectionChangedListener listener = (ISelectionChangedListener) iter
+ .next();
+ provider.removeSelectionChangedListener(listener);
+ }
+ }
+ fEditor = null;
+ super.dispose();
+ }
+
+ private void setGlobalActionHandlers(IActionBars actionBar) {
+ // actionBar.setGlobalActionHandler(JdtActionConstants.ADD_IMPORT,
+ // fAddImport);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.SURROUND_WITH_TRY_CATCH,
+ // fSurroundWithTryCatch);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.OVERRIDE_METHODS,
+ // fOverrideMethods);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.GENERATE_GETTER_SETTER,
+ // fAddGetterSetter);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.ADD_CONSTRUCTOR_FROM_SUPERCLASS,
+ // fAddUnimplementedConstructors);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.ADD_JAVA_DOC_COMMENT,
+ // fAddJavaDocStub);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.EXTERNALIZE_STRINGS,
+ // fExternalizeStrings);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.FIND_STRINGS_TO_EXTERNALIZE,
+ // fFindStringsToExternalize);
+ // actionBar.setGlobalActionHandler(JdtActionConstants.ORGANIZE_IMPORTS,
+ // fOrganizeImports);
+ if (!isEditorOwner()) {
+ // editor provides its own implementation of these actions.
+ actionBar.setGlobalActionHandler(IDEActionFactory.BOOKMARK.getId(),
+ fAddBookmark);
+ actionBar.setGlobalActionHandler(IDEActionFactory.ADD_TASK.getId(),
+ fAddTaskAction);
+ }
+ }
+
+ private int appendToGroup(IMenuManager menu, IAction action) {
+ if (action != null && action.isEnabled()) {
+ menu.appendToGroup(fGroupName, action);
+ return 1;
+ }
+ return 0;
+ }
+
+ private int addAction(IMenuManager menu, IAction action) {
+ if (action != null && action.isEnabled()) {
+ menu.add(action);
+ return 1;
+ }
+ return 0;
+ }
+
+ private int addEditorAction(IMenuManager menu, String actionID) {
+ if (fEditor == null)
+ return 0;
+ IAction action = fEditor.getAction(actionID);
+ if (action == null)
+ return 0;
+ if (action instanceof IUpdate)
+ ((IUpdate) action).update();
+ if (action.isEnabled()) {
+ menu.add(action);
+ return 1;
+ }
+ return 0;
+ }
+
+ private boolean isEditorOwner() {
+ return fEditor != null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/GotoMatchingBracketAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/GotoMatchingBracketAction.java
new file mode 100644
index 0000000..ae586c0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/GotoMatchingBracketAction.java
@@ -0,0 +1,31 @@
+package net.sourceforge.phpdt.ui.actions;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import net.sourceforge.phpdt.internal.corext.Assert;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditorMessages;
+
+import org.eclipse.jface.action.Action;
+
+public class GotoMatchingBracketAction extends Action {
+
+ public final static String GOTO_MATCHING_BRACKET = "GotoMatchingBracket"; //$NON-NLS-1$
+
+ private final PHPEditor fEditor;
+
+ public GotoMatchingBracketAction(PHPEditor editor) {
+ super(PHPEditorMessages.getString("GotoMatchingBracket.label"));
+ Assert.isNotNull(editor);
+ fEditor = editor;
+ setEnabled(null != fEditor);
+ }
+
+ public void run() {
+ fEditor.gotoMatchingBracket();
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/MemberFilterActionGroup.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/MemberFilterActionGroup.java
new file mode 100644
index 0000000..25d3159
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/MemberFilterActionGroup.java
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.actions;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.actions.ActionMessages;
+import net.sourceforge.phpdt.internal.ui.viewsupport.MemberFilter;
+import net.sourceforge.phpdt.internal.ui.viewsupport.MemberFilterAction;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.actions.ActionGroup;
+
+/**
+ * Action Group that contributes filter buttons for a view parts showing methods
+ * and fields. Contributed filters are: hide fields, hide static members and
+ * hide non-public members.
+ *
+ * The action group installs a filter on a structured viewer. The filter is
+ * connected to the actions installed in the view part's toolbar menu and is
+ * updated when the state of the buttons changes.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class MemberFilterActionGroup extends ActionGroup {
+
+ public static final int FILTER_NONPUBLIC = MemberFilter.FILTER_NONPUBLIC;
+
+ public static final int FILTER_STATIC = MemberFilter.FILTER_STATIC;
+
+ public static final int FILTER_FIELDS = MemberFilter.FILTER_FIELDS;
+
+ private static final String TAG_HIDEFIELDS = "hidefields"; //$NON-NLS-1$
+
+ private static final String TAG_HIDESTATIC = "hidestatic"; //$NON-NLS-1$
+
+ private static final String TAG_HIDENONPUBLIC = "hidenonpublic"; //$NON-NLS-1$
+
+ private MemberFilterAction[] fFilterActions;
+
+ private MemberFilter fFilter;
+
+ private StructuredViewer fViewer;
+
+ private String fViewerId;
+
+ private boolean fInViewMenu;
+
+ /**
+ * Creates a new MemberFilterActionGroup
.
+ *
+ * @param viewer
+ * the viewer to be filtered
+ * @param viewerId
+ * a unique id of the viewer. Used as a key to to store the last
+ * used filter settings in the preference store
+ */
+ public MemberFilterActionGroup(StructuredViewer viewer, String viewerId) {
+ this(viewer, viewerId, false);
+ }
+
+ /**
+ * Creates a new MemberFilterActionGroup
.
+ *
+ * @param viewer
+ * the viewer to be filtered
+ * @param viewerId
+ * a unique id of the viewer. Used as a key to to store the last
+ * used filter settings in the preference store
+ * @param inViewMenu
+ * if true
the actions are added to the view menu.
+ * If false
they are added to the toobar.
+ *
+ * @since 2.1
+ */
+ public MemberFilterActionGroup(StructuredViewer viewer, String viewerId,
+ boolean inViewMenu) {
+ fViewer = viewer;
+ fViewerId = viewerId;
+ fInViewMenu = inViewMenu;
+
+ // get initial values
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ boolean doHideFields = store
+ .getBoolean(getPreferenceKey(FILTER_FIELDS));
+ boolean doHideStatic = store
+ .getBoolean(getPreferenceKey(FILTER_STATIC));
+ boolean doHidePublic = store
+ .getBoolean(getPreferenceKey(FILTER_NONPUBLIC));
+
+ fFilter = new MemberFilter();
+ if (doHideFields)
+ fFilter.addFilter(FILTER_FIELDS);
+ if (doHideStatic)
+ fFilter.addFilter(FILTER_STATIC);
+ if (doHidePublic)
+ fFilter.addFilter(FILTER_NONPUBLIC);
+
+ // fields
+ String title = ActionMessages
+ .getString("MemberFilterActionGroup.hide_fields.label"); //$NON-NLS-1$
+ String helpContext = IJavaHelpContextIds.FILTER_FIELDS_ACTION;
+ MemberFilterAction hideFields = new MemberFilterAction(this, title,
+ FILTER_FIELDS, helpContext, doHideFields);
+ hideFields.setDescription(ActionMessages
+ .getString("MemberFilterActionGroup.hide_fields.description")); //$NON-NLS-1$
+ hideFields.setToolTipText(ActionMessages
+ .getString("MemberFilterActionGroup.hide_fields.tooltip")); //$NON-NLS-1$
+ PHPUiImages.setLocalImageDescriptors(hideFields, "fields_co.gif"); //$NON-NLS-1$
+
+ // static
+ title = ActionMessages
+ .getString("MemberFilterActionGroup.hide_static.label"); //$NON-NLS-1$
+ helpContext = IJavaHelpContextIds.FILTER_STATIC_ACTION;
+ MemberFilterAction hideStatic = new MemberFilterAction(this, title,
+ FILTER_STATIC, helpContext, doHideStatic);
+ hideStatic.setDescription(ActionMessages
+ .getString("MemberFilterActionGroup.hide_static.description")); //$NON-NLS-1$
+ hideStatic.setToolTipText(ActionMessages
+ .getString("MemberFilterActionGroup.hide_static.tooltip")); //$NON-NLS-1$
+ PHPUiImages.setLocalImageDescriptors(hideStatic, "static_co.gif"); //$NON-NLS-1$
+
+ // non-public
+ title = ActionMessages
+ .getString("MemberFilterActionGroup.hide_nonpublic.label"); //$NON-NLS-1$
+ helpContext = IJavaHelpContextIds.FILTER_PUBLIC_ACTION;
+ MemberFilterAction hideNonPublic = new MemberFilterAction(this, title,
+ FILTER_NONPUBLIC, helpContext, doHidePublic);
+ hideNonPublic
+ .setDescription(ActionMessages
+ .getString("MemberFilterActionGroup.hide_nonpublic.description")); //$NON-NLS-1$
+ hideNonPublic.setToolTipText(ActionMessages
+ .getString("MemberFilterActionGroup.hide_nonpublic.tooltip")); //$NON-NLS-1$
+ PHPUiImages.setLocalImageDescriptors(hideNonPublic, "public_co.gif"); //$NON-NLS-1$
+
+ // order corresponds to order in toolbar
+ fFilterActions = new MemberFilterAction[] { hideFields, hideStatic,
+ hideNonPublic };
+
+ fViewer.addFilter(fFilter);
+ }
+
+ private String getPreferenceKey(int filterProperty) {
+ return "MemberFilterActionGroup." + fViewerId + '.' + String.valueOf(filterProperty); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the member filters.
+ *
+ * @param filterProperty
+ * the filter to be manipulated. Valid values are
+ * FILTER_FIELDS
, FILTER_PUBLIC
,
+ * and FILTER_PRIVATE
as defined by this action
+ * group
+ * @param set
+ * if true
the given filter is installed. If
+ * false
the given filter is removed .
+ */
+ public void setMemberFilter(int filterProperty, boolean set) {
+ setMemberFilters(new int[] { filterProperty }, new boolean[] { set },
+ true);
+ }
+
+ private void setMemberFilters(int[] propertyKeys, boolean[] propertyValues,
+ boolean refresh) {
+ if (propertyKeys.length == 0)
+ return;
+ Assert.isTrue(propertyKeys.length == propertyValues.length);
+
+ for (int i = 0; i < propertyKeys.length; i++) {
+ int filterProperty = propertyKeys[i];
+ boolean set = propertyValues[i];
+ if (set) {
+ fFilter.addFilter(filterProperty);
+ } else {
+ fFilter.removeFilter(filterProperty);
+ }
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+
+ for (int j = 0; j < fFilterActions.length; j++) {
+ int currProperty = fFilterActions[j].getFilterProperty();
+ if (currProperty == filterProperty) {
+ fFilterActions[j].setChecked(set);
+ }
+ store.setValue(getPreferenceKey(currProperty),
+ hasMemberFilter(currProperty));
+ }
+ }
+ if (refresh) {
+ fViewer.getControl().setRedraw(false);
+ BusyIndicator.showWhile(fViewer.getControl().getDisplay(),
+ new Runnable() {
+ public void run() {
+ fViewer.refresh();
+ }
+ });
+ fViewer.getControl().setRedraw(true);
+ }
+ }
+
+ /**
+ * Returns true
if the given filter is installed.
+ *
+ * @param filterProperty
+ * the filter to be tested. Valid values are
+ * FILTER_FIELDS
, FILTER_PUBLIC
,
+ * and FILTER_PRIVATE
as defined by this action
+ * group
+ */
+ public boolean hasMemberFilter(int filterProperty) {
+ return fFilter.hasFilter(filterProperty);
+ }
+
+ /**
+ * Saves the state of the filter actions in a memento.
+ *
+ * @param memento
+ * the memento to which the state is saved
+ */
+ public void saveState(IMemento memento) {
+ memento.putString(TAG_HIDEFIELDS, String
+ .valueOf(hasMemberFilter(FILTER_FIELDS)));
+ memento.putString(TAG_HIDESTATIC, String
+ .valueOf(hasMemberFilter(FILTER_STATIC)));
+ memento.putString(TAG_HIDENONPUBLIC, String
+ .valueOf(hasMemberFilter(FILTER_NONPUBLIC)));
+ }
+
+ /**
+ * Restores the state of the filter actions from a memento.
+ *
+ * Note: This method does not refresh the viewer.
+ *
+ *
+ * @param memento
+ * the memento from which the state is restored
+ */
+ public void restoreState(IMemento memento) {
+ setMemberFilters(new int[] { FILTER_FIELDS, FILTER_STATIC,
+ FILTER_NONPUBLIC }, new boolean[] {
+ Boolean.valueOf(memento.getString(TAG_HIDEFIELDS))
+ .booleanValue(),
+ Boolean.valueOf(memento.getString(TAG_HIDESTATIC))
+ .booleanValue(),
+ Boolean.valueOf(memento.getString(TAG_HIDENONPUBLIC))
+ .booleanValue() }, false);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ActionGroup#fillActionBars(IActionBars)
+ */
+ public void fillActionBars(IActionBars actionBars) {
+ contributeToToolBar(actionBars.getToolBarManager());
+ };
+
+ /**
+ * Adds the filter actions to the given tool bar
+ *
+ * @param tbm
+ * the tool bar to which the actions are added
+ */
+ public void contributeToToolBar(IToolBarManager tbm) {
+ if (fInViewMenu)
+ return;
+ tbm.add(fFilterActions[0]); // fields
+ tbm.add(fFilterActions[1]); // static
+ tbm.add(fFilterActions[2]); // public
+ }
+
+ /**
+ * Adds the filter actions to the given menu manager.
+ *
+ * @param menu
+ * the menu manager to which the actions are added
+ * @since 2.1
+ */
+ public void contributeToViewMenu(IMenuManager menu) {
+ if (!fInViewMenu)
+ return;
+ final String filters = "filters"; //$NON-NLS-1$
+ if (menu.find(filters) != null) {
+ menu.prependToGroup(filters, fFilterActions[0]); // fields
+ menu.prependToGroup(filters, fFilterActions[1]); // static
+ menu.prependToGroup(filters, fFilterActions[2]); // public
+ } else {
+ menu.add(fFilterActions[0]); // fields
+ menu.add(fFilterActions[1]); // static
+ menu.add(fFilterActions[2]); // public
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ActionGroup#dispose()
+ */
+ public void dispose() {
+ super.dispose();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/OpenEditorActionGroup.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/OpenEditorActionGroup.java
new file mode 100644
index 0000000..a1474ea
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/OpenEditorActionGroup.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.actions;
+
+import net.sourceforge.phpdt.internal.ui.actions.ActionMessages;
+import net.sourceforge.phpdt.ui.IContextMenuConstants;
+import net.sourceforge.phpeclipse.actions.PHPOpenDeclarationAction;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.actions.OpenWithMenu;
+
+/**
+ * Action group that adds the actions opening a new editor to the context menu
+ * and the action bar's navigate menu.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class OpenEditorActionGroup extends ActionGroup {
+
+ private IWorkbenchSite fSite;
+
+ private boolean fIsEditorOwner;
+
+ private PHPOpenDeclarationAction fOpen;
+
+ /**
+ * Creates a new OpenActionGroup
. The group requires that
+ * the selection provided by the part's selection provider is of type
+ * org.eclipse.jface.viewers.IStructuredSelection
.
+ *
+ * @param part
+ * the view part that owns this action group
+ */
+ public OpenEditorActionGroup(IViewPart part) {
+ fSite = part.getSite();
+ fOpen = new PHPOpenDeclarationAction(fSite);
+ fOpen.setActionDefinitionId(PHPEditorActionDefinitionIds.OPEN_EDITOR);
+ initialize(fSite.getSelectionProvider());
+ }
+
+ /**
+ * Note: This constructor is for internal use only. Clients should not call
+ * this constructor.
+ */
+ public OpenEditorActionGroup(PHPEditor part) {
+ fIsEditorOwner = true;
+ fOpen = new PHPOpenDeclarationAction(part);
+ fOpen.setActionDefinitionId(PHPEditorActionDefinitionIds.OPEN_EDITOR);
+ part.setAction("OpenEditor", fOpen); //$NON-NLS-1$
+ fSite = part.getEditorSite();
+ initialize(fSite.getSelectionProvider());
+ }
+
+ /**
+ * Returns the open action managed by this action group.
+ *
+ * @return the open action. Returns null
if the group doesn't
+ * provide any open action
+ */
+ public IAction getOpenAction() {
+ return fOpen;
+ }
+
+ private void initialize(ISelectionProvider provider) {
+ ISelection selection = provider.getSelection();
+ fOpen.update(selection);
+ if (!fIsEditorOwner) {
+ provider.addSelectionChangedListener(fOpen);
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared in ActionGroup
+ */
+ public void fillActionBars(IActionBars actionBar) {
+ super.fillActionBars(actionBar);
+ setGlobalActionHandlers(actionBar);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in ActionGroup
+ */
+ public void fillContextMenu(IMenuManager menu) {
+ super.fillContextMenu(menu);
+ appendToGroup(menu, fOpen);
+ if (!fIsEditorOwner) {
+ addOpenWithMenu(menu);
+ }
+ }
+
+ /*
+ * @see ActionGroup#dispose()
+ */
+ public void dispose() {
+ ISelectionProvider provider = fSite.getSelectionProvider();
+ provider.removeSelectionChangedListener(fOpen);
+ super.dispose();
+ }
+
+ private void setGlobalActionHandlers(IActionBars actionBars) {
+ actionBars.setGlobalActionHandler(PHPdtActionConstants.OPEN, fOpen);
+ }
+
+ private void appendToGroup(IMenuManager menu, IAction action) {
+ if (action.isEnabled())
+ menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, action);
+ }
+
+ private void addOpenWithMenu(IMenuManager menu) {
+ ISelection selection = getContext().getSelection();
+ if (selection.isEmpty() || !(selection instanceof IStructuredSelection))
+ return;
+ IStructuredSelection ss = (IStructuredSelection) selection;
+ if (ss.size() != 1)
+ return;
+
+ Object o = ss.getFirstElement();
+ if (!(o instanceof IAdaptable))
+ return;
+
+ IAdaptable element = (IAdaptable) o;
+ Object resource = element.getAdapter(IResource.class);
+ if (!(resource instanceof IFile))
+ return;
+
+ // Create a menu flyout.
+ IMenuManager submenu = new MenuManager(ActionMessages
+ .getString("OpenWithMenu.label")); //$NON-NLS-1$
+ submenu.add(new OpenWithMenu(fSite.getPage(), (IFile) resource));
+
+ // Add the submenu.
+ menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, submenu);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/OpenPHPPerspectiveAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/OpenPHPPerspectiveAction.java
new file mode 100644
index 0000000..577af0e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/OpenPHPPerspectiveAction.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.actions;
+
+import net.sourceforge.phpdt.internal.ui.actions.ActionMessages;
+import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+import net.sourceforge.phpdt.ui.JavaUI;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.WorkbenchException;
+
+/**
+ * Action to programmatically open a Java perspective.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class OpenPHPPerspectiveAction extends Action {
+
+ /**
+ * Create a new OpenPHPPerspectiveAction
.
+ */
+ public OpenPHPPerspectiveAction() {
+ // WorkbenchHelp.setHelp(this,
+ // IJavaHelpContextIds.OPEN_JAVA_PERSPECTIVE_ACTION);
+ }
+
+ public void run() {
+ IWorkbench workbench = WebUI.getDefault().getWorkbench();
+ IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ IAdaptable input;
+ if (page != null)
+ input = page.getInput();
+ else
+ input = ResourcesPlugin.getWorkspace().getRoot();
+ try {
+ workbench.showPerspective(JavaUI.ID_PERSPECTIVE, window,
+ input);
+ } catch (WorkbenchException e) {
+ ExceptionHandler
+ .handle(
+ e,
+ window.getShell(),
+ ActionMessages
+ .getString("OpenPHPPerspectiveAction.dialog.title"), //$NON-NLS-1$
+ ActionMessages
+ .getString("OpenPHPPerspectiveAction.error.open_failed")); //$NON-NLS-1$
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/PHPEditorActionDefinitionIds.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/PHPEditorActionDefinitionIds.java
new file mode 100644
index 0000000..13c5b40
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/PHPEditorActionDefinitionIds.java
@@ -0,0 +1,42 @@
+package net.sourceforge.phpdt.ui.actions;
+
+public interface PHPEditorActionDefinitionIds {
+ /**
+ * Value: net.sourceforge.phpeclipse.phpeditor.comment
+ */
+ public static final String COMMENT = "net.sourceforge.phpdt.ui.actions.comment";
+
+ /**
+ * Value: net.sourceforge.phpeclipse.phpeditor.uncomment
+ */
+ public static final String UNCOMMENT = "net.sourceforge.phpdt.ui.actions.uncomment";
+
+ // navigate
+
+ /**
+ * Action definition ID of the navigate -> open action (value
+ * "org.phpeclipse.phpdt.ui.edit.text.php.open.editor"
).
+ */
+ public static final String OPEN_EDITOR = "net.sourceforge.phpeclipse.ui.edit.text.java.open.editor"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the toggle presentation toolbar button action
+ * (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.toggle.presentation"
).
+ */
+ public static final String TOGGLE_PRESENTATION = "net.sourceforge.phpeclipse.ui.edit.text.java.toggle.presentation"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the toggle text hover toolbar button action
+ * (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.toggle.text.hover"
).
+ */
+ public static final String TOGGLE_TEXT_HOVER = "net.sourceforge.phpeclipse.ui.edit.text.java.toggle.text.hover"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the edit -> show Javadoc action (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.show.javadoc"
).
+ */
+ public static final String SHOW_JAVADOC = "net.sourceforge.phpeclipse.ui.edit.text.java.show.javadoc"; //$NON-NLS-1$
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/PHPdtActionConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/PHPdtActionConstants.java
new file mode 100644
index 0000000..b7b5df5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/PHPdtActionConstants.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui.actions;
+
+/**
+ * Action ids for standard actions, for groups in the menu bar, and for actions
+ * in context menus of PHPDT views.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * @since 2.0
+ */
+public class PHPdtActionConstants {
+
+ // Edit menu
+ /**
+ * Edit menu: name of standard Show Javadoc global action (value
+ * "net.sourceforge.phpdt.ui.actions.ShowJavaDoc"
).
+ */
+ public static final String SHOW_JAVA_DOC = "net.sourceforge.phpeclipse.phpeditor.ShowJavaDoc"; //$NON-NLS-1$
+
+ /**
+ * Edit menu: name of standard Code Assist global action (value
+ * "org.phpeclipse.phpdt.ui.actions.ContentAssist"
).
+ */
+ public static final String CONTENT_ASSIST = "net.sourceforge.phpeclipse.phpeditor.ContentAssist"; //$NON-NLS-1$
+
+ // Source menu
+
+ /**
+ * Source menu: name of standard Comment global action (value
+ * "net.sourceforge.phpdt.ui.actions.Comment"
).
+ */
+ public static final String COMMENT = "net.sourceforge.phpeclipse.phpeditor.Comment"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Uncomment global action (value
+ * "net.sourceforge.phpdt.ui.actions.Uncomment"
).
+ */
+ public static final String UNCOMMENT = "net.sourceforge.phpeclipse.phpeditor.Uncomment"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard ToggleComment global action (value
+ * "net.sourceforge.phpdt.ui.actions.ToggleComment"
).
+ *
+ * @since 3.0
+ */
+ public static final String TOGGLE_COMMENT = "net.sourceforge.phpeclipse.ui.actions.ToggleComment"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Comment global action (value
+ * "net.sourceforge.phpdt.ui.actions.AddBlockComment"
).
+ *
+ * @since 3.0
+ */
+ public static final String ADD_BLOCK_COMMENT = "net.sourceforge.phpeclipse.ui.actions.AddBlockComment"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Uncomment global action (value
+ * "net.sourceforge.phpdt.ui.actions.RemoveBlockComment"
).
+ *
+ * @since 3.0
+ */
+ public static final String REMOVE_BLOCK_COMMENT = "net.sourceforge.phpeclipse.ui.actions.RemoveBlockComment"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Indent global action (value
+ * "net.sourceforge.phpdt.ui.actions.Indent"
).
+ *
+ * @since 3.0
+ */
+ public static final String INDENT = "net.sourceforge.phpeclipse.ui.actions.Indent"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Shift Rightl action (value
+ * "net.sourceforge.phpeclipse.phpeditor.ShiftRight"
).
+ */
+ public static final String SHIFT_RIGHT = "net.sourceforge.phpeclipse.phpeditor.ShiftRight"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Shift Left global action (value
+ * "net.sourceforge.phpeclipse.phpeditor.ShiftLeft"
).
+ */
+ public static final String SHIFT_LEFT = "net.sourceforge.phpeclipse.phpeditor.ShiftLeft"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Format global action (value "org.
+ * phpeclipse.phpdt.ui.actions.Format"
).
+ */
+ public static final String FORMAT = "net.sourceforge.phpeclipse.phpeditor.Format"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Convert Line Delimiters To Windows global
+ * action (value
+ * "org.phpeclipse.phpdt.ui.actions.ConvertLineDelimitersToWindows"
).
+ */
+ public static String CONVERT_LINE_DELIMITERS_TO_WINDOWS = "net.sourceforge.phpeclipse.ui.actions.ConvertLineDelimitersToWindows"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard Convert Line Delimiters To UNIX global
+ * action (value
+ * "org.phpeclipse.phpdt.ui.actions.ConvertLineDelimitersToUNIX"
).
+ */
+ public static String CONVERT_LINE_DELIMITERS_TO_UNIX = "net.sourceforge.phpeclipse.ui.actions.ConvertLineDelimitersToUNIX"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standardConvert Line Delimiters ToMac global action
+ * (value
+ * "org.phpeclipse.phpdt.ui.actions.ConvertLineDelimitersToMac"
).
+ */
+ public static String CONVERT_LINE_DELIMITERS_TO_MAC = "net.sourceforge.phpeclipse.ui.actions.ConvertLineDelimitersToMac"; //$NON-NLS-1$
+
+ /**
+ * Navigate menu: name of standard Open global action (value
+ * "org.phpeclipse.phpdt.ui.actions.Open"
).
+ */
+ public static final String OPEN = "net.sourceforge.phpeclipse.ui.actions.Open"; //$NON-NLS-1$
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/SelectionDispatchAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/SelectionDispatchAction.java
new file mode 100644
index 0000000..41d8d34
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/actions/SelectionDispatchAction.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchSite;
+
+/**
+ * Action that dispatches the IAction#run()
and the
+ * ISelectionChangedListener#selectionChanged
according to the
+ * type of the selection.
+ *
+ *
+ * - if selection is of type
ITextSelection
then
+ * run(ITextSelection)
and
+ * selectionChanged(ITextSelection)
is called.
+ * - if selection is of type
IStructuredSelection
then
+ * run(IStructuredSelection)
and
+ * selectionChanged(IStructuredSelection)
+ * is called.
+ * - default is to call
run(ISelection)
and
+ * selectionChanged(ISelection)
.
+ *
+ *
+ *
+ * Note: This class is not intended to be subclassed outside the JDT UI plugin.
+ *
+ *
+ * @since 2.0
+ */
+public abstract class SelectionDispatchAction extends Action implements
+ ISelectionChangedListener {
+
+ private IWorkbenchSite fSite;
+
+ /**
+ * Creates a new action with no text and no image.
+ *
+ * Configure the action later using the set methods.
+ *
+ *
+ * @param site
+ * the site this action is working on
+ */
+ protected SelectionDispatchAction(IWorkbenchSite site) {
+ Assert.isNotNull(site);
+ fSite = site;
+ }
+
+ /**
+ * Returns the site owning this action.
+ *
+ * @return the site owning this action
+ */
+ public IWorkbenchSite getSite() {
+ return fSite;
+ }
+
+ /**
+ * Returns the selection provided by the site owning this action.
+ *
+ * @return the site's selection
+ */
+ public ISelection getSelection() {
+ return getSelectionProvider().getSelection();
+ }
+
+ /**
+ * Returns the shell provided by the site owning this action.
+ *
+ * @return the site's shell
+ */
+ public Shell getShell() {
+ return fSite.getShell();
+ }
+
+ /**
+ * Returns the selection provider managed by the site owning this action.
+ *
+ * @return the site's selection provider
+ */
+ public ISelectionProvider getSelectionProvider() {
+ return fSite.getSelectionProvider();
+ }
+
+ /**
+ * Updates the action's enablement state according to the given selection.
+ * This default implementation calls one of the
+ * selectionChanged
methods depending on the type of the
+ * passed selection.
+ *
+ * @param selection
+ * the selection this action is working on
+ */
+ public void update(ISelection selection) {
+ dispatchSelectionChanged(selection);
+ }
+
+ /**
+ * Notifies this action that the given structured selection has changed.
+ * This default implementation calls
+ * selectionChanged(ISelection selection)
.
+ *
+ * @param selection
+ * the new selection
+ */
+ protected void selectionChanged(IStructuredSelection selection) {
+ selectionChanged((ISelection) selection);
+ }
+
+ /**
+ * Executes this actions with the given structured selection. This default
+ * implementation calls run(ISelection selection)
.
+ */
+ protected void run(IStructuredSelection selection) {
+ run((ISelection) selection);
+ }
+
+ /**
+ * Notifies this action that the given text selection has changed. This
+ * default implementation calls
+ * selectionChanged(ISelection selection)
.
+ *
+ * @param selection
+ * the new selection
+ */
+ protected void selectionChanged(ITextSelection selection) {
+ selectionChanged((ISelection) selection);
+ }
+
+ /**
+ * Executes this actions with the given text selection. This default
+ * implementation calls run(ISelection selection)
.
+ */
+ protected void run(ITextSelection selection) {
+ run((ISelection) selection);
+ }
+
+ /**
+ * Notifies this action that the given selection has changed. This default
+ * implementation sets the action's enablement state to false
.
+ *
+ * @param selection
+ * the new selection
+ */
+ protected void selectionChanged(ISelection selection) {
+ setEnabled(false);
+ }
+
+ /**
+ * Executes this actions with the given selection. This default
+ * implementation does nothing.
+ */
+ protected void run(ISelection selection) {
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IAction.
+ */
+ public void run() {
+ dispatchRun(getSelection());
+ }
+
+ /*
+ * (non-Javadoc) Method declared on ISelectionChangedListener.
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ dispatchSelectionChanged(event.getSelection());
+ }
+
+ private void dispatchSelectionChanged(ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ selectionChanged((IStructuredSelection) selection);
+ } else if (selection instanceof ITextSelection) {
+ selectionChanged((ITextSelection) selection);
+ } else {
+ selectionChanged(selection);
+ }
+ }
+
+ private void dispatchRun(ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ run((IStructuredSelection) selection);
+ } else if (selection instanceof ITextSelection) {
+ run((ITextSelection) selection);
+ } else {
+ run(selection);
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IColorManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IColorManager.java
new file mode 100644
index 0000000..2a6b3a5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IColorManager.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui.text;
+
+import org.eclipse.jface.text.source.ISharedTextColors;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Manages SWT color objects for given color keys and given RGB
+ * objects. Until the dispose
method is called, the same color
+ * object is returned for equal keys and equal RGB
values.
+ *
+ * This interface may be implemented by clients.
+ *
+ *
+ * @see IJavaColorConstants
+ */
+public interface IColorManager extends ISharedTextColors {
+
+ /**
+ * Returns a color object for the given key. The color objects are
+ * remembered internally; the same color object is returned for equal keys.
+ *
+ * @param key
+ * the color key
+ * @return the color object for the given key
+ */
+ Color getColor(String key);
+
+ /**
+ * Returns the color object for the value represented by the given
+ * RGB
object.
+ *
+ * @param rgb
+ * the rgb color specification
+ * @return the color object for the given rgb value
+ */
+ Color getColor(RGB rgb);
+
+ /**
+ * Disposes all color objects remembered by this color manager.
+ */
+ void dispose();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IColorManagerExtension.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IColorManagerExtension.java
new file mode 100644
index 0000000..15c0346
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IColorManagerExtension.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui.text;
+
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * A color manager extension for extending IColorManager
+ * instances with new functionality.
+ *
+ * @since 2.0
+ */
+public interface IColorManagerExtension {
+
+ /**
+ * Remembers the given color specification under the given key.
+ *
+ * @param key
+ * the color key
+ * @param rgb
+ * the color specification
+ * @exception UnsupportedOperationException
+ * if there is already a color specification remembered under
+ * the given key
+ */
+ void bindColor(String key, RGB rgb);
+
+ /**
+ * Forgets the color specification remembered under the given key.
+ *
+ * @param key
+ * the color key
+ */
+ void unbindColor(String key);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IJavaColorConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IJavaColorConstants.java
new file mode 100644
index 0000000..936d157
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/IJavaColorConstants.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.ui.text;
+
+/**
+ * Color keys used for syntax highlighting PHP code and PHPDoc compliant
+ * comments. A IColorManager
is responsible for mapping concrete
+ * colors to these keys.
+ *
+ * This interface declares static final fields only; it is not intended to be
+ * implemented.
+ *
+ *
+ * @see IColorManager
+ */
+public interface IJavaColorConstants {
+
+ /**
+ * Note: This constant is for internal use only. Clients should not use this
+ * constant. The prefix all color constants start with.
+ */
+ // String PREFIX= "php_"; //$NON-NLS-1$
+ //
+ // /** The color key for multi-line comments in PHP code. */
+ // String PHP_MULTI_LINE_COMMENT= "php_multi_line_comment"; //$NON-NLS-1$
+ // /** The color key for single-line comments in PHP code. */
+ // String PHP_SINGLE_LINE_COMMENT= "php_single_line_comment"; //$NON-NLS-1$
+ // /** The color key for PHP keywords in PHP code. */
+ // String PHP_KEYWORD= "php_keyword"; //$NON-NLS-1$
+ // /** The color key for string and character literals in PHP code. */
+ // String PHP_STRING= "php_string"; //$NON-NLS-1$
+ // /** The color key for everthing in PHP code for which no other color is
+ // specified. */
+ // String PHP_DEFAULT= "php_default"; //$NON-NLS-1$
+ // /** The color key for predefined PHP function namesin PHP code. */
+ // String PHP_FUNCTIONNAME= "php_functionname"; //$NON-NLS-1$
+ // /** The color key for ($-)variables in PHP code. */
+ // String PHP_VARIABLE= "php_variable"; //$NON-NLS-1$
+ // /** The color key for constants in PHP code */
+ // String PHP_CONSTANT= "php_constant"; //$NON-NLS-1$
+ // /** The color key for the PHP built-in types in PHP code. */
+ // String PHP_TYPE= "php_type"; //$NON-NLS-1$
+
+ // /** The color key for PHPDoc keywords (@foo
) in PHPDoc
+ // comments. */
+ // String PHPDOC_KEYWORD= "php_doc_keyword"; //$NON-NLS-1$
+ // /** The color key for HTML tags (<foo>
) in PHPDoc
+ // comments. */
+ // String PHPDOC_TAG= "php_doc_tag"; //$NON-NLS-1$
+ // /** The color key for PHPDoc links ({foo}
) in PHPDoc
+ // comments. */
+ // String PHPDOC_LINK= "php_doc_link"; //$NON-NLS-1$
+ // /** The color key for everthing in PHPDoc comments for which no other
+ // color is specified. */
+ // String PHPDOC_DEFAULT= "php_doc_default"; //$NON-NLS-1$
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java
new file mode 100644
index 0000000..028bc82
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java
@@ -0,0 +1,736 @@
+package net.sourceforge.phpdt.ui.text;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import net.sourceforge.phpdt.internal.ui.text.FastJavaPartitionScanner;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaColorManager;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.PHPDocCodeScanner;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.phpeditor.php.HTMLPartitionScanner;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPCodeScanner;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPPartitionScanner;
+import net.sourceforge.phpeclipse.phpeditor.php.SmartyCodeScanner;
+import net.sourceforge.phpeclipse.phpeditor.php.SmartyDocCodeScanner;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.DefaultPartitioner;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+//
+// import org.phpeclipse.phpdt.internal.ui.text.FastJavaPartitionScanner;
+// import org.phpeclipse.phpdt.internal.ui.text.JavaColorManager;
+// import org.phpeclipse.phpdt.internal.ui.text.JavaPartitionScanner;
+// import org.phpeclipse.phpdt.internal.ui.text.SingleTokenJavaScanner;
+// import org.phpeclipse.phpdt.internal.ui.text.php.JavaCodeScanner;
+// import org.phpeclipse.phpdt.internal.ui.text.phpdoc.JavaDocScanner;
+
+/**
+ * Tools required to configure a Java text viewer. The color manager and all
+ * scanner exist only one time, i.e. the same instances are returned to all
+ * clients. Thus, clients share those tools.
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ */
+public class JavaTextTools implements IPHPPartitions {
+ // private static final String[] TOKENS = {
+ // JSPScriptScanner.JSP_DEFAULT,
+ // JSPScriptScanner.JSP_BRACKET };
+ private final static String[] LEGAL_CONTENT_TYPES = new String[] {
+ PHP_PHPDOC_COMMENT, PHP_MULTILINE_COMMENT, PHP_SINGLELINE_COMMENT,
+ PHP_STRING_DQ, PHP_STRING_SQ, PHP_STRING_HEREDOC };
+
+ // private static XMLPartitionScanner HTML_PARTITION_SCANNER = null;
+
+ // private static FastJavaPartitionScanner PHP_PARTITION_SCANNER = null;
+
+ private static HTMLPartitionScanner SMARTY_PARTITION_SCANNER = null;
+
+ // private static XMLPartitionScanner XML_PARTITION_SCANNER = null;
+
+ // private final static String[] TYPES= new String[] {
+ // PHPPartitionScanner.PHP, PHPPartitionScanner.JAVA_DOC,
+ // PHPPartitionScanner.JAVA_MULTILINE_COMMENT };
+ // private final static String[] TYPES = new String[] {
+ // IPHPPartitions.PHP_PARTITIONING,
+ // IPHPPartitions.PHP_PHPDOC_COMMENT,
+ // // IPHPPartitions.HTML,
+ // // IPHPPartitions.HTML_MULTILINE_COMMENT,
+ // IPHPPartitions.JAVASCRIPT,
+ // IPHPPartitions.CSS,
+ // IPHPPartitions.SMARTY,
+ // IPHPPartitions.SMARTY_MULTILINE_COMMENT };
+
+ /**
+ * This tools' preference listener.
+ */
+ private class PreferenceListener implements IPropertyChangeListener,
+ Preferences.IPropertyChangeListener {
+ public void propertyChange(PropertyChangeEvent event) {
+ adaptToPreferenceChange(event);
+ }
+
+ public void propertyChange(Preferences.PropertyChangeEvent event) {
+ adaptToPreferenceChange(new PropertyChangeEvent(event.getSource(),
+ event.getProperty(), event.getOldValue(), event
+ .getNewValue()));
+ }
+ };
+
+ // /** The color manager */
+ private JavaColorManager colorManager;
+
+ /** The PHP source code scanner */
+ private PHPCodeScanner fCodeScanner;
+
+ /** The PHP multiline comment scanner */
+ private SingleTokenPHPScanner fMultilineCommentScanner;
+
+ /** The Java singleline comment scanner */
+ private SingleTokenPHPScanner fSinglelineCommentScanner;
+
+ /** The PHP double quoted string scanner */
+ // private SingleTokenPHPScanner fStringDQScanner;
+ /** The PHP single quoted string scanner */
+ // private SingleTokenPHPScanner fStringSQScanner;
+ /** The PHPDoc scanner */
+ private PHPDocCodeScanner fPHPDocScanner;
+
+ /** The HTML scanner */
+ // private HTMLCodeScanner fHTMLScanner;
+ /** The Smarty scanner */
+ private SmartyCodeScanner fSmartyScanner;
+
+ /** The SmartyDoc scanner */
+ private SmartyDocCodeScanner fSmartyDocScanner;
+
+ /** The Java partitions scanner. */
+ private FastJavaPartitionScanner fPartitionScanner;
+
+ /** The preference store */
+ private IPreferenceStore fPreferenceStore;
+
+ /** The XML Language text tools */
+ private XMLTextTools xmlTextTools;
+
+ /**
+ * The core preference store.
+ *
+ * @since 2.1
+ */
+ private Preferences fCorePreferenceStore;
+
+ /** The preference change listener */
+ private PreferenceListener fPreferenceListener = new PreferenceListener();
+
+ /** The JSP partitions scanner */
+ private PHPPartitionScanner jspPartitionScanner = null;
+
+ /** The JSP script subpartitions scanner */
+ // private JSPScriptScanner jspScriptScanner;
+ /** The PHP plain text scanner */
+ // private RuleBasedScanner jspTextScanner;
+ /** The PHP brackets scanner */
+ // private RuleBasedScanner jspBracketScanner;
+ /**
+ * Creates a new Java text tools collection.
+ *
+ * @param store
+ * the preference store to initialize the text tools. The text
+ * tool instance installs a listener on the passed preference
+ * store to adapt itself to changes in the preference store. In
+ * general PreferenceConstants.
+ * getPreferenceStore()
+ * should be used to initialize the text tools.
+ * @param coreStore
+ * optional preference store to initialize the text tools. The
+ * text tool instance installs a listener on the passed
+ * preference store to adapt itself to changes in the preference
+ * store.
+ * @see net.sourceforge.phpdt.ui.PreferenceConstants#getPreferenceStore()
+ * @since 2.1
+ */
+ public JavaTextTools(IPreferenceStore store, Preferences coreStore) {
+ this(store, coreStore, true);
+ }
+
+ /**
+ * Creates a new Java text tools collection.
+ *
+ * @param store
+ * the preference store to initialize the text tools. The text
+ * tool instance installs a listener on the passed preference
+ * store to adapt itself to changes in the preference store. In
+ * general PreferenceConstants.
+ * getPreferenceStore()
+ * shoould be used to initialize the text tools.
+ * @param coreStore
+ * optional preference store to initialize the text tools. The
+ * text tool instance installs a listener on the passed
+ * preference store to adapt itself to changes in the preference
+ * store.
+ * @param autoDisposeOnDisplayDispose
+ * if true
the color manager automatically
+ * disposes all managed colors when the current display gets
+ * disposed and all calls to
+ * {@link org.eclipse.jface.text.source.ISharedTextColors#dispose()}are
+ * ignored.
+ * @see net.sourceforge.phpdt.ui.PreferenceConstants#getPreferenceStore()
+ * @since 2.1
+ */
+ public JavaTextTools(IPreferenceStore store, Preferences coreStore,
+ boolean autoDisposeOnDisplayDispose) {
+ // super(store, TOKENS, );
+ // REVISIT: preference store
+ xmlTextTools = new XMLTextTools(/*XMLPlugin*/WebUI.getDefault()
+ .getPreferenceStore());
+
+ colorManager = new JavaColorManager(autoDisposeOnDisplayDispose);
+ fPreferenceStore = store;
+ fPreferenceStore.addPropertyChangeListener(fPreferenceListener);
+
+ fCorePreferenceStore = coreStore;
+ if (fCorePreferenceStore != null)
+ fCorePreferenceStore.addPropertyChangeListener(fPreferenceListener);
+
+ fCodeScanner = new PHPCodeScanner((JavaColorManager) colorManager,
+ store);
+ fMultilineCommentScanner = new SingleTokenPHPScanner(
+ (JavaColorManager) colorManager, store,
+ IPreferenceConstants.PHP_MULTILINE_COMMENT);
+ fSinglelineCommentScanner = new SingleTokenPHPScanner(
+ (JavaColorManager) colorManager, store,
+ IPreferenceConstants.PHP_SINGLELINE_COMMENT);
+ // fStringDQScanner = new SingleTokenPHPScanner((JavaColorManager)
+ // colorManager, store, IPreferenceConstants.PHP_STRING);
+ // fStringSQScanner = new SingleTokenPHPScanner((JavaColorManager)
+ // colorManager, store, IPreferenceConstants.PHP_STRING);
+
+ fPHPDocScanner = new PHPDocCodeScanner((JavaColorManager) colorManager,
+ store);
+ // fHTMLScanner = new HTMLCodeScanner((JavaColorManager)fColorManager,
+ // store);
+ fSmartyScanner = new SmartyCodeScanner((JavaColorManager) colorManager,
+ store);
+ fSmartyDocScanner = new SmartyDocCodeScanner(
+ (JavaColorManager) colorManager, store);
+
+ fPartitionScanner = new FastJavaPartitionScanner();
+
+ // jspScriptScanner = new JSPScriptScanner();
+ // fPartitionScanner = new FastJavaPartitionScanner();
+ // fPartitionScanner = new PHPPartitionScanner();
+
+ // jspBracketScanner = new RuleBasedScanner();
+ // jspBracketScanner.setDefaultReturnToken(new
+ // Token(JSPScriptScanner.JSP_BRACKET));
+ // jspTextScanner = new RuleBasedScanner();
+ // jspTextScanner.setDefaultReturnToken(new
+ // Token(JSPScriptScanner.JSP_DEFAULT));
+ }
+
+ /**
+ *
+ */
+ public XMLTextTools getXMLTextTools() {
+ return xmlTextTools;
+ }
+
+ /**
+ * Disposes all the individual tools of this tools collection.
+ */
+ public void dispose() {
+
+ fCodeScanner = null;
+ fMultilineCommentScanner = null;
+ fSinglelineCommentScanner = null;
+ // fStringDQScanner = null;
+ // fStringSQScanner = null;
+ fPHPDocScanner = null;
+ // fPartitionScanner = null;
+
+ if (colorManager != null) {
+ colorManager.dispose();
+ colorManager = null;
+ }
+
+ if (fPreferenceStore != null) {
+ fPreferenceStore.removePropertyChangeListener(fPreferenceListener);
+ fPreferenceStore = null;
+
+ if (fCorePreferenceStore != null) {
+ fCorePreferenceStore
+ .removePropertyChangeListener(fPreferenceListener);
+ fCorePreferenceStore = null;
+ }
+
+ fPreferenceListener = null;
+ }
+ }
+
+ /**
+ * Returns the color manager which is used to manage any Java-specific
+ * colors needed for such things like syntax highlighting.
+ *
+ * @return the color manager to be used for Java text viewers
+ */
+ public JavaColorManager getColorManager() {
+ return (JavaColorManager) colorManager;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan Java source code.
+ *
+ * @return a Java source code scanner
+ */
+ public RuleBasedScanner getCodeScanner() {
+ return fCodeScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan Java multiline comments.
+ *
+ * @return a Java multiline comment scanner
+ *
+ * @since 2.0
+ */
+ public RuleBasedScanner getMultilineCommentScanner() {
+ return fMultilineCommentScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan HTML code.
+ *
+ * @return a HTML scanner
+ *
+ * @since 2.0
+ */
+ // public RuleBasedScanner getHTMLScanner() {
+ // return fHTMLScanner;
+ // }
+ /**
+ * Returns a scanner which is configured to scan Smarty code.
+ *
+ * @return a Smarty scanner
+ *
+ * @since 2.0
+ */
+ public RuleBasedScanner getSmartyScanner() {
+ return fSmartyScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan Smarty code.
+ *
+ * @return a Smarty scanner
+ *
+ * @since 2.0
+ */
+ public RuleBasedScanner getSmartyDocScanner() {
+ return fSmartyDocScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan Java singleline comments.
+ *
+ * @return a Java singleline comment scanner
+ *
+ * @since 2.0
+ */
+ public RuleBasedScanner getSinglelineCommentScanner() {
+ return fSinglelineCommentScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan Java strings.
+ *
+ * @return a Java string scanner
+ *
+ * @since 2.0
+ */
+ // public RuleBasedScanner getStringScanner() {
+ // return fStringDQScanner;
+ // }
+ /**
+ * Returns a scanner which is configured to scan JavaDoc compliant comments.
+ * Notes that the start sequence "/**" and the corresponding end sequence
+ * are part of the JavaDoc comment.
+ *
+ * @return a JavaDoc scanner
+ */
+ public RuleBasedScanner getJavaDocScanner() {
+ return fPHPDocScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan Java-specific partitions,
+ * which are multi-line comments, JavaDoc comments, and regular Java source
+ * code.
+ *
+ * @return a Java partition scanner
+ */
+ // public IPartitionTokenScanner getPartitionScanner() {
+ // return fPartitionScanner;
+ // }
+ /**
+ * Factory method for creating a PHP-specific document partitioner using
+ * this object's partitions scanner. This method is a convenience method.
+ *
+ * @return a newly created Java document partitioner
+ */
+ public IDocumentPartitioner createDocumentPartitioner() {
+ return createDocumentPartitioner(".php");
+ }
+
+ /**
+ * Factory method for creating a PHP-specific document partitioner using
+ * this object's partitions scanner. This method is a convenience method.
+ *
+ * @return a newly created Java document partitioner
+ */
+ public IDocumentPartitioner createDocumentPartitioner(String extension) {
+
+ // String[] types =
+ // new String[] {
+ // FastJavaPartitionScanner.JAVA_DOC,
+ // FastJavaPartitionScanner.JAVA_MULTI_LINE_COMMENT,
+ // FastJavaPartitionScanner.JAVA_SINGLE_LINE_COMMENT,
+ // FastJavaPartitionScanner.JAVA_STRING };
+ //
+ // return new DefaultPartitioner(getPartitionScanner(), types);
+ IDocumentPartitioner partitioner = null;
+ // System.out.println(extension);
+ if (extension.equalsIgnoreCase(".html")
+ || extension.equalsIgnoreCase(".htm")) {
+ // html
+ partitioner = createHTMLPartitioner();
+ partitioner = createJSPPartitioner();
+ } else if (extension.equalsIgnoreCase(".xml")) {
+ // xml
+ partitioner = createXMLPartitioner();
+ // } else if (extension.equalsIgnoreCase(".js")) {
+ // // javascript
+ // partitioner = createJavaScriptPartitioner();
+ // } else if (extension.equalsIgnoreCase(".css")) {
+ // // cascading style sheets
+ // partitioner = createCSSPartitioner();
+ } else if (extension.equalsIgnoreCase(".tpl")) {
+ // smarty ?
+ partitioner = createSmartyPartitioner();
+ // } else if (extension.equalsIgnoreCase(".inc")) {
+ // // php include files ?
+ // partitioner = createIncludePartitioner();
+ }
+
+ if (partitioner == null) {
+ partitioner = createJSPPartitioner();
+ }
+
+ return partitioner;
+ }
+
+ /**
+ * Sets up the Java document partitioner for the given document for the
+ * given partitioning.
+ *
+ * @param document
+ * the document to be set up
+ * @param partitioning
+ * the document partitioning
+ * @param element
+ * TODO
+ *
+ * @since 3.0
+ */
+ // public void setupJavaDocumentPartitioner(IDocument document, String
+ // partitioning, Object element) {
+ // IDocumentPartitioner partitioner = createDocumentPartitioner(".php");
+ //
+ // // if (document instanceof IDocumentExtension3) {
+ // // IDocumentExtension3 extension3= (IDocumentExtension3) document;
+ // // extension3.setDocumentPartitioner(partitioning, partitioner);
+ // // } else {
+ // document.setDocumentPartitioner(partitioner);
+ // // }
+ // partitioner.connect(document);
+ // }
+ public void setupHTMLDocumentPartitioner(IDocument document,
+ String partitioning, Object element) {
+ IDocumentPartitioner partitioner = createDocumentPartitioner(".html");
+
+ // if (document instanceof IDocumentExtension3) {
+ // IDocumentExtension3 extension3= (IDocumentExtension3) document;
+ // extension3.setDocumentPartitioner(partitioning, partitioner);
+ // } else {
+ document.setDocumentPartitioner(partitioner);
+ // }
+ partitioner.connect(document);
+ }
+
+ public void setupSmartyDocumentPartitioner(IDocument document,
+ String partitioning, Object element) {
+ IDocumentPartitioner partitioner = createDocumentPartitioner(".tpl");
+
+ // if (document instanceof IDocumentExtension3) {
+ // IDocumentExtension3 extension3= (IDocumentExtension3) document;
+ // extension3.setDocumentPartitioner(partitioning, partitioner);
+ // } else {
+ document.setDocumentPartitioner(partitioner);
+ // }
+ partitioner.connect(document);
+ }
+
+ /**
+ * Returns the names of the document position categories used by the
+ * document partitioners created by this object to manage their partition
+ * information. If the partitioners don't use document position categories,
+ * the returned result is null
.
+ *
+ * @return the partition managing position categories or null
+ * if there is none
+ */
+ public String[] getPartitionManagingPositionCategories() {
+ return new String[] { DefaultPartitioner.CONTENT_TYPES_CATEGORY };
+ }
+
+ /**
+ * Determines whether the preference change encoded by the given event
+ * changes the behavior of one its contained components.
+ *
+ * @param event
+ * the event to be investigated
+ * @return true
if event causes a behavioral change
+ * @since 2.0
+ * @deprecated As of 3.0, replaced by
+ * {@link net.sourceforge.phpdt.ui.text.JavaSourceViewerConfiguration#affectsTextPresentation(PropertyChangeEvent)}
+ */
+ // public boolean affectsBehavior(PropertyChangeEvent event) {
+ // return fCodeScanner.affectsBehavior(event)
+ // || fMultilineCommentScanner.affectsBehavior(event)
+ // || fSinglelineCommentScanner.affectsBehavior(event)
+ // || fStringDQScanner.affectsBehavior(event)
+ // || fPHPDocScanner.affectsBehavior(event);
+ // }
+ /**
+ * Adapts the behavior of the contained components to the change encoded in
+ * the given event.
+ *
+ * @param event
+ * the event to which to adapt
+ * @since 2.0
+ */
+ protected void adaptToPreferenceChange(PropertyChangeEvent event) {
+ if (fCodeScanner.affectsBehavior(event))
+ fCodeScanner.adaptToPreferenceChange(event);
+ if (fMultilineCommentScanner.affectsBehavior(event))
+ fMultilineCommentScanner.adaptToPreferenceChange(event);
+ if (fSinglelineCommentScanner.affectsBehavior(event))
+ fSinglelineCommentScanner.adaptToPreferenceChange(event);
+ // if (fStringDQScanner.affectsBehavior(event))
+ // fStringDQScanner.adaptToPreferenceChange(event);
+ if (fPHPDocScanner.affectsBehavior(event))
+ fPHPDocScanner.adaptToPreferenceChange(event);
+ // if (fHTMLScanner.affectsBehavior(event))
+ // fHTMLScanner.adaptToPreferenceChange(event);
+ if (fSmartyScanner.affectsBehavior(event))
+ fSmartyScanner.adaptToPreferenceChange(event);
+ if (fSmartyDocScanner.affectsBehavior(event))
+ fSmartyDocScanner.adaptToPreferenceChange(event);
+ // if (XMLPlugin.getDefault().getXMLTextTools().affectsBehavior(event))
+ // {
+ // XMLPlugin.getDefault().getXMLTextTools().adaptToPreferenceChange(event);
+ // }
+ }
+
+ /**
+ * Return a partitioner for .html files.
+ */
+ public IDocumentPartitioner createHTMLPartitioner() {
+ // return new DefaultPartitioner(getHTMLPartitionScanner(), TYPES);
+ return xmlTextTools.createXMLPartitioner();
+ }
+
+ // private static IDocumentPartitioner createIncludePartitioner() {
+ // // return new DefaultPartitioner(getPHPPartitionScanner(), TYPES);
+ // return new DefaultPartitioner(getPHPPartitionScanner(),
+ // FastJavaPartitionScanner.PHP_PARTITION_TYPES);
+ //
+ // }
+
+ // private static IDocumentPartitioner createJavaScriptPartitioner() {
+ // return new DefaultPartitioner(getHTMLPartitionScanner(), TYPES);
+ // }
+
+ /**
+ * Return a partitioner for .php files.
+ */
+ public IDocumentPartitioner createPHPPartitioner() {
+ // return new DefaultPartitioner(getPHPPartitionScanner(), TYPES);
+ return new DefaultPartitioner(getPHPPartitionScanner(),
+ LEGAL_CONTENT_TYPES);
+ }
+
+ private IDocumentPartitioner createJSPPartitioner() {
+ return new PHPDocumentPartitioner(getJSPPartitionScanner());
+ // return new JSPDocumentPartitioner(getJSPPartitionScanner(),
+ // jspScriptScanner);
+ }
+
+ /**
+ *
+ */
+ // public IPartitionTokenScanner getJSPScriptScanner() {
+ // return jspScriptScanner;
+ // }
+ private IDocumentPartitioner createSmartyPartitioner() {
+ return new DefaultPartitioner(getSmartyPartitionScanner(),
+ XMLTextTools.TYPES);
+ }
+
+ private IDocumentPartitioner createXMLPartitioner() {
+ // return new DefaultPartitioner(getXMLPartitionScanner(),
+ // XMLTextTools.TYPES);
+ return xmlTextTools.createXMLPartitioner();
+ }
+
+ // private IDocumentPartitioner createCSSPartitioner() {
+ // return new DefaultPartitioner(getHTMLPartitionScanner(),
+ // XMLTextTools.TYPES);
+ // }
+
+ /**
+ * Return a scanner for creating html partitions.
+ */
+ // private static XMLPartitionScanner getHTMLPartitionScanner() {
+ // // if (HTML_PARTITION_SCANNER == null)
+ // // HTML_PARTITION_SCANNER = new
+ // HTMLPartitionScanner(IPHPPartitions.HTML_FILE);
+ // // return HTML_PARTITION_SCANNER;^
+ // if (HTML_PARTITION_SCANNER == null)
+ // HTML_PARTITION_SCANNER = new XMLPartitionScanner(false);
+ // return HTML_PARTITION_SCANNER;
+ // }
+ /**
+ * Return a scanner for creating php partitions.
+ */
+ private FastJavaPartitionScanner getPHPPartitionScanner() {
+ // if (PHP_PARTITION_SCANNER == null)
+ // PHP_PARTITION_SCANNER = new FastJavaPartitionScanner(); //new
+ // PHPPartitionScanner(IPHPPartitions.PHP_FILE);
+ // return PHP_PARTITION_SCANNER;
+ return fPartitionScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan plain text in JSP.
+ *
+ * @return a JSP text scanner
+ */
+ // public RuleBasedScanner getJSPTextScanner() {
+ // return jspTextScanner;
+ // }
+ /**
+ * Returns a scanner which is configured to scan plain text in JSP.
+ *
+ * @return a JSP text scanner
+ */
+ // public RuleBasedScanner getJSPBracketScanner() {
+ // return jspBracketScanner;
+ // }
+ /**
+ * Return a scanner for creating smarty partitions.
+ */
+ private static HTMLPartitionScanner getSmartyPartitionScanner() {
+ if (SMARTY_PARTITION_SCANNER == null)
+ SMARTY_PARTITION_SCANNER = new HTMLPartitionScanner(
+ IPHPPartitions.SMARTY_FILE);
+ return SMARTY_PARTITION_SCANNER;
+ }
+
+ /**
+ * Return a scanner for creating xml partitions.
+ */
+ // private static XMLPartitionScanner getXMLPartitionScanner() {
+ // // if (XML_PARTITION_SCANNER == null)
+ // // XML_PARTITION_SCANNER = new
+ // HTMLPartitionScanner(IPHPPartitions.XML_FILE);
+ // // return XML_PARTITION_SCANNER;
+ // if (XML_PARTITION_SCANNER == null)
+ // XML_PARTITION_SCANNER = new XMLPartitionScanner(false);
+ // return XML_PARTITION_SCANNER;
+ // }
+ private PHPPartitionScanner getJSPPartitionScanner() {
+ if (jspPartitionScanner == null)
+ jspPartitionScanner = new PHPPartitionScanner();
+ return jspPartitionScanner;
+ }
+
+ /**
+ * Sets up the Java document partitioner for the given document for the
+ * default partitioning.
+ *
+ * @param document
+ * the document to be set up
+ * @since 3.0
+ */
+ public void setupJavaDocumentPartitioner(IDocument document) {
+ setupJavaDocumentPartitioner(document,
+ IDocumentExtension3.DEFAULT_PARTITIONING);
+ }
+
+ /**
+ * Sets up the Java document partitioner for the given document for the
+ * given partitioning.
+ *
+ * @param document
+ * the document to be set up
+ * @param partitioning
+ * the document partitioning
+ * @since 3.0
+ */
+ public void setupJavaDocumentPartitioner(IDocument document,
+ String partitioning) {
+ IDocumentPartitioner partitioner = createDocumentPartitioner();
+ if (document instanceof IDocumentExtension3) {
+ IDocumentExtension3 extension3 = (IDocumentExtension3) document;
+ extension3.setDocumentPartitioner(partitioning, partitioner);
+ } else {
+ document.setDocumentPartitioner(partitioner);
+ }
+ partitioner.connect(document);
+ }
+
+ /**
+ * Returns this text tool's preference store.
+ *
+ * @return the preference store
+ * @since 3.0
+ */
+ protected IPreferenceStore getPreferenceStore() {
+ return fPreferenceStore;
+ }
+
+ /**
+ * Returns this text tool's core preference store.
+ *
+ * @return the core preference store
+ * @since 3.0
+ */
+ protected Preferences getCorePreferenceStore() {
+ return fCorePreferenceStore;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/PHPSourceViewerConfiguration.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/PHPSourceViewerConfiguration.java
new file mode 100644
index 0000000..3cba77d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/PHPSourceViewerConfiguration.java
@@ -0,0 +1,1146 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpdt.ui.text;
+
+import java.util.Vector;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+import net.sourceforge.phpdt.internal.ui.text.ContentAssistPreference;
+import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaAnnotationHover;
+import net.sourceforge.phpdt.internal.ui.text.JavaCompositeReconcilingStrategy;
+import net.sourceforge.phpdt.internal.ui.text.JavaElementProvider;
+import net.sourceforge.phpdt.internal.ui.text.JavaOutlineInformationControl;
+import net.sourceforge.phpdt.internal.ui.text.JavaPresentationReconciler;
+import net.sourceforge.phpdt.internal.ui.text.JavaReconciler;
+import net.sourceforge.phpdt.internal.ui.text.java.JavaFormattingStrategy;
+import net.sourceforge.phpdt.internal.ui.text.java.JavaStringAutoIndentStrategyDQ;
+import net.sourceforge.phpdt.internal.ui.text.java.JavaStringAutoIndentStrategySQ;
+import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaEditorTextHoverDescriptor;
+import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaEditorTextHoverProxy;
+import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaInformationProvider;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.JavaDocAutoIndentStrategy;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.PHPDocCodeScanner;
+import net.sourceforge.phpdt.internal.ui.text.phpdoc.PHPDocCompletionProcessor;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+//import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.php.HTMLCompletionProcessor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPAutoIndentStrategy;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPCodeScanner;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPCompletionProcessor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPDoubleClickSelector;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPPartitionScanner;
+import net.sourceforge.phpeclipse.ui.WebUI;
+//import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLConfiguration;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLPartitionScanner;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewerExtension2;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.formatter.ContentFormatter;
+import org.eclipse.jface.text.formatter.IContentFormatter;
+import org.eclipse.jface.text.formatter.IFormattingStrategy;
+import org.eclipse.jface.text.information.IInformationPresenter;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.InformationPresenter;
+import org.eclipse.jface.text.presentation.IPresentationDamager;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.IPresentationRepairer;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.DefaultPartitioner;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Configuration for an SourceViewer
which shows PHP code.
+ */
+public class PHPSourceViewerConfiguration extends SourceViewerConfiguration {
+ /**
+ * Preference key used to look up display tab width.
+ *
+ * @since 2.0
+ */
+ public final static String PREFERENCE_TAB_WIDTH = PreferenceConstants.EDITOR_TAB_WIDTH;
+
+ /**
+ * Preference key for inserting spaces rather than tabs.
+ *
+ * @since 2.0
+ */
+ public final static String SPACES_FOR_TABS = PreferenceConstants.EDITOR_SPACES_FOR_TABS;
+
+ // public static final String HTML_DEFAULT =
+ // IPHPPartitionScannerConstants.HTML;
+ // IDocument.DEFAULT_CONTENT_TYPE;
+ // private JavaTextTools fJavaTextTools;
+
+ private ITextEditor fTextEditor;
+
+ /**
+ * The document partitioning.
+ *
+ * @since 3.0
+ */
+ private String fDocumentPartitioning;
+
+ private ContentFormatter fFormatter;
+
+ /**
+ * Single token scanner.
+ */
+ static class SingleTokenScanner extends BufferedRuleBasedScanner {
+ public SingleTokenScanner(TextAttribute attribute) {
+ setDefaultReturnToken(new Token(attribute));
+ }
+ };
+
+ /**
+ * The document partitioning.
+ *
+ * @since 3.0
+ */
+ // private String fDocumentPartitioning;
+ /**
+ * The Java source code scanner
+ *
+ * @since 3.0
+ */
+ private AbstractJavaScanner fCodeScanner;
+
+ /**
+ * The Java multi-line comment scanner
+ *
+ * @since 3.0
+ */
+ private AbstractJavaScanner fMultilineCommentScanner;
+
+ /**
+ * The Java single-line comment scanner
+ *
+ * @since 3.0
+ */
+ private AbstractJavaScanner fSinglelineCommentScanner;
+
+ /**
+ * The PHP double quoted string scanner
+ */
+ private AbstractJavaScanner fStringDQScanner;
+
+ /**
+ * The PHP single quoted string scanner
+ */
+ private AbstractJavaScanner fStringSQScanner;
+
+ /**
+ * The Javadoc scanner
+ *
+ * @since 3.0
+ */
+ private AbstractJavaScanner fJavaDocScanner;
+
+ /**
+ * The preference store, can be read-only
+ *
+ * @since 3.0
+ */
+ private IPreferenceStore fPreferenceStore;
+
+ /**
+ * The color manager
+ *
+ * @since 3.0
+ */
+ private IColorManager fColorManager;
+
+ private XMLTextTools fXMLTextTools;
+
+ private XMLConfiguration xmlConfiguration;
+
+ /**
+ * Creates a new Java source viewer configuration for viewers in the given
+ * editor using the given preference store, the color manager and the
+ * specified document partitioning.
+ *
+ * Creates a Java source viewer configuration in the new setup without text
+ * tools. Clients are allowed to call
+ * {@link JavaSourceViewerConfiguration#handlePropertyChangeEvent(PropertyChangeEvent)}and
+ * disallowed to call
+ * {@link JavaSourceViewerConfiguration#getPreferenceStore()}on the
+ * resulting Java source viewer configuration.
+ *
+ *
+ * @param colorManager
+ * the color manager
+ * @param preferenceStore
+ * the preference store, can be read-only
+ * @param editor
+ * the editor in which the configured viewer(s) will reside
+ * @param partitioning
+ * the document partitioning for this configuration
+ * @since 3.0
+ */
+ public PHPSourceViewerConfiguration(IColorManager colorManager,
+ IPreferenceStore preferenceStore, ITextEditor editor,
+ String partitioning) {
+ fColorManager = colorManager;
+ fPreferenceStore = preferenceStore;
+ fTextEditor = editor;
+ fDocumentPartitioning = partitioning;
+ // fJavaTextTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
+ fXMLTextTools = new XMLTextTools(getPreferenceStore());
+ //XMLPlugin.getDefault().getXMLTextTools();
+ xmlConfiguration = new XMLConfiguration(fXMLTextTools);
+ fColorManager = colorManager;
+ fPreferenceStore = preferenceStore;
+ fTextEditor = editor;
+ fDocumentPartitioning = partitioning;
+
+ initializeScanners();
+ }
+
+ /**
+ * Creates a new Java source viewer configuration for viewers in the given
+ * editor using the given Java tools.
+ *
+ * @param tools
+ * the Java text tools to be used
+ * @param editor
+ * the editor in which the configured viewer(s) will reside
+ * @see JavaTextTools
+ * @deprecated As of 3.0, replaced by
+ * {@link JavaSourceViewerConfiguration#JavaSourceViewerConfiguration(IColorManager, IPreferenceStore, ITextEditor, String)}
+ */
+ // public PHPSourceViewerConfiguration(JavaTextTools tools, PHPEditor
+ // editor, String partitioning) {
+ // fJavaTextTools = tools;
+ // fColorManager = tools.getColorManager();
+ // fPreferenceStore = createPreferenceStore();
+ // fDocumentPartitioning = partitioning;
+ // fCodeScanner = (AbstractJavaScanner) fJavaTextTools.getCodeScanner();
+ // fMultilineCommentScanner = (AbstractJavaScanner)
+ // fJavaTextTools.getMultilineCommentScanner();
+ // fSinglelineCommentScanner = (AbstractJavaScanner)
+ // fJavaTextTools.getSinglelineCommentScanner();
+ // fStringDQScanner = (AbstractJavaScanner)
+ // fJavaTextTools.getStringScanner();
+ // fJavaDocScanner = (AbstractJavaScanner)
+ // fJavaTextTools.getJavaDocScanner();
+ // fTextEditor = editor;
+ // fXMLTextTools = XMLPlugin.getDefault().getXMLTextTools();
+ // xmlConfiguration = new XMLConfiguration(fXMLTextTools);
+ // }
+ /**
+ * Returns the color manager for this configuration.
+ *
+ * @return the color manager
+ */
+ protected IColorManager getColorManager() {
+ return fColorManager;
+ }
+
+ /**
+ * Initializes the scanners.
+ *
+ * @since 3.0
+ */
+ private void initializeScanners() {
+ // Assert.isTrue(isNewSetup());
+ fCodeScanner = new PHPCodeScanner(getColorManager(), fPreferenceStore);
+ fMultilineCommentScanner = new SingleTokenPHPScanner(getColorManager(),
+ fPreferenceStore, IPreferenceConstants.PHP_MULTILINE_COMMENT);
+ fSinglelineCommentScanner = new SingleTokenPHPScanner(
+ getColorManager(), fPreferenceStore,
+ IPreferenceConstants.PHP_SINGLELINE_COMMENT);
+ // fStringDQScanner = new SingleTokenPHPScanner(getColorManager(),
+ // fPreferenceStore, IPreferenceConstants.PHP_STRING_DQ);
+ fStringDQScanner = new PHPStringDQCodeScanner(getColorManager(),
+ fPreferenceStore);
+ fStringSQScanner = new SingleTokenPHPScanner(getColorManager(),
+ fPreferenceStore, IPreferenceConstants.PHP_STRING_SQ);
+ fJavaDocScanner = new PHPDocCodeScanner(getColorManager(),
+ fPreferenceStore);
+ }
+
+ /**
+ * Determines whether the preference change encoded by the given event
+ * changes the behavior of one of its contained components.
+ *
+ * @param event
+ * the event to be investigated
+ * @return true
if event causes a behavioral change
+ * @since 3.0
+ */
+ public boolean affectsTextPresentation(PropertyChangeEvent event) {
+ return fCodeScanner.affectsBehavior(event)
+ || fMultilineCommentScanner.affectsBehavior(event)
+ || fSinglelineCommentScanner.affectsBehavior(event)
+ || fStringDQScanner.affectsBehavior(event)
+ || fStringSQScanner.affectsBehavior(event)
+ || fJavaDocScanner.affectsBehavior(event);
+ }
+
+ /**
+ * Adapts the behavior of the contained components to the change encoded in
+ * the given event.
+ *
+ * Clients are not allowed to call this method if the old setup with text
+ * tools is in use.
+ *
+ *
+ * @param event
+ * the event to which to adapt
+ * @see JavaSourceViewerConfiguration#JavaSourceViewerConfiguration(IColorManager,
+ * IPreferenceStore, ITextEditor, String)
+ * @since 3.0
+ */
+ public void handlePropertyChangeEvent(PropertyChangeEvent event) {
+ // Assert.isTrue(isNewSetup());
+ if (fCodeScanner.affectsBehavior(event))
+ fCodeScanner.adaptToPreferenceChange(event);
+ if (fMultilineCommentScanner.affectsBehavior(event))
+ fMultilineCommentScanner.adaptToPreferenceChange(event);
+ if (fSinglelineCommentScanner.affectsBehavior(event))
+ fSinglelineCommentScanner.adaptToPreferenceChange(event);
+ if (fStringDQScanner.affectsBehavior(event))
+ fStringDQScanner.adaptToPreferenceChange(event);
+ if (fStringSQScanner.affectsBehavior(event))
+ fStringSQScanner.adaptToPreferenceChange(event);
+ if (fJavaDocScanner.affectsBehavior(event))
+ fJavaDocScanner.adaptToPreferenceChange(event);
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getContentFormatter(ISourceViewer)
+ */
+ public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
+ // if (fFormatter == null) {
+ // fFormatter = new ContentFormatter();
+ // fFormattingStrategy = new HTMLFormattingStrategy(this,
+ // sourceViewer);
+ // fFormatter.setFormattingStrategy(fFormattingStrategy, HTML_DEFAULT);
+ // fFormatter.enablePartitionAwareFormatting(false);
+ // fFormatter.setPartitionManagingPositionCategories(getConfiguredContentTypes(null));
+ // }
+ // return fFormatter;
+ if (fFormatter == null) {
+ // ContentFormatter
+ fFormatter = new ContentFormatter();
+ IFormattingStrategy strategy = new JavaFormattingStrategy(
+ sourceViewer);
+ fFormatter.setFormattingStrategy(strategy,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ fFormatter.enablePartitionAwareFormatting(false);
+ fFormatter
+ .setPartitionManagingPositionCategories(getPartitionManagingPositionCategories());
+ }
+ return fFormatter;
+ }
+
+ /**
+ * Returns the names of the document position categories used by the
+ * document partitioners created by this object to manage their partition
+ * information. If the partitioners don't use document position categories,
+ * the returned result is null
.
+ *
+ * @return the partition managing position categories or null
+ * if there is none
+ */
+ public String[] getPartitionManagingPositionCategories() {
+ return new String[] { DefaultPartitioner.CONTENT_TYPES_CATEGORY };
+ }
+
+ // /**
+ // * Returns the names of the document position categories used by the
+ // document
+ // * partitioners created by this object to manage their partition
+ // information.
+ // * If the partitioners don't use document position categories, the
+ // returned
+ // * result is null
.
+ // *
+ // * @return the partition managing position categories or
+ // null
+ // * if there is none
+ // */
+ // private String[] getPartitionManagingPositionCategories() {
+ // return new String[] { DefaultPartitioner.CONTENT_TYPES_CATEGORY };
+ // }
+ public ITextEditor getEditor() {
+ return fTextEditor;
+ }
+
+ /**
+ * Returns the preference store used by this configuration to initialize the
+ * individual bits and pieces.
+ *
+ * @return the preference store used to initialize this configuration
+ *
+ * @since 2.0
+ */
+ protected IPreferenceStore getPreferenceStore() {
+ return WebUI.getDefault().getPreferenceStore();
+ }
+
+ // /* (non-Javadoc)
+ // * Method declared on SourceViewerConfiguration
+ // */
+ // public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+ // return new PHPAnnotationHover();
+ // }
+ /*
+ * @see SourceViewerConfiguration#getAnnotationHover(ISourceViewer)
+ */
+ public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+ return new JavaAnnotationHover(JavaAnnotationHover.VERTICAL_RULER_HOVER);
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getOverviewRulerAnnotationHover(ISourceViewer)
+ * @since 3.0
+ */
+ public IAnnotationHover getOverviewRulerAnnotationHover(
+ ISourceViewer sourceViewer) {
+ return new JavaAnnotationHover(JavaAnnotationHover.OVERVIEW_RULER_HOVER);
+ }
+
+ public IAutoEditStrategy[] getAutoEditStrategies(
+ ISourceViewer sourceViewer, String contentType) {
+ IAutoEditStrategy strategy = new DefaultIndentLineAutoEditStrategy();
+ if (IPHPPartitions.PHP_PHPDOC_COMMENT.equals(contentType)
+ || IPHPPartitions.PHP_MULTILINE_COMMENT.equals(contentType))
+ strategy = new JavaDocAutoIndentStrategy(
+ getConfiguredDocumentPartitioning(sourceViewer));
+ else if (IPHPPartitions.PHP_STRING_DQ.equals(contentType))
+ strategy = new JavaStringAutoIndentStrategyDQ(
+ getConfiguredDocumentPartitioning(sourceViewer));
+ else if (IPHPPartitions.PHP_STRING_SQ.equals(contentType))
+ strategy = new JavaStringAutoIndentStrategySQ(
+ getConfiguredDocumentPartitioning(sourceViewer));
+ else
+ strategy = (PHPDocumentPartitioner.PHP_TEMPLATE_DATA
+ .equals(contentType)
+ || PHPDocumentPartitioner.PHP_SCRIPT_CODE
+ .equals(contentType)
+ || IDocument.DEFAULT_CONTENT_TYPE.equals(contentType)
+ || IPHPPartitions.PHP_PARTITIONING.equals(contentType)
+ || PHPPartitionScanner.PHP_SCRIPTING_AREA
+ .equals(contentType) ? new PHPAutoIndentStrategy()
+ : new DefaultIndentLineAutoEditStrategy());
+ IAutoEditStrategy[] result = new IAutoEditStrategy[1];
+ result[0] = strategy;
+ return result;
+ }
+
+ /**
+ * Returns the PHP source code scanner for this configuration.
+ *
+ * @return the PHP source code scanner
+ */
+ protected RuleBasedScanner getCodeScanner() {
+ return fCodeScanner; // fJavaTextTools.getCodeScanner();
+ }
+
+ /**
+ * Returns the Java multi-line comment scanner for this configuration.
+ *
+ * @return the Java multi-line comment scanner
+ * @since 2.0
+ */
+ protected RuleBasedScanner getMultilineCommentScanner() {
+ return fMultilineCommentScanner;
+ }
+
+ /**
+ * Returns the Java single-line comment scanner for this configuration.
+ *
+ * @return the Java single-line comment scanner
+ * @since 2.0
+ */
+ protected RuleBasedScanner getSinglelineCommentScanner() {
+ return fSinglelineCommentScanner;
+ }
+
+ /**
+ * Returns the PHP double quoted string scanner for this configuration.
+ *
+ * @return the PHP double quoted string scanner
+ */
+ protected RuleBasedScanner getStringDQScanner() {
+ return fStringDQScanner;
+ }
+
+ /**
+ * Returns the PHP single quoted string scanner for this configuration.
+ *
+ * @return the PHP single quoted string scanner
+ */
+ protected RuleBasedScanner getStringSQScanner() {
+ return fStringSQScanner;
+ }
+
+ /**
+ * Returns the HTML source code scanner for this configuration.
+ *
+ * @return the HTML source code scanner
+ */
+ // protected RuleBasedScanner getHTMLScanner() {
+ // return fJavaTextTools.getHTMLScanner();
+ // }
+ /**
+ * Returns the Smarty source code scanner for this configuration.
+ *
+ * @return the Smarty source code scanner
+ */
+ // protected RuleBasedScanner getSmartyScanner() {
+ // return fJavaTextTools.getSmartyScanner();
+ // }
+ /*
+ * @see SourceViewerConfiguration#getReconciler(ISourceViewer)
+ */
+ /*
+ * @see SourceViewerConfiguration#getReconciler(ISourceViewer)
+ */
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+
+ final ITextEditor editor = getEditor();
+ if (editor != null && editor.isEditable()) {
+
+ JavaCompositeReconcilingStrategy strategy = new JavaCompositeReconcilingStrategy(
+ editor, getConfiguredDocumentPartitioning(sourceViewer));
+ JavaReconciler reconciler = new JavaReconciler(editor, strategy,
+ false);
+ reconciler.setIsIncrementalReconciler(false);
+ reconciler.setProgressMonitor(new NullProgressMonitor());
+ reconciler.setDelay(500);
+
+ return reconciler;
+ }
+ return null;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getConfiguredTextHoverStateMasks(ISourceViewer,
+ * String)
+ * @since 2.1
+ */
+ public int[] getConfiguredTextHoverStateMasks(ISourceViewer sourceViewer,
+ String contentType) {
+ JavaEditorTextHoverDescriptor[] hoverDescs = WebUI
+ .getDefault().getJavaEditorTextHoverDescriptors();
+ int stateMasks[] = new int[hoverDescs.length];
+ int stateMasksLength = 0;
+ for (int i = 0; i < hoverDescs.length; i++) {
+ if (hoverDescs[i].isEnabled()) {
+ int j = 0;
+ int stateMask = hoverDescs[i].getStateMask();
+ while (j < stateMasksLength) {
+ if (stateMasks[j] == stateMask)
+ break;
+ j++;
+ }
+ if (j == stateMasksLength)
+ stateMasks[stateMasksLength++] = stateMask;
+ }
+ }
+ if (stateMasksLength == hoverDescs.length)
+ return stateMasks;
+ int[] shortenedStateMasks = new int[stateMasksLength];
+ System.arraycopy(stateMasks, 0, shortenedStateMasks, 0,
+ stateMasksLength);
+ return shortenedStateMasks;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getTextHover(ISourceViewer, String, int)
+ * @since 2.1
+ */
+ public ITextHover getTextHover(ISourceViewer sourceViewer,
+ String contentType, int stateMask) {
+ JavaEditorTextHoverDescriptor[] hoverDescs = WebUI
+ .getDefault().getJavaEditorTextHoverDescriptors();
+ int i = 0;
+ while (i < hoverDescs.length) {
+ if (hoverDescs[i].isEnabled()
+ && hoverDescs[i].getStateMask() == stateMask)
+ return new JavaEditorTextHoverProxy(hoverDescs[i], getEditor());
+ i++;
+ }
+ return null;
+ // if (fEditor != null) {
+ // IEditorInput editorInput = fEditor.getEditorInput();
+ // if (editorInput instanceof IFileEditorInput) {
+ // try {
+ // IFile f = ((IFileEditorInput) editorInput).getFile();
+ // return new PHPTextHover(f.getProject());
+ // } catch (NullPointerException e) {
+ // // this exception occurs, if getTextHover is called by
+ // // preference pages !
+ // }
+ // }
+ // }
+ // return new PHPTextHover(null);
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getTextHover(ISourceViewer, String)
+ */
+ public ITextHover getTextHover(ISourceViewer sourceViewer,
+ String contentType) {
+ return getTextHover(sourceViewer, contentType,
+ ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
+ }
+
+ /**
+ * Returns the SmartyDoc source code scanner for this configuration.
+ *
+ * @return the SmartyDoc source code scanner
+ */
+ // protected RuleBasedScanner getSmartyDocScanner() {
+ // return fJavaTextTools.getSmartyDocScanner();
+ // }
+ /**
+ * Returns the PHPDoc source code scanner for this configuration.
+ *
+ * @return the PHPDoc source code scanner
+ */
+ protected RuleBasedScanner getPHPDocScanner() {
+ return fJavaDocScanner; // fJavaTextTools.getJavaDocScanner();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SourceViewerConfiguration
+ */
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ return new String[] { IDocument.DEFAULT_CONTENT_TYPE,
+ PHPPartitionScanner.PHP_SCRIPTING_AREA,
+
+ IPHPPartitions.HTML, IPHPPartitions.HTML_MULTILINE_COMMENT,
+ IPHPPartitions.PHP_PARTITIONING,
+ IPHPPartitions.PHP_SINGLELINE_COMMENT,
+ IPHPPartitions.PHP_MULTILINE_COMMENT,
+ IPHPPartitions.PHP_PHPDOC_COMMENT,
+ IPHPPartitions.PHP_STRING_DQ, IPHPPartitions.PHP_STRING_SQ,
+ IPHPPartitions.PHP_STRING_HEREDOC, IPHPPartitions.CSS,
+ IPHPPartitions.CSS_MULTILINE_COMMENT,
+ IPHPPartitions.JAVASCRIPT, IPHPPartitions.JS_MULTILINE_COMMENT,
+ IPHPPartitions.SMARTY, IPHPPartitions.SMARTY_MULTILINE_COMMENT,
+
+ XMLPartitionScanner.XML_PI, XMLPartitionScanner.XML_COMMENT,
+ XMLPartitionScanner.XML_DECL, XMLPartitionScanner.XML_TAG,
+ XMLPartitionScanner.XML_ATTRIBUTE,
+ XMLPartitionScanner.XML_CDATA,
+
+ XMLPartitionScanner.DTD_INTERNAL,
+ XMLPartitionScanner.DTD_INTERNAL_PI,
+ XMLPartitionScanner.DTD_INTERNAL_COMMENT,
+ XMLPartitionScanner.DTD_INTERNAL_DECL,
+
+ PHPDocumentPartitioner.PHP_TEMPLATE_DATA,
+ PHPDocumentPartitioner.PHP_SCRIPT_CODE };
+ }
+
+ public String[] getConfiguredHTMLContentTypes() {
+ return new String[] { XMLPartitionScanner.XML_PI,
+ XMLPartitionScanner.XML_COMMENT, XMLPartitionScanner.XML_DECL,
+ XMLPartitionScanner.XML_TAG, XMLPartitionScanner.XML_ATTRIBUTE,
+ XMLPartitionScanner.XML_CDATA,
+
+ XMLPartitionScanner.DTD_INTERNAL,
+ XMLPartitionScanner.DTD_INTERNAL_PI,
+ XMLPartitionScanner.DTD_INTERNAL_COMMENT,
+ XMLPartitionScanner.DTD_INTERNAL_DECL, };
+ }
+
+ public String[] getConfiguredPHPContentTypes() {
+ return new String[] { IDocument.DEFAULT_CONTENT_TYPE,
+ IPHPPartitions.PHP_PARTITIONING,
+ IPHPPartitions.PHP_SINGLELINE_COMMENT,
+ IPHPPartitions.PHP_MULTILINE_COMMENT,
+ IPHPPartitions.PHP_PHPDOC_COMMENT,
+ IPHPPartitions.PHP_STRING_DQ, IPHPPartitions.PHP_STRING_SQ,
+ IPHPPartitions.PHP_STRING_HEREDOC, IPHPPartitions.CSS,
+ IPHPPartitions.CSS_MULTILINE_COMMENT,
+ IPHPPartitions.JAVASCRIPT, IPHPPartitions.JS_MULTILINE_COMMENT,
+ IPHPPartitions.SMARTY, IPHPPartitions.SMARTY_MULTILINE_COMMENT, };
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredDocumentPartitioning(org.eclipse.jface.text.source.ISourceViewer)
+ * @since 3.0
+ */
+ public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) {
+ if (fDocumentPartitioning != null)
+ return fDocumentPartitioning;
+ return super.getConfiguredDocumentPartitioning(sourceViewer);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SourceViewerConfiguration
+ */
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+ ContentAssistant assistant = new ContentAssistant();
+ IContentAssistProcessor processor = new HTMLCompletionProcessor(
+ getEditor());
+ assistant
+ .setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+ assistant.setContentAssistProcessor(processor, IPHPPartitions.HTML);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.HTML_MULTILINE_COMMENT);
+
+ assistant.setContentAssistProcessor(processor, IPHPPartitions.CSS);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.CSS_MULTILINE_COMMENT);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.JAVASCRIPT);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.JS_MULTILINE_COMMENT);
+ // TODO define special smarty partition content assist
+ assistant.setContentAssistProcessor(processor, IPHPPartitions.SMARTY);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.SMARTY_MULTILINE_COMMENT);
+
+ assistant.setContentAssistProcessor(processor,
+ PHPDocumentPartitioner.PHP_TEMPLATE_DATA);
+ String[] htmlTypes = getConfiguredHTMLContentTypes();
+ for (int i = 0; i < htmlTypes.length; i++) {
+ assistant.setContentAssistProcessor(processor, htmlTypes[i]);
+ }
+ processor = new PHPCompletionProcessor(getEditor());
+
+ assistant.setContentAssistProcessor(processor,
+ PHPDocumentPartitioner.PHP_SCRIPT_CODE);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.PHP_PARTITIONING);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.PHP_STRING_DQ);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.PHP_STRING_SQ);
+ assistant.setContentAssistProcessor(processor,
+ IPHPPartitions.PHP_STRING_HEREDOC);
+
+ assistant.setContentAssistProcessor(new PHPDocCompletionProcessor(
+ getEditor()), IPHPPartitions.PHP_PHPDOC_COMMENT);
+ // assistant.enableAutoActivation(true);
+ // assistant.setAutoActivationDelay(500);
+ // assistant.setProposalPopupOrientation(ContentAssistant.PROPOSAL_OVERLAY);
+ // ContentAssistPreference.configure(assistant, getPreferenceStore());
+ // assistant.setContextInformationPopupOrientation(
+ // ContentAssistant.CONTEXT_INFO_ABOVE);
+ // assistant.setContextInformationPopupBackground(
+ // PHPEditorEnvironment.getPHPColorProvider().getColor(
+ // new RGB(150, 150, 0)));
+ ContentAssistPreference.configure(assistant, getPreferenceStore());
+ assistant
+ .setContextInformationPopupOrientation(ContentAssistant.CONTEXT_INFO_ABOVE);
+ assistant
+ .setInformationControlCreator(getInformationControlCreator(sourceViewer));
+ return assistant;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SourceViewerConfiguration
+ */
+ // public String getDefaultPrefix(ISourceViewer sourceViewer, String
+ // contentType) {
+ // return (PHPPartitionScanner.PHP.equals(contentType) ? "//" : null);
+ // //$NON-NLS-1$
+ // // return (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType) ? "//" :
+ // null); //$NON-NLS-1$
+ // }
+ /*
+ * @see SourceViewerConfiguration#getDefaultPrefix(ISourceViewer, String)
+ * @since 2.0
+ */
+ public String[] getDefaultPrefixes(ISourceViewer sourceViewer,
+ String contentType) {
+ return new String[] { "//", "" }; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SourceViewerConfiguration
+ */
+ public ITextDoubleClickStrategy getDoubleClickStrategy(
+ ISourceViewer sourceViewer, String contentType) {
+ return new PHPDoubleClickSelector();
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getIndentPrefixes(ISourceViewer, String)
+ */
+ public String[] getIndentPrefixes(ISourceViewer sourceViewer,
+ String contentType) {
+ Vector vector = new Vector();
+ // prefix[0] is either '\t' or ' ' x tabWidth, depending on useSpaces
+ final IPreferenceStore preferences = WebUI.getDefault()
+ .getPreferenceStore();
+ int tabWidth = preferences.getInt(JavaCore.FORMATTER_TAB_SIZE);
+ boolean useSpaces = getPreferenceStore().getBoolean(SPACES_FOR_TABS);
+ for (int i = 0; i <= tabWidth; i++) {
+ StringBuffer prefix = new StringBuffer();
+ if (useSpaces) {
+ for (int j = 0; j + i < tabWidth; j++)
+ prefix.append(' ');
+ if (i != 0)
+ prefix.append('\t');
+ } else {
+ for (int j = 0; j < i; j++)
+ prefix.append(' ');
+ if (i != tabWidth)
+ prefix.append('\t');
+ }
+ vector.add(prefix.toString());
+ }
+ vector.add(""); //$NON-NLS-1$
+ return (String[]) vector.toArray(new String[vector.size()]);
+ }
+
+ /**
+ * @return true
iff the new setup without text tools is in
+ * use.
+ *
+ * @since 3.0
+ */
+ // private boolean isNewSetup() {
+ // return fJavaTextTools == null;
+ // }
+ /**
+ * Creates and returns a preference store which combines the preference
+ * stores from the text tools and which is read-only.
+ *
+ * @return the read-only preference store
+ * @since 3.0
+ */
+ // private IPreferenceStore createPreferenceStore() {
+ // Assert.isTrue(!isNewSetup());
+ // IPreferenceStore generalTextStore = EditorsUI.getPreferenceStore();
+ // if (fJavaTextTools.getCorePreferenceStore() == null)
+ // return new ChainedPreferenceStore(new IPreferenceStore[] {
+ // fJavaTextTools.getPreferenceStore(), generalTextStore });
+ //
+ // return new ChainedPreferenceStore(new IPreferenceStore[] {
+ // fJavaTextTools.getPreferenceStore(),
+ // new PreferencesAdapter(fJavaTextTools.getCorePreferenceStore()),
+ // generalTextStore });
+ // }
+ /*
+ * (non-Javadoc) Method declared on SourceViewerConfiguration
+ */
+ public IPresentationReconciler getPresentationReconciler(
+ ISourceViewer sourceViewer) {
+ // PHPColorProvider provider =
+ // PHPEditorEnvironment.getPHPColorProvider();
+ // JavaColorManager provider =
+ // PHPEditorEnvironment.getPHPColorProvider();
+ PresentationReconciler phpReconciler = new JavaPresentationReconciler();
+ phpReconciler
+ .setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+ // DefaultDamagerRepairer dr = new
+ // DefaultDamagerRepairer(getHTMLScanner());
+ // reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ // reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ // dr = new DefaultDamagerRepairer(getHTMLScanner());
+ // reconciler.setDamager(dr, IPHPPartitions.HTML);
+ // reconciler.setRepairer(dr, IPHPPartitions.HTML);
+ // dr = new DefaultDamagerRepairer(getHTMLScanner());
+ // reconciler.setDamager(dr, IPHPPartitions.CSS);
+ // reconciler.setRepairer(dr, IPHPPartitions.CSS);
+ // dr = new DefaultDamagerRepairer(getHTMLScanner());
+ // reconciler.setDamager(dr, IPHPPartitions.CSS_MULTILINE_COMMENT);
+ // reconciler.setRepairer(dr, IPHPPartitions.CSS_MULTILINE_COMMENT);
+ // dr = new DefaultDamagerRepairer(getHTMLScanner());
+ // reconciler.setDamager(dr, IPHPPartitions.JAVASCRIPT);
+ // reconciler.setRepairer(dr, IPHPPartitions.JAVASCRIPT);
+ // dr = new DefaultDamagerRepairer(getHTMLScanner());
+ // reconciler.setDamager(dr, IPHPPartitions.JS_MULTILINE_COMMENT);
+ // reconciler.setRepairer(dr, IPHPPartitions.JS_MULTILINE_COMMENT);
+ // DefaultDamagerRepairer phpDR = new
+ // DefaultDamagerRepairer(getSmartyScanner());
+ // phpReconciler.setDamager(phpDR, IPHPPartitions.SMARTY);
+ // phpReconciler.setRepairer(phpDR, IPHPPartitions.SMARTY);
+ // phpDR = new DefaultDamagerRepairer(getSmartyDocScanner());
+ // phpReconciler.setDamager(phpDR,
+ // IPHPPartitions.SMARTY_MULTILINE_COMMENT);
+ // phpReconciler.setRepairer(phpDR,
+ // IPHPPartitions.SMARTY_MULTILINE_COMMENT);
+ // dr = new DefaultDamagerRepairer(new SingleTokenScanner(new
+ // TextAttribute(fJavaTextTools.getColorManager().getColor(
+ // PHPColorProvider.MULTI_LINE_COMMENT))));
+ // reconciler.setDamager(dr, IPHPPartitions.HTML_MULTILINE_COMMENT);
+ // reconciler.setRepairer(dr, IPHPPartitions.HTML_MULTILINE_COMMENT);
+
+ DefaultDamagerRepairer phpDR = new DefaultDamagerRepairer(
+ getCodeScanner());
+ phpReconciler.setDamager(phpDR, IDocument.DEFAULT_CONTENT_TYPE);
+ phpReconciler.setRepairer(phpDR, IDocument.DEFAULT_CONTENT_TYPE);
+
+ phpDR = new DefaultDamagerRepairer(getCodeScanner());
+ phpReconciler.setDamager(phpDR, IPHPPartitions.PHP_PARTITIONING);
+ phpReconciler.setRepairer(phpDR, IPHPPartitions.PHP_PARTITIONING);
+
+ phpDR = new DefaultDamagerRepairer(getPHPDocScanner());
+ phpReconciler.setDamager(phpDR, IPHPPartitions.PHP_PHPDOC_COMMENT);
+ phpReconciler.setRepairer(phpDR, IPHPPartitions.PHP_PHPDOC_COMMENT);
+
+ phpDR = new DefaultDamagerRepairer(getStringDQScanner());
+ phpReconciler.setDamager(phpDR, IPHPPartitions.PHP_STRING_DQ);
+ phpReconciler.setRepairer(phpDR, IPHPPartitions.PHP_STRING_DQ);
+ phpDR = new DefaultDamagerRepairer(getStringSQScanner());
+ phpReconciler.setDamager(phpDR, IPHPPartitions.PHP_STRING_SQ);
+ phpReconciler.setRepairer(phpDR, IPHPPartitions.PHP_STRING_SQ);
+ phpDR = new DefaultDamagerRepairer(getStringDQScanner());
+ phpReconciler.setDamager(phpDR, IPHPPartitions.PHP_STRING_HEREDOC);
+ phpReconciler.setRepairer(phpDR, IPHPPartitions.PHP_STRING_HEREDOC);
+ phpDR = new DefaultDamagerRepairer(getSinglelineCommentScanner());
+ phpReconciler.setDamager(phpDR, IPHPPartitions.PHP_SINGLELINE_COMMENT);
+ phpReconciler.setRepairer(phpDR, IPHPPartitions.PHP_SINGLELINE_COMMENT);
+ phpDR = new DefaultDamagerRepairer(getMultilineCommentScanner());
+ phpReconciler.setDamager(phpDR, IPHPPartitions.PHP_MULTILINE_COMMENT);
+ phpReconciler.setRepairer(phpDR, IPHPPartitions.PHP_MULTILINE_COMMENT);
+
+ PresentationReconciler reconciler = new PresentationReconciler();
+ reconciler
+ .setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+ //
+ // JavaTextTools jspTextTools =
+ // PHPeclipsePlugin.getDefault().getJavaTextTools();
+ DefaultDamagerRepairer dr = new DefaultDamagerRepairer(
+ getPHPDocScanner());// jspTextTools.getJSPTextScanner());
+ reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+ // dr = new DefaultDamagerRepairer(new SingleTokenScanner(new
+ // TextAttribute(fJavaTextTools.getColorManager().getColor(
+ // PHPColorProvider.PHPDOC_TAG))));//jspTextTools.getJSPBracketScanner());
+ // reconciler.setDamager(dr, JSPScriptScanner.JSP_BRACKET);
+ // reconciler.setRepairer(dr, JSPScriptScanner.JSP_BRACKET);
+
+ // xml partitions
+ configureEmbeddedPresentationReconciler(reconciler, xmlConfiguration
+ .getPresentationReconciler(sourceViewer), xmlConfiguration
+ .getConfiguredContentTypes(sourceViewer),
+ PHPDocumentPartitioner.PHP_TEMPLATE_DATA);
+
+ // java partitions
+ configureEmbeddedPresentationReconciler(reconciler, phpReconciler,
+ getConfiguredPHPContentTypes(),
+ PHPDocumentPartitioner.PHP_SCRIPT_CODE);
+
+ return reconciler;
+ }
+
+ private void configureEmbeddedPresentationReconciler(
+ PresentationReconciler reconciler,
+ IPresentationReconciler embedded, String[] types, String defaultType) {
+ for (int i = 0; i < types.length; i++) {
+ String type = types[i];
+
+ IPresentationDamager damager = embedded.getDamager(type);
+ IPresentationRepairer repairer = embedded.getRepairer(type);
+
+ if (type == IDocument.DEFAULT_CONTENT_TYPE) {
+ type = defaultType;
+ }
+
+ reconciler.setDamager(damager, type);
+ reconciler.setRepairer(repairer, type);
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SourceViewerConfiguration
+ */
+ public int getTabWidth(ISourceViewer sourceViewer) {
+ return getPreferenceStore().getInt(PREFERENCE_TAB_WIDTH);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SourceViewerConfiguration
+ */
+ // public ITextHover getTextHover(ISourceViewer sourceViewer, String
+ // contentType) {
+ // if (fEditor != null) {
+ // IEditorInput editorInput = fEditor.getEditorInput();
+ // if (editorInput instanceof IFileEditorInput) {
+ // try {
+ // IFile f = ((IFileEditorInput) editorInput).getFile();
+ // return new PHPTextHover(f.getProject());
+ // } catch (NullPointerException e) {
+ // // this exception occurs, if getTextHover is called by preference pages
+ // !
+ // }
+ // }
+ // }
+ // return new PHPTextHover(null);
+ // }
+ /*
+ * @see SourceViewerConfiguration#getInformationControlCreator(ISourceViewer)
+ * @since 2.0
+ */
+ public IInformationControlCreator getInformationControlCreator(
+ ISourceViewer sourceViewer) {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ return new DefaultInformationControl(parent, SWT.NONE,
+ new HTMLTextPresenter(true));
+ // return new HoverBrowserControl(parent);
+ }
+ };
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getInformationPresenter(ISourceViewer)
+ * @since 2.0
+ */
+ public IInformationPresenter getInformationPresenter(
+ ISourceViewer sourceViewer) {
+ InformationPresenter presenter = new InformationPresenter(
+ getInformationPresenterControlCreator(sourceViewer));
+ presenter
+ .setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+ IInformationProvider provider = new JavaInformationProvider(getEditor());
+ presenter.setInformationProvider(provider,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ presenter.setInformationProvider(provider,
+ IPHPPartitions.PHP_PHPDOC_COMMENT);
+ // presenter.setInformationProvider(provider,
+ // IPHPPartitions.JAVA_CHARACTER);
+ presenter.setSizeConstraints(60, 10, true, true);
+ return presenter;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getInformationPresenter(ISourceViewer)
+ * @since 2.0
+ */
+ // public IInformationPresenter getInformationPresenter(ISourceViewer
+ // sourceViewer) {
+ // InformationPresenter presenter= new
+ // InformationPresenter(getInformationPresenterControlCreator(sourceViewer));
+ // IInformationProvider provider= new JavaInformationProvider(getEditor());
+ // presenter.setInformationProvider(provider,
+ // IDocument.DEFAULT_CONTENT_TYPE);
+ // presenter.setInformationProvider(provider, IJavaPartitions.JAVA_DOC);
+ // presenter.setSizeConstraints(60, 10, true, true);
+ // return presenter;
+ // }
+ /**
+ * Returns the information presenter control creator. The creator is a
+ * factory creating the presenter controls for the given source viewer. This
+ * implementation always returns a creator for
+ * DefaultInformationControl
instances.
+ *
+ * @param sourceViewer
+ * the source viewer to be configured by this configuration
+ * @return an information control creator
+ * @since 2.1
+ */
+ private IInformationControlCreator getInformationPresenterControlCreator(
+ ISourceViewer sourceViewer) {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ int shellStyle = SWT.RESIZE;
+ int style = SWT.V_SCROLL | SWT.H_SCROLL;
+ return new DefaultInformationControl(parent, shellStyle, style,
+ new HTMLTextPresenter(false));
+ // return new HoverBrowserControl(parent);
+ }
+ };
+ }
+
+ /**
+ * Returns the outline presenter control creator. The creator is a factory
+ * creating outline presenter controls for the given source viewer. This
+ * implementation always returns a creator for
+ * JavaOutlineInformationControl
instances.
+ *
+ * @param sourceViewer
+ * the source viewer to be configured by this configuration
+ * @return an information control creator
+ * @since 2.1
+ */
+ private IInformationControlCreator getOutlinePresenterControlCreator(
+ ISourceViewer sourceViewer) {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ int shellStyle = SWT.RESIZE;
+ int treeStyle = SWT.V_SCROLL | SWT.H_SCROLL;
+ return new JavaOutlineInformationControl(parent, shellStyle,
+ treeStyle);
+ }
+ };
+ }
+
+ /**
+ * Returns the outline presenter which will determine and shown information
+ * requested for the current cursor position.
+ *
+ * @param sourceViewer
+ * the source viewer to be configured by this configuration
+ * @param doCodeResolve
+ * a boolean which specifies whether code resolve should be used
+ * to compute the Java element
+ * @return an information presenter
+ * @since 2.1
+ */
+ public IInformationPresenter getOutlinePresenter(
+ ISourceViewer sourceViewer, boolean doCodeResolve) {
+ InformationPresenter presenter = new InformationPresenter(
+ getOutlinePresenterControlCreator(sourceViewer));
+ presenter.setAnchor(InformationPresenter.ANCHOR_GLOBAL);
+ IInformationProvider provider = new JavaElementProvider(getEditor(),
+ doCodeResolve);
+ presenter.setInformationProvider(provider,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ presenter.setInformationProvider(provider,
+ PHPDocumentPartitioner.PHP_SCRIPT_CODE);
+ presenter.setInformationProvider(provider,
+ IPHPPartitions.PHP_PARTITIONING);
+ presenter.setInformationProvider(provider,
+ IPHPPartitions.PHP_PHPDOC_COMMENT);
+ presenter.setInformationProvider(provider,
+ IPHPPartitions.SMARTY_MULTILINE_COMMENT);
+ presenter.setInformationProvider(provider, IPHPPartitions.HTML);
+ presenter.setInformationProvider(provider,
+ IPHPPartitions.HTML_MULTILINE_COMMENT);
+ presenter.setSizeConstraints(40, 20, true, false);
+ return presenter;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/PHPStringDQCodeScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/PHPStringDQCodeScanner.java
new file mode 100644
index 0000000..6203ece
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/PHPStringDQCodeScanner.java
@@ -0,0 +1,125 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpdt.ui.text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPVariableDetector;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WordRule;
+
+/**
+ * A rule based PHPDoc scanner.
+ */
+public final class PHPStringDQCodeScanner extends AbstractJavaScanner {
+
+ private static String[] fgTokenProperties = {
+ IPreferenceConstants.PHP_STRING_DQ,
+ IPreferenceConstants.PHP_VARIABLE,
+ IPreferenceConstants.PHP_VARIABLE_DOLLAR };
+
+ private class PHPWordRule extends WordRule {
+ private StringBuffer fBuffer = new StringBuffer();
+
+ public PHPWordRule(IWordDetector detector) {
+ super(detector, Token.UNDEFINED);
+ }
+
+ public PHPWordRule(IWordDetector detector, IToken defaultToken) {
+ super(detector, defaultToken);
+ }
+
+ public IToken evaluate(ICharacterScanner scanner) {
+ int c = scanner.read();
+ boolean isUnderscore = false;
+ if (fDetector.isWordStart((char) c)) {
+ if (fColumn == UNDEFINED
+ || (fColumn == scanner.getColumn() - 1)) {
+
+ fBuffer.setLength(0);
+ fBuffer.append((char) c);
+ c = scanner.read();
+ if (c == '_') {
+ isUnderscore = true;
+ }
+ while (c != ICharacterScanner.EOF
+ && fDetector.isWordPart((char) c)) {
+ fBuffer.append((char) c);
+ c = scanner.read();
+ // hack for coloring object elements with variable color
+ // instead of string color
+ if (c == '-') {
+ int c2 = scanner.read();
+ if (c2 == '>') {
+ fBuffer.append(c);
+ fBuffer.append(c2);
+ c = scanner.read();
+ } else {
+ scanner.unread();
+ }
+ }
+ // hack end
+ }
+ scanner.unread();
+ if (isUnderscore) {
+ return getToken(IPreferenceConstants.PHP_VARIABLE_DOLLAR);
+ }
+ return getToken(IPreferenceConstants.PHP_VARIABLE);
+ }
+ }
+
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+ }
+
+ public PHPStringDQCodeScanner(IColorManager manager, IPreferenceStore store) {
+ super(manager, store);
+ initialize();
+ }
+
+ public IDocument getDocument() {
+ return fDocument;
+ }
+
+ /*
+ * @see AbstractJavaScanner#getTokenProperties()
+ */
+ protected String[] getTokenProperties() {
+ return fgTokenProperties;
+ }
+
+ /*
+ * @see AbstractJavaScanner#createRules()
+ */
+ protected List createRules() {
+
+ List list = new ArrayList();
+
+ // Add rule for tags.
+ Token token = getToken(IPreferenceConstants.PHP_STRING_DQ);
+ PHPWordRule wordRule = new PHPWordRule(new PHPVariableDetector(), token);
+
+ list.add(wordRule);
+
+ setDefaultReturnToken(getToken(IPreferenceConstants.PHP_STRING_DQ));
+ return list;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/SingleTokenPHPScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/SingleTokenPHPScanner.java
new file mode 100644
index 0000000..81bdd4e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/SingleTokenPHPScanner.java
@@ -0,0 +1,42 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+package net.sourceforge.phpdt.ui.text;
+
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ *
+ */
+public final class SingleTokenPHPScanner extends AbstractJavaScanner {
+
+ private String[] fProperty;
+
+ public SingleTokenPHPScanner(IColorManager manager, IPreferenceStore store,
+ String property) {
+ super(manager, store);
+ fProperty = new String[] { property };
+ initialize();
+ }
+
+ /*
+ * @see AbstractJavaScanner#getTokenProperties()
+ */
+ protected String[] getTokenProperties() {
+ return fProperty;
+ }
+
+ /*
+ * @see AbstractJavaScanner#createRules()
+ */
+ protected List createRules() {
+ setDefaultReturnToken(getToken(fProperty[0]));
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/IJavaFoldingPreferenceBlock.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/IJavaFoldingPreferenceBlock.java
new file mode 100644
index 0000000..dc9e1bf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/IJavaFoldingPreferenceBlock.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.text.folding;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Contributors to the
+ * net.sourceforge.phpdt.ui.foldingStructureProvider
extension
+ * point can specify an implementation of this interface to be displayed on the
+ * Java > Editor > Folding preference page.
+ *
+ * Clients may implement this interface.
+ *
+ *
+ * @since 3.0
+ */
+public interface IJavaFoldingPreferenceBlock {
+
+ /**
+ * Creates the control that will be displayed on the Java Editor folding
+ * preference page.
+ *
+ * @param parent
+ * the parent composite to which to add the preferences control
+ * @return the control that was added to parent
+ */
+ Control createControl(Composite parent);
+
+ /**
+ * Called after creating the control. Implementations should load the
+ * preferences values and update the controls accordingly.
+ */
+ void initialize();
+
+ /**
+ * Called when the OK
button is pressed on the preference
+ * page. Implementations should commit the configured preference settings
+ * into their form of preference storage.
+ */
+ void performOk();
+
+ /**
+ * Called when the Defaults
button is pressed on the
+ * preference page. Implementation should reset any preference settings to
+ * their default values and adjust the controls accordingly.
+ */
+ void performDefaults();
+
+ /**
+ * Called when the preference page is being disposed. Implementations should
+ * free any resources they are holding on to.
+ */
+ void dispose();
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/IJavaFoldingStructureProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/IJavaFoldingStructureProvider.java
new file mode 100644
index 0000000..9fa814a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/IJavaFoldingStructureProvider.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.text.folding;
+
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Contributors to the
+ * net.sourceforge.phpdt.ui.foldingStructureProvider
extension
+ * point must specify an implementation of this interface which will create and
+ * maintain
+ * {@link org.eclipse.jface.text.source.projection.ProjectionAnnotation} objects
+ * as understood by
+ * {@link org.eclipse.jface.text.source.projection.ProjectionViewer}.
+ *
+ * Clients may implement this interface.
+ *
+ *
+ * @since 3.0
+ */
+public interface IJavaFoldingStructureProvider {
+
+ /**
+ * Installs this structure provider on the given editor and viewer.
+ * Implementations should observe the projection events generated by
+ * viewer
and enable / disable generation of projection
+ * structure accordingly.
+ *
+ * @param editor
+ * the editor that this provider works on
+ * @param viewer
+ * the projection viewer that displays the annotations created by
+ * this structure provider
+ */
+ public abstract void install(ITextEditor editor, ProjectionViewer viewer);
+
+ /**
+ * Uninstalls this structure provider. Any references to editors or viewers
+ * should be cleared.
+ */
+ public abstract void uninstall();
+
+ /**
+ * (Re-)initializes the structure provided by the receiver.
+ */
+ public abstract void initialize();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/package.html b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/package.html
new file mode 100644
index 0000000..3148d97
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/folding/package.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ Java Folding
+
+
+Application programming interfaces for interaction
+with the Eclipse Java Editor folding.
+
+Package Specification
+Interfaces for contributions to the net.sourceforge.phpdt.ui.foldingStructureProviders
extension point.
+
+
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/java/hover/IJavaEditorTextHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/java/hover/IJavaEditorTextHover.java
new file mode 100644
index 0000000..5f4dda2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/java/hover/IJavaEditorTextHover.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.text.java.hover;
+
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Provides a hover popup which appears on top of an editor with relevant
+ * display information. If the text hover does not provide information no hover
+ * popup is shown.
+ *
+ * Clients may implement this interface.
+ *
+ *
+ * @see org.eclipse.ui.IEditorPart
+ * @see org.eclipse.jface.text.ITextHover
+ *
+ * @since 2.0
+ */
+public interface IJavaEditorTextHover extends ITextHover {
+
+ /**
+ * Sets the editor on which the hover is shown.
+ *
+ * @param editor
+ * the editor on which the hover popup should be shown
+ */
+ void setEditor(IEditorPart editor);
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/java/hover/package.html b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/java/hover/package.html
new file mode 100644
index 0000000..7cfda13
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/text/java/hover/package.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ Package-level Javadoc
+
+
+Application programming interfaces for interaction with the PHPeclipse PHP Editor.
+
+Package Specification
+Support for presenting text hovers in PHP editors. The interface IJavaEditorTextHover
+defines the programming interface for a text hover.
+
+
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewClassWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewClassWizardPage.java
new file mode 100644
index 0000000..4203e32
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewClassWizardPage.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.wizards;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.ui.wizards.NewWizardMessages;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Wizard page to create a new class.
+ *
+ * Note: This class is not intended to be subclassed. To implement a different
+ * kind of a new class wizard page, extend NewTypeWizardPage
.
+ *
+ *
+ * @since 2.0
+ */
+public class NewClassWizardPage extends NewTypeWizardPage {
+
+ private final static String PAGE_NAME = "NewClassWizardPage"; //$NON-NLS-1$
+
+ private final static String SETTINGS_CREATEMAIN = "create_main"; //$NON-NLS-1$
+
+ private final static String SETTINGS_CREATECONSTR = "create_constructor"; //$NON-NLS-1$
+
+ private final static String SETTINGS_CREATEUNIMPLEMENTED = "create_unimplemented"; //$NON-NLS-1$
+
+ private SelectionButtonDialogFieldGroup fMethodStubsButtons;
+
+ /**
+ * Creates a new NewClassWizardPage
+ */
+ public NewClassWizardPage() {
+ super(true, PAGE_NAME);
+
+ setTitle(NewWizardMessages.getString("NewClassWizardPage.title")); //$NON-NLS-1$
+ setDescription(NewWizardMessages
+ .getString("NewClassWizardPage.description")); //$NON-NLS-1$
+
+ String[] buttonNames3 = new String[] {
+ NewWizardMessages.getString("NewClassWizardPage.methods.main"), NewWizardMessages.getString("NewClassWizardPage.methods.constructors"), //$NON-NLS-1$ //$NON-NLS-2$
+ NewWizardMessages
+ .getString("NewClassWizardPage.methods.inherited") //$NON-NLS-1$
+ };
+ fMethodStubsButtons = new SelectionButtonDialogFieldGroup(SWT.CHECK,
+ buttonNames3, 1);
+ fMethodStubsButtons.setLabelText(NewWizardMessages
+ .getString("NewClassWizardPage.methods.label")); //$NON-NLS-1$
+ }
+
+ // -------- Initialization ---------
+
+ /**
+ * 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 page.
+ *
+ * @param selection
+ * used to initialize the fields
+ */
+ public void init(IStructuredSelection selection) {
+ IJavaElement jelem = getInitialJavaElement(selection);
+ initContainerPage(jelem);
+ initTypePage(jelem);
+ doStatusUpdate();
+
+ boolean createMain = false;
+ boolean createConstructors = false;
+ boolean createUnimplemented = true;
+ IDialogSettings section = getDialogSettings().getSection(PAGE_NAME);
+ if (section != null) {
+ createMain = section.getBoolean(SETTINGS_CREATEMAIN);
+ createConstructors = section.getBoolean(SETTINGS_CREATECONSTR);
+ createUnimplemented = section
+ .getBoolean(SETTINGS_CREATEUNIMPLEMENTED);
+ }
+
+ setMethodStubSelection(createMain, createConstructors,
+ createUnimplemented, true);
+ }
+
+ // ------ validation --------
+ private void doStatusUpdate() {
+ // status of all used components
+ IStatus[] status = new IStatus[] {
+ fContainerStatus,
+ isEnclosingTypeSelected() ? fEnclosingTypeStatus
+ : fPackageStatus, fTypeNameStatus, fModifierStatus,
+ // fSuperClassStatus,
+ // fSuperInterfacesStatus
+ };
+
+ // the mode severe status will be displayed and the ok button
+ // enabled/disabled.
+ updateStatus(status);
+ }
+
+ /*
+ * @see NewContainerWizardPage#handleFieldChanged
+ */
+ protected void handleFieldChanged(String fieldName) {
+ super.handleFieldChanged(fieldName);
+
+ doStatusUpdate();
+ }
+
+ // ------ ui --------
+
+ /*
+ * @see WizardPage#createControl
+ */
+ public void createControl(Composite parent) {
+ initializeDialogUnits(parent);
+
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ int nColumns = 4;
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = nColumns;
+ composite.setLayout(layout);
+
+ // pick & choose the wanted UI components
+
+ createContainerControls(composite, nColumns);
+ createPackageControls(composite, nColumns);
+ createEnclosingTypeControls(composite, nColumns);
+
+ createSeparator(composite, nColumns);
+
+ createTypeNameControls(composite, nColumns);
+ createModifierControls(composite, nColumns);
+
+ createSuperClassControls(composite, nColumns);
+ createSuperInterfacesControls(composite, nColumns);
+
+ createMethodStubSelectionControls(composite, nColumns);
+
+ setControl(composite);
+
+ Dialog.applyDialogFont(composite);
+ // WorkbenchHelp.setHelp(composite,
+ // IJavaHelpContextIds.NEW_CLASS_WIZARD_PAGE);
+ }
+
+ /*
+ * @see WizardPage#becomesVisible
+ */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ setFocus();
+ }
+ }
+
+ private void createMethodStubSelectionControls(Composite composite,
+ int nColumns) {
+ Control labelControl = fMethodStubsButtons.getLabelControl(composite);
+ LayoutUtil.setHorizontalSpan(labelControl, nColumns);
+
+ DialogField.createEmptySpace(composite);
+
+ Control buttonGroup = fMethodStubsButtons
+ .getSelectionButtonsGroup(composite);
+ LayoutUtil.setHorizontalSpan(buttonGroup, nColumns - 1);
+ }
+
+ /**
+ * Returns the current selection state of the 'Create Main' checkbox.
+ *
+ * @return the selection state of the 'Create Main' checkbox
+ */
+ public boolean isCreateMain() {
+ return fMethodStubsButtons.isSelected(0);
+ }
+
+ /**
+ * Returns the current selection state of the 'Create Constructors'
+ * checkbox.
+ *
+ * @return the selection state of the 'Create Constructors' checkbox
+ */
+ public boolean isCreateConstructors() {
+ return fMethodStubsButtons.isSelected(1);
+ }
+
+ /**
+ * Returns the current selection state of the 'Create inherited abstract
+ * methods' checkbox.
+ *
+ * @return the selection state of the 'Create inherited abstract methods'
+ * checkbox
+ */
+ public boolean isCreateInherited() {
+ return fMethodStubsButtons.isSelected(2);
+ }
+
+ /**
+ * Sets the selection state of the method stub checkboxes.
+ *
+ * @param createMain
+ * initial selection state of the 'Create Main' checkbox.
+ * @param createConstructors
+ * initial selection state of the 'Create Constructors' checkbox.
+ * @param createInherited
+ * initial selection state of the 'Create inherited abstract
+ * methods' checkbox.
+ * @param canBeModified
+ * if true
the method stub checkboxes can be
+ * changed by the user. If false
the buttons are
+ * "read-only"
+ */
+ public void setMethodStubSelection(boolean createMain,
+ boolean createConstructors, boolean createInherited,
+ boolean canBeModified) {
+ fMethodStubsButtons.setSelection(0, createMain);
+ fMethodStubsButtons.setSelection(1, createConstructors);
+ fMethodStubsButtons.setSelection(2, createInherited);
+
+ fMethodStubsButtons.setEnabled(canBeModified);
+ }
+
+ // ---- creation ----------------
+
+ /*
+ * @see NewTypeWizardPage#createTypeMembers
+ */
+ // protected void createTypeMembers(IType type, ImportsManager imports,
+ // IProgressMonitor monitor) throws CoreException {
+ // boolean doMain= isCreateMain();
+ // boolean doConstr= isCreateConstructors();
+ // boolean doInherited= isCreateInherited();
+ // createInheritedMethods(type, doConstr, doInherited, imports, new
+ // SubProgressMonitor(monitor, 1));
+ //
+ // if (doMain) {
+ // StringBuffer buf= new StringBuffer();
+ // buf.append("public static void main("); //$NON-NLS-1$
+ // buf.append(imports.addImport("java.lang.String")); //$NON-NLS-1$
+ // buf.append("[] args) {}"); //$NON-NLS-1$
+ // type.createMethod(buf.toString(), null, false, null);
+ // }
+ //
+ // IDialogSettings section= getDialogSettings().getSection(PAGE_NAME);
+ // if (section == null) {
+ // section= getDialogSettings().addNewSection(PAGE_NAME);
+ // }
+ // section.put(SETTINGS_CREATEMAIN, doMain);
+ // section.put(SETTINGS_CREATECONSTR, doConstr);
+ // section.put(SETTINGS_CREATEUNIMPLEMENTED, doInherited);
+ //
+ // if (monitor != null) {
+ // monitor.done();
+ // }
+ // }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewContainerWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewContainerWizardPage.java
new file mode 100644
index 0000000..f21bfb6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewContainerWizardPage.java
@@ -0,0 +1,474 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.wizards;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.externaltools.internal.ui.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
+import net.sourceforge.phpdt.internal.ui.wizards.NewWizardMessages;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.views.contentoutline.ContentOutline;
+
+/**
+ * Wizard page that acts as a base class for wizard pages that create new Java
+ * elements. The class provides a input field for source folders (called
+ * container in this class) and API to validate the enter source folder name.
+ *
+ * @since 2.0
+ */
+public abstract class NewContainerWizardPage extends NewElementWizardPage {
+
+ /** Id of the container field */
+ protected static final String CONTAINER = "NewContainerWizardPage.container"; //$NON-NLS-1$
+
+ /** The status of the last validation. */
+ protected IStatus fContainerStatus;
+
+ private StringButtonDialogField fContainerDialogField;
+
+ /*
+ * package fragment root corresponding to the input type (can be null)
+ */
+ private IPackageFragmentRoot fCurrRoot;
+
+ private IWorkspaceRoot fWorkspaceRoot;
+
+ /**
+ * Create a new NewContainerWizardPage
+ *
+ * @param name
+ * the wizard page's name
+ */
+ public NewContainerWizardPage(String name) {
+ super(name);
+ fWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ ContainerFieldAdapter adapter = new ContainerFieldAdapter();
+
+ fContainerDialogField = new StringButtonDialogField(adapter);
+ fContainerDialogField.setDialogFieldListener(adapter);
+ fContainerDialogField.setLabelText(NewWizardMessages
+ .getString("NewContainerWizardPage.container.label")); //$NON-NLS-1$
+ fContainerDialogField.setButtonLabel(NewWizardMessages
+ .getString("NewContainerWizardPage.container.button")); //$NON-NLS-1$
+
+ fContainerStatus = new StatusInfo();
+ fCurrRoot = null;
+ }
+
+ /**
+ * Initializes the source folder field with a valid package fragement root.
+ * The package fragement root is computed from the given Java element.
+ *
+ * @param elem
+ * the Java element used to compute the initial package fragment
+ * root used as the source folder
+ */
+ protected void initContainerPage(IJavaElement elem) {
+ IPackageFragmentRoot initRoot = null;
+ // if (elem != null) {
+ // initRoot= JavaModelUtil.getPackageFragmentRoot(elem);
+ // if (initRoot == null || initRoot.isArchive()) {
+ // IJavaProject jproject= elem.getJavaProject();
+ // if (jproject != null) {
+ // try {
+ // initRoot= null;
+ // if (jproject.exists()) {
+ // IPackageFragmentRoot[] roots= jproject.getPackageFragmentRoots();
+ // for (int i= 0; i < roots.length; i++) {
+ // if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
+ // initRoot= roots[i];
+ // break;
+ // }
+ // }
+ // }
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e);
+ // }
+ // if (initRoot == null) {
+ // initRoot= jproject.getPackageFragmentRoot(jproject.getResource());
+ // }
+ // }
+ // }
+ // }
+ // setPackageFragmentRoot(initRoot, true);
+ }
+
+ /**
+ * Utility method to inspect a selection to find a Java element.
+ *
+ * @param selection
+ * the selection to be inspected
+ * @return a Java element to be used as the initial selection, or
+ * null
, if no Java element exists in the given
+ * selection
+ */
+ protected IJavaElement getInitialJavaElement(IStructuredSelection selection) {
+ IJavaElement jelem = null;
+ if (selection != null && !selection.isEmpty()) {
+ Object selectedElement = selection.getFirstElement();
+ if (selectedElement instanceof IAdaptable) {
+ IAdaptable adaptable = (IAdaptable) selectedElement;
+
+ jelem = (IJavaElement) adaptable.getAdapter(IJavaElement.class);
+ if (jelem == null) {
+ IResource resource = (IResource) adaptable
+ .getAdapter(IResource.class);
+ if (resource != null
+ && resource.getType() != IResource.ROOT) {
+ while (jelem == null
+ && resource.getType() != IResource.PROJECT) {
+ resource = resource.getParent();
+ jelem = (IJavaElement) resource
+ .getAdapter(IJavaElement.class);
+ }
+ if (jelem == null) {
+ jelem = JavaCore.create(resource); // java project
+ }
+ }
+ }
+ }
+ }
+ if (jelem == null) {
+ IWorkbenchPart part = WebUI.getActivePage()
+ .getActivePart();
+ if (part instanceof ContentOutline) {
+ part = WebUI.getActivePage().getActiveEditor();
+ }
+
+ if (part instanceof IViewPartInputProvider) {
+ Object elem = ((IViewPartInputProvider) part)
+ .getViewPartInput();
+ if (elem instanceof IJavaElement) {
+ jelem = (IJavaElement) elem;
+ }
+ }
+ }
+
+ if (jelem == null || jelem.getElementType() == IJavaElement.JAVA_MODEL) {
+ try {
+ IJavaProject[] projects = JavaCore.create(getWorkspaceRoot())
+ .getJavaProjects();
+ if (projects.length == 1) {
+ jelem = projects[0];
+ }
+ } catch (JavaModelException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ return jelem;
+ }
+
+ /**
+ * Returns the recommended maximum width for text fields (in pixels). This
+ * method requires that createContent has been called before this method is
+ * call. Subclasses may override to change the maximum width for text
+ * fields.
+ *
+ * @return the recommended maximum width for text fields.
+ */
+ protected int getMaxFieldWidth() {
+ return convertWidthInCharsToPixels(40);
+ }
+
+ /**
+ * Creates the necessary controls (label, text field and browse button) to
+ * edit the source folder location. The method expects that the parent
+ * composite uses a GridLayout
as its layout manager and that
+ * the grid layout has at least 3 columns.
+ *
+ * @param parent
+ * the parent composite
+ * @param nColumns
+ * the number of columns to span. This number must be greater or
+ * equal three
+ */
+ protected void createContainerControls(Composite parent, int nColumns) {
+ fContainerDialogField.doFillIntoGrid(parent, nColumns);
+ LayoutUtil.setWidthHint(fContainerDialogField.getTextControl(null),
+ getMaxFieldWidth());
+ }
+
+ /**
+ * Sets the focus to the source folder's text field.
+ */
+ protected void setFocusOnContainer() {
+ fContainerDialogField.setFocus();
+ }
+
+ // -------- ContainerFieldAdapter --------
+
+ private class ContainerFieldAdapter implements IStringButtonAdapter,
+ IDialogFieldListener {
+
+ // -------- IStringButtonAdapter
+ public void changeControlPressed(DialogField field) {
+ containerChangeControlPressed(field);
+ }
+
+ // -------- IDialogFieldListener
+ public void dialogFieldChanged(DialogField field) {
+ containerDialogFieldChanged(field);
+ }
+ }
+
+ private void containerChangeControlPressed(DialogField field) {
+ // take the current jproject as init element of the dialog
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ // root= chooseSourceContainer(root);
+ // if (root != null) {
+ // setPackageFragmentRoot(root, true);
+ // }
+ }
+
+ private void containerDialogFieldChanged(DialogField field) {
+ if (field == fContainerDialogField) {
+ fContainerStatus = containerChanged();
+ }
+ // tell all others
+ handleFieldChanged(CONTAINER);
+ }
+
+ // ----------- validation ----------
+
+ /**
+ * This method is a hook which gets called after the source folder's text
+ * input field has changed. This default implementation updates the model
+ * and returns an error status. The underlying model is only valid if the
+ * returned status is OK.
+ *
+ * @return the model's error status
+ */
+ protected IStatus containerChanged() {
+ StatusInfo status = new StatusInfo();
+
+ fCurrRoot = null;
+ String str = getPackageFragmentRootText();
+ if (str.length() == 0) {
+ status
+ .setError(NewWizardMessages
+ .getString("NewContainerWizardPage.error.EnterContainerName")); //$NON-NLS-1$
+ return status;
+ }
+ IPath path = new Path(str);
+ IResource res = fWorkspaceRoot.findMember(path);
+ if (res != null) {
+ int resType = res.getType();
+ if (resType == IResource.PROJECT || resType == IResource.FOLDER) {
+ IProject proj = res.getProject();
+ if (!proj.isOpen()) {
+ status
+ .setError(NewWizardMessages
+ .getFormattedString(
+ "NewContainerWizardPage.error.ProjectClosed", proj.getFullPath().toString())); //$NON-NLS-1$
+ return status;
+ }
+ IJavaProject jproject = JavaCore.create(proj);
+ // fCurrRoot= jproject.getPackageFragmentRoot(res);
+ // if (res.exists()) {
+ // try {
+ // if (!proj.hasNature(JavaCore.NATURE_ID)) {
+ // if (resType == IResource.PROJECT) {
+ // status.setError(NewWizardMessages.getString("NewContainerWizardPage.warning.NotAJavaProject"));
+ // //$NON-NLS-1$
+ // } else {
+ // status.setWarning(NewWizardMessages.getString("NewContainerWizardPage.warning.NotInAJavaProject"));
+ // //$NON-NLS-1$
+ // }
+ // return status;
+ // }
+ // } catch (CoreException e) {
+ // status.setWarning(NewWizardMessages.getString("NewContainerWizardPage.warning.NotAJavaProject"));
+ // //$NON-NLS-1$
+ // }
+ // if (!jproject.isOnClasspath(fCurrRoot)) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewContainerWizardPage.warning.NotOnClassPath",
+ // str)); //$NON-NLS-1$
+ // }
+ // if (fCurrRoot.isArchive()) {
+ // status.setError(NewWizardMessages.getFormattedString("NewContainerWizardPage.error.ContainerIsBinary",
+ // str)); //$NON-NLS-1$
+ // return status;
+ // }
+ // }
+ return status;
+ } else {
+ status.setError(NewWizardMessages.getFormattedString(
+ "NewContainerWizardPage.error.NotAFolder", str)); //$NON-NLS-1$
+ return status;
+ }
+ } else {
+ status.setError(NewWizardMessages.getFormattedString(
+ "NewContainerWizardPage.error.ContainerDoesNotExist", str)); //$NON-NLS-1$
+ return status;
+ }
+ }
+
+ // -------- update message ----------------
+
+ /**
+ * Hook method that gets called when a field on this page has changed. For
+ * this page the method gets called when the source folder field changes.
+ *
+ * Every sub type is responsible to call this method when a field on its
+ * page has changed. Subtypes override (extend) the method to add
+ * verification when a own field has a dependency to an other field. For
+ * example the class name input must be verified again when the package
+ * field changes (check for duplicated class names).
+ *
+ * @param fieldName
+ * The name of the field that has changed (field id). For the
+ * source folder the field id is CONTAINER
+ */
+ protected void handleFieldChanged(String fieldName) {
+ }
+
+ // ---- get ----------------
+
+ /**
+ * Returns the workspace root.
+ *
+ * @return the workspace root
+ */
+ protected IWorkspaceRoot getWorkspaceRoot() {
+ return fWorkspaceRoot;
+ }
+
+ /**
+ * Returns the IPackageFragmentRoot
that corresponds to the
+ * current value of the source folder field.
+ *
+ * @return the IPackageFragmentRoot or null
if the current
+ * source folder value is not a valid package fragment root
+ *
+ */
+ public IPackageFragmentRoot getPackageFragmentRoot() {
+ return fCurrRoot;
+ }
+
+ /**
+ * Returns the current text of source folder text field.
+ *
+ * @return the text of the source folder text field
+ */
+ public String getPackageFragmentRootText() {
+ return fContainerDialogField.getText();
+ }
+
+ /**
+ * Sets the current source folder (model and text field) to the given
+ * package fragment root.
+ *
+ * @param canBeModified
+ * if false
the source folder field can not be
+ * changed by the user. If true
the field is
+ * editable
+ */
+ // public void setPackageFragmentRoot(IPackageFragmentRoot root, boolean
+ // canBeModified) {
+ // fCurrRoot= root;
+ // String str= (root == null) ? "" :
+ // root.getPath().makeRelative().toString(); //$NON-NLS-1$
+ // fContainerDialogField.setText(str);
+ // fContainerDialogField.setEnabled(canBeModified);
+ // }
+ // ------------- choose source container dialog
+ // private IPackageFragmentRoot chooseSourceContainer(IJavaElement
+ // initElement) {
+ // Class[] acceptedClasses= new Class[] { IPackageFragmentRoot.class,
+ // IJavaProject.class };
+ // TypedElementSelectionValidator validator= new
+ // TypedElementSelectionValidator(acceptedClasses, false) {
+ // public boolean isSelectedValid(Object element) {
+ // try {
+ // if (element instanceof IJavaProject) {
+ // IJavaProject jproject= (IJavaProject)element;
+ // IPath path= jproject.getProject().getFullPath();
+ // return (jproject.findPackageFragmentRoot(path) != null);
+ // } else if (element instanceof IPackageFragmentRoot) {
+ // return (((IPackageFragmentRoot)element).getKind() ==
+ // IPackageFragmentRoot.K_SOURCE);
+ // }
+ // return true;
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e.getStatus()); // just log, no ui in validation
+ // }
+ // return false;
+ // }
+ // };
+ //
+ // acceptedClasses= new Class[] { IJavaModel.class,
+ // IPackageFragmentRoot.class, IJavaProject.class };
+ // ViewerFilter filter= new TypedViewerFilter(acceptedClasses) {
+ // public boolean select(Viewer viewer, Object parent, Object element) {
+ // if (element instanceof IPackageFragmentRoot) {
+ // try {
+ // return (((IPackageFragmentRoot)element).getKind() ==
+ // IPackageFragmentRoot.K_SOURCE);
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e.getStatus()); // just log, no ui in validation
+ // return false;
+ // }
+ // }
+ // return super.select(viewer, parent, element);
+ // }
+ // };
+ //
+ // StandardJavaElementContentProvider provider= new
+ // StandardJavaElementContentProvider();
+ // ILabelProvider labelProvider= new
+ // JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
+ // ElementTreeSelectionDialog dialog= new
+ // ElementTreeSelectionDialog(getShell(), labelProvider, provider);
+ // dialog.setValidator(validator);
+ // dialog.setSorter(new JavaElementSorter());
+ // dialog.setTitle(NewWizardMessages.getString("NewContainerWizardPage.ChooseSourceContainerDialog.title"));
+ // //$NON-NLS-1$
+ // dialog.setMessage(NewWizardMessages.getString("NewContainerWizardPage.ChooseSourceContainerDialog.description"));
+ // //$NON-NLS-1$
+ // dialog.addFilter(filter);
+ // dialog.setInput(JavaCore.create(fWorkspaceRoot));
+ // dialog.setInitialSelection(initElement);
+ //
+ // if (dialog.open() == ElementTreeSelectionDialog.OK) {
+ // Object element= dialog.getFirstResult();
+ // if (element instanceof IJavaProject) {
+ // IJavaProject jproject= (IJavaProject)element;
+ // return jproject.getPackageFragmentRoot(jproject.getProject());
+ // } else if (element instanceof IPackageFragmentRoot) {
+ // return (IPackageFragmentRoot)element;
+ // }
+ // return null;
+ // }
+ // return null;
+ // }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewElementWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewElementWizardPage.java
new file mode 100644
index 0000000..653d4a0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewElementWizardPage.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.wizards;
+
+import net.sourceforge.phpdt.externaltools.internal.ui.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.wizard.WizardPage;
+
+/**
+ * Base class for wizard page responsible to create PHP elements. The class
+ * provides API to update the wizard's statis line and OK button according to
+ * the value of a IStatus
object.
+ *
+ * @since 2.0
+ */
+public abstract class NewElementWizardPage extends WizardPage {
+
+ private IStatus fCurrStatus;
+
+ private boolean fPageVisible;
+
+ /**
+ * Creates a NewElementWizardPage
.
+ *
+ * @param name
+ * the wizard page's name
+ */
+ public NewElementWizardPage(String name) {
+ super(name);
+ fPageVisible = false;
+ fCurrStatus = new StatusInfo();
+ }
+
+ // ---- WizardPage ----------------
+
+ /*
+ * @see WizardPage#becomesVisible
+ */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ fPageVisible = visible;
+ // policy: wizards are not allowed to come up with an error message
+ if (visible && fCurrStatus.matches(IStatus.ERROR)) {
+ StatusInfo status = new StatusInfo();
+ status.setError(""); //$NON-NLS-1$
+ fCurrStatus = status;
+ }
+ updateStatus(fCurrStatus);
+ }
+
+ /**
+ * Updates the status line and the ok button according to the given status
+ *
+ * @param status
+ * status to apply
+ */
+ protected void updateStatus(IStatus status) {
+ fCurrStatus = status;
+ setPageComplete(!status.matches(IStatus.ERROR));
+ if (fPageVisible) {
+ StatusUtil.applyToStatusLine(this, status);
+ }
+ }
+
+ /**
+ * Updates the status line and the ok button according to the status
+ * evaluate from an array of status. The most severe error is taken. In case
+ * that two status with the same severity exists, the status with lower
+ * index is taken.
+ *
+ * @param status
+ * the array of status
+ */
+ protected void updateStatus(IStatus[] status) {
+ updateStatus(StatusUtil.getMostSevere(status));
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewTypeWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewTypeWizardPage.java
new file mode 100644
index 0000000..a73147a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/ui/wizards/NewTypeWizardPage.java
@@ -0,0 +1,1954 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.ui.wizards;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.Flags;
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.ToolFactory;
+import net.sourceforge.phpdt.core.compiler.IScanner;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.externaltools.internal.ui.StatusInfo;
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.corext.template.php.Templates;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.NewWizardMessages;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IListAdapter;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.ListDialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.Separator;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.StringButtonStatusDialogField;
+import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.StringDialogField;
+import net.sourceforge.phpdt.ui.CodeGeneration;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * The class NewTypeWizardPage
contains controls and validation
+ * routines for a 'New Type WizardPage'. Implementors decide which components to
+ * add and to enable. Implementors can also customize the validation code.
+ * NewTypeWizardPage
is intended to serve as base class of all
+ * wizards that create types like applets, servlets, classes, interfaces, etc.
+ *
+ * See NewClassWizardPage
or NewInterfaceWizardPage
+ * for an example usage of NewTypeWizardPage
.
+ *
+ *
+ * @see net.sourceforge.phpdt.ui.wizards.NewClassWizardPage
+ * @see net.sourceforge.phpdt.ui.wizards.NewInterfaceWizardPage
+ *
+ * @since 2.0
+ */
+public abstract class NewTypeWizardPage extends NewContainerWizardPage {
+
+ /**
+ * Class used in stub creation routines to add needed imports to a
+ * compilation unit.
+ */
+ // public static class ImportsManager {
+ //
+ // private IImportsStructure fImportsStructure;
+ //
+ // /* package */ ImportsManager(IImportsStructure structure) {
+ // fImportsStructure= structure;
+ // }
+ //
+ // /* package */ IImportsStructure getImportsStructure() {
+ // return fImportsStructure;
+ // }
+ //
+ // /**
+ // * Adds a new import declaration that is sorted in the existing imports.
+ // * If an import already exists or the import would conflict with another
+ // import
+ // * of an other type with the same simple name the import is not added.
+ // *
+ // * @param qualifiedTypeName The fully qualified name of the type to import
+ // * (dot separated)
+ // * @return Returns the simple type name that can be used in the code or
+ // the
+ // * fully qualified type name if an import conflict prevented the import
+ // */
+ // public String addImport(String qualifiedTypeName) {
+ // return fImportsStructure.addImport(qualifiedTypeName);
+ // }
+ // }
+ /**
+ * Public access flag. See The Java Virtual Machine Specification for more
+ * details.
+ */
+ public int F_PUBLIC = Flags.AccPublic;
+
+ /**
+ * Private access flag. See The Java Virtual Machine Specification for more
+ * details.
+ */
+ public int F_PRIVATE = Flags.AccPrivate;
+
+ /**
+ * Protected access flag. See The Java Virtual Machine Specification for
+ * more details.
+ */
+ public int F_PROTECTED = Flags.AccProtected;
+
+ /**
+ * Static access flag. See The Java Virtual Machine Specification for more
+ * details.
+ */
+ public int F_STATIC = Flags.AccStatic;
+
+ /**
+ * Final access flag. See The Java Virtual Machine Specification for more
+ * details.
+ */
+ public int F_FINAL = Flags.AccFinal;
+
+ /**
+ * Abstract property flag. See The Java Virtual Machine Specification for
+ * more details.
+ */
+ // public int F_ABSTRACT = Flags.AccAbstract;
+ private final static String PAGE_NAME = "NewTypeWizardPage"; //$NON-NLS-1$
+
+ /** Field ID of the package input field */
+ protected final static String PACKAGE = PAGE_NAME + ".package"; //$NON-NLS-1$
+
+ /** Field ID of the eclosing type input field */
+ protected final static String ENCLOSING = PAGE_NAME + ".enclosing"; //$NON-NLS-1$
+
+ /** Field ID of the enclosing type checkbox */
+ protected final static String ENCLOSINGSELECTION = ENCLOSING + ".selection"; //$NON-NLS-1$
+
+ /** Field ID of the type name input field */
+ protected final static String TYPENAME = PAGE_NAME + ".typename"; //$NON-NLS-1$
+
+ /** Field ID of the super type input field */
+ protected final static String SUPER = PAGE_NAME + ".superclass"; //$NON-NLS-1$
+
+ /** Field ID of the super interfaces input field */
+ protected final static String INTERFACES = PAGE_NAME + ".interfaces"; //$NON-NLS-1$
+
+ /** Field ID of the modifier checkboxes */
+ protected final static String MODIFIERS = PAGE_NAME + ".modifiers"; //$NON-NLS-1$
+
+ /** Field ID of the method stubs checkboxes */
+ protected final static String METHODS = PAGE_NAME + ".methods"; //$NON-NLS-1$
+
+ private class InterfacesListLabelProvider extends LabelProvider {
+
+ private Image fInterfaceImage;
+
+ public InterfacesListLabelProvider() {
+ super();
+ fInterfaceImage = PHPUiImages.get(PHPUiImages.IMG_OBJS_INTERFACE);
+ }
+
+ public Image getImage(Object element) {
+ return fInterfaceImage;
+ }
+ }
+
+ private StringButtonStatusDialogField fPackageDialogField;
+
+ private SelectionButtonDialogField fEnclosingTypeSelection;
+
+ private StringButtonDialogField fEnclosingTypeDialogField;
+
+ private boolean fCanModifyPackage;
+
+ private boolean fCanModifyEnclosingType;
+
+ private IPackageFragment fCurrPackage;
+
+ // private IType fCurrEnclosingType;
+ private StringDialogField fTypeNameDialogField;
+
+ private StringButtonDialogField fSuperClassDialogField;
+
+ private ListDialogField fSuperInterfacesDialogField;
+
+ // private IType fSuperClass;
+
+ private SelectionButtonDialogFieldGroup fAccMdfButtons;
+
+ private SelectionButtonDialogFieldGroup fOtherMdfButtons;
+
+ private IType fCreatedType;
+
+ protected IStatus fEnclosingTypeStatus;
+
+ protected IStatus fPackageStatus;
+
+ protected IStatus fTypeNameStatus;
+
+ // protected IStatus fSuperClassStatus;
+ protected IStatus fModifierStatus;
+
+ // protected IStatus fSuperInterfacesStatus;
+
+ private boolean fIsClass;
+
+ private int fStaticMdfIndex;
+
+ private final int PUBLIC_INDEX = 0, DEFAULT_INDEX = 1, PRIVATE_INDEX = 2,
+ PROTECTED_INDEX = 3;
+
+ private final int ABSTRACT_INDEX = 0, FINAL_INDEX = 1;
+
+ /**
+ * Creates a new NewTypeWizardPage
+ *
+ * @param isClass
+ * true
if a new class is to be created; otherwise
+ * an interface is to be created
+ * @param pageName
+ * the wizard page's name
+ */
+ public NewTypeWizardPage(boolean isClass, String pageName) {
+ super(pageName);
+ fCreatedType = null;
+
+ fIsClass = isClass;
+
+ TypeFieldsAdapter adapter = new TypeFieldsAdapter();
+
+ fPackageDialogField = new StringButtonStatusDialogField(adapter);
+ fPackageDialogField.setDialogFieldListener(adapter);
+ fPackageDialogField.setLabelText(NewWizardMessages
+ .getString("NewTypeWizardPage.package.label")); //$NON-NLS-1$
+ fPackageDialogField.setButtonLabel(NewWizardMessages
+ .getString("NewTypeWizardPage.package.button")); //$NON-NLS-1$
+ fPackageDialogField.setStatusWidthHint(NewWizardMessages
+ .getString("NewTypeWizardPage.default")); //$NON-NLS-1$
+
+ fEnclosingTypeSelection = new SelectionButtonDialogField(SWT.CHECK);
+ fEnclosingTypeSelection.setDialogFieldListener(adapter);
+ fEnclosingTypeSelection.setLabelText(NewWizardMessages
+ .getString("NewTypeWizardPage.enclosing.selection.label")); //$NON-NLS-1$
+
+ fEnclosingTypeDialogField = new StringButtonDialogField(adapter);
+ fEnclosingTypeDialogField.setDialogFieldListener(adapter);
+ fEnclosingTypeDialogField.setButtonLabel(NewWizardMessages
+ .getString("NewTypeWizardPage.enclosing.button")); //$NON-NLS-1$
+
+ fTypeNameDialogField = new StringDialogField();
+ fTypeNameDialogField.setDialogFieldListener(adapter);
+ fTypeNameDialogField.setLabelText(NewWizardMessages
+ .getString("NewTypeWizardPage.typename.label")); //$NON-NLS-1$
+
+ fSuperClassDialogField = new StringButtonDialogField(adapter);
+ fSuperClassDialogField.setDialogFieldListener(adapter);
+ fSuperClassDialogField.setLabelText(NewWizardMessages
+ .getString("NewTypeWizardPage.superclass.label")); //$NON-NLS-1$
+ fSuperClassDialogField.setButtonLabel(NewWizardMessages
+ .getString("NewTypeWizardPage.superclass.button")); //$NON-NLS-1$
+
+ String[] addButtons = new String[] {
+ /* 0 */
+ NewWizardMessages.getString("NewTypeWizardPage.interfaces.add"), //$NON-NLS-1$
+ /* 1 */
+ null,
+ /* 2 */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.interfaces.remove") //$NON-NLS-1$
+ };
+ fSuperInterfacesDialogField = new ListDialogField(adapter, addButtons,
+ new InterfacesListLabelProvider());
+ fSuperInterfacesDialogField.setDialogFieldListener(adapter);
+ String interfaceLabel = fIsClass ? NewWizardMessages
+ .getString("NewTypeWizardPage.interfaces.class.label") : NewWizardMessages.getString("NewTypeWizardPage.interfaces.ifc.label"); //$NON-NLS-1$ //$NON-NLS-2$
+ fSuperInterfacesDialogField.setLabelText(interfaceLabel);
+ fSuperInterfacesDialogField.setRemoveButtonIndex(2);
+
+ String[] buttonNames1 = new String[] {
+ /* 0 == PUBLIC_INDEX */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.public"), //$NON-NLS-1$
+ /* 1 == DEFAULT_INDEX */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.default"), //$NON-NLS-1$
+ /* 2 == PRIVATE_INDEX */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.private"), //$NON-NLS-1$
+ /* 3 == PROTECTED_INDEX */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.protected") //$NON-NLS-1$
+ };
+ fAccMdfButtons = new SelectionButtonDialogFieldGroup(SWT.RADIO,
+ buttonNames1, 4);
+ fAccMdfButtons.setDialogFieldListener(adapter);
+ fAccMdfButtons.setLabelText(NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.acc.label")); //$NON-NLS-1$
+ fAccMdfButtons.setSelection(0, true);
+
+ String[] buttonNames2;
+ if (fIsClass) {
+ buttonNames2 = new String[] {
+ /* 0 == ABSTRACT_INDEX */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.abstract"), //$NON-NLS-1$
+ /* 1 == FINAL_INDEX */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.final"), //$NON-NLS-1$
+ /* 2 */
+ NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.static") //$NON-NLS-1$
+ };
+ fStaticMdfIndex = 2; // index of the static checkbox is 2
+ } else {
+ buttonNames2 = new String[] { NewWizardMessages
+ .getString("NewTypeWizardPage.modifiers.static") //$NON-NLS-1$
+ };
+ fStaticMdfIndex = 0; // index of the static checkbox is 0
+ }
+
+ fOtherMdfButtons = new SelectionButtonDialogFieldGroup(SWT.CHECK,
+ buttonNames2, 4);
+ fOtherMdfButtons.setDialogFieldListener(adapter);
+
+ fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, false);
+ fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, false);
+ fOtherMdfButtons.enableSelectionButton(fStaticMdfIndex, false);
+
+ fPackageStatus = new StatusInfo();
+ fEnclosingTypeStatus = new StatusInfo();
+
+ fCanModifyPackage = true;
+ fCanModifyEnclosingType = true;
+ updateEnableState();
+
+ fTypeNameStatus = new StatusInfo();
+ // fSuperClassStatus= new StatusInfo();
+ // fSuperInterfacesStatus= new StatusInfo();
+ fModifierStatus = new StatusInfo();
+ }
+
+ /**
+ * Initializes all fields provided by the page with a given selection.
+ *
+ * @param elem
+ * the selection used to intialize this page or
+ * null
+ * if no selection was available
+ */
+ protected void initTypePage(IJavaElement elem) {
+ String initSuperclass = "java.lang.Object"; //$NON-NLS-1$
+ ArrayList initSuperinterfaces = new ArrayList(5);
+
+ IPackageFragment pack = null;
+ IType enclosingType = null;
+
+ if (elem != null) {
+ // evaluate the enclosing type
+ pack = (IPackageFragment) elem
+ .getAncestor(IJavaElement.PACKAGE_FRAGMENT);
+ IType typeInCU = (IType) elem.getAncestor(IJavaElement.TYPE);
+ if (typeInCU != null) {
+ if (typeInCU.getCompilationUnit() != null) {
+ enclosingType = typeInCU;
+ }
+ } else {
+ ICompilationUnit cu = (ICompilationUnit) elem
+ .getAncestor(IJavaElement.COMPILATION_UNIT);
+ if (cu != null) {
+ // enclosingType= cu.findPrimaryType();
+ }
+ }
+
+ // try {
+ // IType type= null;
+ // if (elem.getElementType() == IJavaElement.TYPE) {
+ // type= (IType)elem;
+ // if (type.exists()) {
+ // String superName= JavaModelUtil.getFullyQualifiedName(type);
+ // if (type.isInterface()) {
+ // initSuperinterfaces.add(superName);
+ // } else {
+ // initSuperclass= superName;
+ // }
+ // }
+ // }
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e);
+ // // ignore this exception now
+ // }
+ }
+
+ setPackageFragment(pack, true);
+ // setEnclosingType(enclosingType, true);
+ setEnclosingTypeSelection(false, true);
+
+ setTypeName("", true); //$NON-NLS-1$
+ setSuperClass(initSuperclass, true);
+ setSuperInterfaces(initSuperinterfaces, true);
+ }
+
+ // -------- UI Creation ---------
+
+ /**
+ * Creates a separator line. Expects a GridLayout
with at
+ * least 1 column.
+ *
+ * @param composite
+ * the parent composite
+ * @param nColumns
+ * number of columns to span
+ */
+ protected void createSeparator(Composite composite, int nColumns) {
+ (new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(
+ composite, nColumns, convertHeightInCharsToPixels(1));
+ }
+
+ /**
+ * Creates the controls for the package name field. Expects a
+ * GridLayout
with at least 4 columns.
+ *
+ * @param composite
+ * the parent composite
+ * @param nColumns
+ * number of columns to span
+ */
+ protected void createPackageControls(Composite composite, int nColumns) {
+ fPackageDialogField.doFillIntoGrid(composite, nColumns);
+ LayoutUtil.setWidthHint(fPackageDialogField.getTextControl(null),
+ getMaxFieldWidth());
+ LayoutUtil.setHorizontalGrabbing(fPackageDialogField
+ .getTextControl(null));
+ }
+
+ /**
+ * Creates the controls for the enclosing type name field. Expects a
+ * GridLayout
with at least 4 columns.
+ *
+ * @param composite
+ * the parent composite
+ * @param nColumns
+ * number of columns to span
+ */
+ protected void createEnclosingTypeControls(Composite composite, int nColumns) {
+ // #6891
+ Composite tabGroup = new Composite(composite, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ tabGroup.setLayout(layout);
+
+ fEnclosingTypeSelection.doFillIntoGrid(tabGroup, 1);
+
+ Control c = fEnclosingTypeDialogField.getTextControl(composite);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = getMaxFieldWidth();
+ gd.horizontalSpan = 2;
+ c.setLayoutData(gd);
+
+ Button button = fEnclosingTypeDialogField.getChangeControl(composite);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.heightHint = SWTUtil.getButtonHeightHint(button);
+ gd.widthHint = SWTUtil.getButtonWidthHint(button);
+ button.setLayoutData(gd);
+ }
+
+ /**
+ * Creates the controls for the type name field. Expects a
+ * GridLayout
with at least 2 columns.
+ *
+ * @param composite
+ * the parent composite
+ * @param nColumns
+ * number of columns to span
+ */
+ protected void createTypeNameControls(Composite composite, int nColumns) {
+ fTypeNameDialogField.doFillIntoGrid(composite, nColumns - 1);
+ DialogField.createEmptySpace(composite);
+
+ LayoutUtil.setWidthHint(fTypeNameDialogField.getTextControl(null),
+ getMaxFieldWidth());
+ }
+
+ /**
+ * Creates the controls for the modifiers radio/ceckbox buttons. Expects a
+ * GridLayout
with at least 3 columns.
+ *
+ * @param composite
+ * the parent composite
+ * @param nColumns
+ * number of columns to span
+ */
+ protected void createModifierControls(Composite composite, int nColumns) {
+ LayoutUtil.setHorizontalSpan(fAccMdfButtons.getLabelControl(composite),
+ 1);
+
+ Control control = fAccMdfButtons.getSelectionButtonsGroup(composite);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = nColumns - 2;
+ control.setLayoutData(gd);
+
+ DialogField.createEmptySpace(composite);
+
+ DialogField.createEmptySpace(composite);
+
+ control = fOtherMdfButtons.getSelectionButtonsGroup(composite);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = nColumns - 2;
+ control.setLayoutData(gd);
+
+ DialogField.createEmptySpace(composite);
+ }
+
+ /**
+ * Creates the controls for the superclass name field. Expects a
+ * GridLayout
with at least 3 columns.
+ *
+ * @param composite
+ * the parent composite
+ * @param nColumns
+ * number of columns to span
+ */
+ protected void createSuperClassControls(Composite composite, int nColumns) {
+ fSuperClassDialogField.doFillIntoGrid(composite, nColumns);
+ LayoutUtil.setWidthHint(fSuperClassDialogField.getTextControl(null),
+ getMaxFieldWidth());
+ }
+
+ /**
+ * Creates the controls for the superclass name field. Expects a
+ * GridLayout
with at least 3 columns.
+ *
+ * @param composite
+ * the parent composite
+ * @param nColumns
+ * number of columns to span
+ */
+ protected void createSuperInterfacesControls(Composite composite,
+ int nColumns) {
+ fSuperInterfacesDialogField.doFillIntoGrid(composite, nColumns);
+ GridData gd = (GridData) fSuperInterfacesDialogField.getListControl(
+ null).getLayoutData();
+ if (fIsClass) {
+ gd.heightHint = convertHeightInCharsToPixels(3);
+ } else {
+ gd.heightHint = convertHeightInCharsToPixels(6);
+ }
+ gd.grabExcessVerticalSpace = false;
+ gd.widthHint = getMaxFieldWidth();
+ }
+
+ /**
+ * Sets the focus on the type name input field.
+ */
+ protected void setFocus() {
+ fTypeNameDialogField.setFocus();
+ }
+
+ // -------- TypeFieldsAdapter --------
+
+ private class TypeFieldsAdapter implements IStringButtonAdapter,
+ IDialogFieldListener, IListAdapter {
+
+ // -------- IStringButtonAdapter
+ public void changeControlPressed(DialogField field) {
+ // typePageChangeControlPressed(field);
+ }
+
+ // -------- IListAdapter
+ public void customButtonPressed(ListDialogField field, int index) {
+ // typePageCustomButtonPressed(field, index);
+ }
+
+ public void selectionChanged(ListDialogField field) {
+ }
+
+ // -------- IDialogFieldListener
+ public void dialogFieldChanged(DialogField field) {
+ typePageDialogFieldChanged(field);
+ }
+
+ public void doubleClicked(ListDialogField field) {
+ }
+ }
+
+ // private void typePageChangeControlPressed(DialogField field) {
+ // if (field == fPackageDialogField) {
+ // IPackageFragment pack= choosePackage();
+ // if (pack != null) {
+ // fPackageDialogField.setText(pack.getElementName());
+ // }
+ // } else if (field == fEnclosingTypeDialogField) {
+ // IType type= chooseEnclosingType();
+ // if (type != null) {
+ // fEnclosingTypeDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
+ // }
+ // } else if (field == fSuperClassDialogField) {
+ // IType type= chooseSuperType();
+ // if (type != null) {
+ // fSuperClassDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
+ // }
+ // }
+ // }
+
+ // private void typePageCustomButtonPressed(DialogField field, int index) {
+ // if (field == fSuperInterfacesDialogField) {
+ // chooseSuperInterfaces();
+ // }
+ // }
+
+ /*
+ * A field on the type has changed. The fields' status and all dependend
+ * status are updated.
+ */
+ private void typePageDialogFieldChanged(DialogField field) {
+ String fieldName = null;
+ if (field == fPackageDialogField) {
+ fPackageStatus = packageChanged();
+ updatePackageStatusLabel();
+ fTypeNameStatus = typeNameChanged();
+ // fSuperClassStatus= superClassChanged();
+ fieldName = PACKAGE;
+ } else if (field == fEnclosingTypeDialogField) {
+ // fEnclosingTypeStatus= enclosingTypeChanged();
+ fTypeNameStatus = typeNameChanged();
+ // fSuperClassStatus= superClassChanged();
+ fieldName = ENCLOSING;
+ } else if (field == fEnclosingTypeSelection) {
+ updateEnableState();
+ boolean isEnclosedType = isEnclosingTypeSelected();
+ if (!isEnclosedType) {
+ if (fAccMdfButtons.isSelected(PRIVATE_INDEX)
+ || fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
+ fAccMdfButtons.setSelection(PRIVATE_INDEX, false);
+ fAccMdfButtons.setSelection(PROTECTED_INDEX, false);
+ fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
+ }
+ if (fOtherMdfButtons.isSelected(fStaticMdfIndex)) {
+ fOtherMdfButtons.setSelection(fStaticMdfIndex, false);
+ }
+ }
+ fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, isEnclosedType
+ && fIsClass);
+ fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX,
+ isEnclosedType && fIsClass);
+ fOtherMdfButtons.enableSelectionButton(fStaticMdfIndex,
+ isEnclosedType);
+ fTypeNameStatus = typeNameChanged();
+ // fSuperClassStatus= superClassChanged();
+ fieldName = ENCLOSINGSELECTION;
+ } else if (field == fTypeNameDialogField) {
+ fTypeNameStatus = typeNameChanged();
+ fieldName = TYPENAME;
+ } else if (field == fSuperClassDialogField) {
+ // fSuperClassStatus= superClassChanged();
+ fieldName = SUPER;
+ } else if (field == fSuperInterfacesDialogField) {
+ // fSuperInterfacesStatus= superInterfacesChanged();
+ fieldName = INTERFACES;
+ } else if (field == fOtherMdfButtons) {
+ fModifierStatus = modifiersChanged();
+ fieldName = MODIFIERS;
+ } else {
+ fieldName = METHODS;
+ }
+ // tell all others
+ handleFieldChanged(fieldName);
+ }
+
+ // -------- update message ----------------
+
+ /*
+ * @see net.sourceforge.phpdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
+ */
+ protected void handleFieldChanged(String fieldName) {
+ super.handleFieldChanged(fieldName);
+ if (fieldName == CONTAINER) {
+ fPackageStatus = packageChanged();
+ // fEnclosingTypeStatus= enclosingTypeChanged();
+ fTypeNameStatus = typeNameChanged();
+ // fSuperClassStatus= superClassChanged();
+ // fSuperInterfacesStatus= superInterfacesChanged();
+ }
+ }
+
+ // ---- set / get ----------------
+
+ /**
+ * Returns the text of the package input field.
+ *
+ * @return the text of the package input field
+ */
+ public String getPackageText() {
+ return fPackageDialogField.getText();
+ }
+
+ /**
+ * Returns the text of the enclosing type input field.
+ *
+ * @return the text of the enclosing type input field
+ */
+ public String getEnclosingTypeText() {
+ return fEnclosingTypeDialogField.getText();
+ }
+
+ /**
+ * Returns the package fragment corresponding to the current input.
+ *
+ * @return a package fragement or null
if the input could not
+ * be resolved.
+ */
+ public IPackageFragment getPackageFragment() {
+ if (!isEnclosingTypeSelected()) {
+ return fCurrPackage;
+ } else {
+ // if (fCurrEnclosingType != null) {
+ // return fCurrEnclosingType.getPackageFragment();
+ // }
+ }
+ return null;
+ }
+
+ /**
+ * Sets the package fragment to the given value. The method updates the
+ * model and the text of the control.
+ *
+ * @param pack
+ * the package fragement to be set
+ * @param canBeModified
+ * if true
the package fragment is editable;
+ * otherwise it is read-only.
+ */
+ public void setPackageFragment(IPackageFragment pack, boolean canBeModified) {
+ fCurrPackage = pack;
+ fCanModifyPackage = canBeModified;
+ String str = (pack == null) ? "" : pack.getElementName(); //$NON-NLS-1$
+ fPackageDialogField.setText(str);
+ updateEnableState();
+ }
+
+ /**
+ * Returns the enclosing type corresponding to the current input.
+ *
+ * @return the enclosing type or null
if the enclosing type
+ * is not selected or the input could not be resolved
+ */
+ public IType getEnclosingType() {
+ // if (isEnclosingTypeSelected()) {
+ // return fCurrEnclosingType;
+ // }
+ return null;
+ }
+
+ /**
+ * Sets the enclosing type. The method updates the underlying model and the
+ * text of the control.
+ *
+ * @param type
+ * the enclosing type
+ * @param canBeModified
+ * if true
the enclosing type field is editable;
+ * otherwise it is read-only.
+ */
+ // public void setEnclosingType(IType type, boolean canBeModified) {
+ // fCurrEnclosingType= type;
+ // fCanModifyEnclosingType= canBeModified;
+ // String str= (type == null) ? "" :
+ // JavaModelUtil.getFullyQualifiedName(type); //$NON-NLS-1$
+ // fEnclosingTypeDialogField.setText(str);
+ // updateEnableState();
+ // }
+ /**
+ * Returns the selection state of the enclosing type checkbox.
+ *
+ * @return the seleciton state of the enclosing type checkbox
+ */
+ public boolean isEnclosingTypeSelected() {
+ return fEnclosingTypeSelection.isSelected();
+ }
+
+ /**
+ * Sets the enclosing type checkbox's selection state.
+ *
+ * @param isSelected
+ * the checkbox's selection state
+ * @param canBeModified
+ * if true
the enclosing type checkbox is
+ * modifiable; otherwise it is read-only.
+ */
+ public void setEnclosingTypeSelection(boolean isSelected,
+ boolean canBeModified) {
+ fEnclosingTypeSelection.setSelection(isSelected);
+ fEnclosingTypeSelection.setEnabled(canBeModified);
+ updateEnableState();
+ }
+
+ /**
+ * Returns the type name entered into the type input field.
+ *
+ * @return the type name
+ */
+ public String getTypeName() {
+ return fTypeNameDialogField.getText();
+ }
+
+ /**
+ * Sets the type name input field's text to the given value. Method doesn't
+ * update the model.
+ *
+ * @param name
+ * the new type name
+ * @param canBeModified
+ * if true
the enclosing type name field is
+ * editable; otherwise it is read-only.
+ */
+ public void setTypeName(String name, boolean canBeModified) {
+ fTypeNameDialogField.setText(name);
+ fTypeNameDialogField.setEnabled(canBeModified);
+ }
+
+ /**
+ * Returns the selected modifiers.
+ *
+ * @return the selected modifiers
+ * @see Flags
+ */
+ public int getModifiers() {
+ int mdf = 0;
+ if (fAccMdfButtons.isSelected(PUBLIC_INDEX)) {
+ mdf += F_PUBLIC;
+ } else if (fAccMdfButtons.isSelected(PRIVATE_INDEX)) {
+ mdf += F_PRIVATE;
+ } else if (fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
+ mdf += F_PROTECTED;
+ }
+ // if (fOtherMdfButtons.isSelected(ABSTRACT_INDEX) && (fStaticMdfIndex
+ // != 0)) {
+ // mdf+= F_ABSTRACT;
+ // }
+ if (fOtherMdfButtons.isSelected(FINAL_INDEX)) {
+ mdf += F_FINAL;
+ }
+ if (fOtherMdfButtons.isSelected(fStaticMdfIndex)) {
+ mdf += F_STATIC;
+ }
+ return mdf;
+ }
+
+ /**
+ * Sets the modifiers.
+ *
+ * @param modifiers
+ * F_PUBLIC
, F_PRIVATE
,
+ * F_PROTECTED
, F_ABSTRACT, F_FINAL
+ * or F_STATIC
or, a valid combination.
+ * @param canBeModified
+ * if true
the modifier fields are editable;
+ * otherwise they are read-only
+ * @see Flags
+ */
+ public void setModifiers(int modifiers, boolean canBeModified) {
+ if (Flags.isPublic(modifiers)) {
+ fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
+ } else if (Flags.isPrivate(modifiers)) {
+ fAccMdfButtons.setSelection(PRIVATE_INDEX, true);
+ } else if (Flags.isProtected(modifiers)) {
+ fAccMdfButtons.setSelection(PROTECTED_INDEX, true);
+ } else {
+ fAccMdfButtons.setSelection(DEFAULT_INDEX, true);
+ }
+ // if (Flags.isAbstract(modifiers)) {
+ // fOtherMdfButtons.setSelection(ABSTRACT_INDEX, true);
+ // }
+ if (Flags.isFinal(modifiers)) {
+ fOtherMdfButtons.setSelection(FINAL_INDEX, true);
+ }
+ if (Flags.isStatic(modifiers)) {
+ fOtherMdfButtons.setSelection(fStaticMdfIndex, true);
+ }
+
+ fAccMdfButtons.setEnabled(canBeModified);
+ fOtherMdfButtons.setEnabled(canBeModified);
+ }
+
+ /**
+ * Returns the content of the superclass input field.
+ *
+ * @return the superclass name
+ */
+ public String getSuperClass() {
+ return fSuperClassDialogField.getText();
+ }
+
+ /**
+ * Sets the super class name.
+ *
+ * @param name
+ * the new superclass name
+ * @param canBeModified
+ * if true
the superclass name field is editable;
+ * otherwise it is read-only.
+ */
+ public void setSuperClass(String name, boolean canBeModified) {
+ fSuperClassDialogField.setText(name);
+ fSuperClassDialogField.setEnabled(canBeModified);
+ }
+
+ /**
+ * Returns the chosen super interfaces.
+ *
+ * @return a list of chosen super interfaces. The list's elements are of
+ * type String
+ */
+ public List getSuperInterfaces() {
+ return fSuperInterfacesDialogField.getElements();
+ }
+
+ /**
+ * Sets the super interfaces.
+ *
+ * @param interfacesNames
+ * a list of super interface. The method requires that the list's
+ * elements are of type String
+ * @param canBeModified
+ * if true
the super interface field is editable;
+ * otherwise it is read-only.
+ */
+ public void setSuperInterfaces(List interfacesNames, boolean canBeModified) {
+ fSuperInterfacesDialogField.setElements(interfacesNames);
+ fSuperInterfacesDialogField.setEnabled(canBeModified);
+ }
+
+ // ----------- validation ----------
+
+ /**
+ * A hook method that gets called when the package field has changed. The
+ * method validates the package name and returns the status of the
+ * validation. The validation also updates the package fragment model.
+ *
+ * Subclasses may extend this method to perform their own validation.
+ *
+ *
+ * @return the status of the validation
+ */
+ protected IStatus packageChanged() {
+ StatusInfo status = new StatusInfo();
+ fPackageDialogField.enableButton(getPackageFragmentRoot() != null);
+
+ // String packName= getPackageText();
+ // if (packName.length() > 0) {
+ // IStatus val= JavaConventions.validatePackageName(packName);
+ // if (val.getSeverity() == IStatus.ERROR) {
+ // status.setError(NewWizardMessages.getFormattedString("NewTypeWizardPage.error.InvalidPackageName",
+ // val.getMessage())); //$NON-NLS-1$
+ // return status;
+ // } else if (val.getSeverity() == IStatus.WARNING) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.DiscouragedPackageName",
+ // val.getMessage())); //$NON-NLS-1$
+ // // continue
+ // }
+ // }
+
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ // if (root != null) {
+ // if (root.getJavaProject().exists() && packName.length() > 0) {
+ // try {
+ // IPath rootPath= root.getPath();
+ // IPath outputPath= root.getJavaProject().getOutputLocation();
+ // if (rootPath.isPrefixOf(outputPath) && !rootPath.equals(outputPath))
+ // {
+ // // if the bin folder is inside of our root, dont allow to name a
+ // package
+ // // like the bin folder
+ // IPath packagePath= rootPath.append(packName.replace('.', '/'));
+ // if (outputPath.isPrefixOf(packagePath)) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.ClashOutputLocation"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ // }
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e);
+ // // let pass
+ // }
+ // }
+ //
+ // fCurrPackage= root.getPackageFragment(packName);
+ // } else {
+ // status.setError(""); //$NON-NLS-1$
+ // }
+ return status;
+ }
+
+ /*
+ * Updates the 'default' label next to the package field.
+ */
+ private void updatePackageStatusLabel() {
+ String packName = getPackageText();
+
+ if (packName.length() == 0) {
+ fPackageDialogField.setStatus(NewWizardMessages
+ .getString("NewTypeWizardPage.default")); //$NON-NLS-1$
+ } else {
+ fPackageDialogField.setStatus(""); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * Updates the enable state of buttons related to the enclosing type
+ * selection checkbox.
+ */
+ private void updateEnableState() {
+ boolean enclosing = isEnclosingTypeSelected();
+ fPackageDialogField.setEnabled(fCanModifyPackage && !enclosing);
+ fEnclosingTypeDialogField.setEnabled(fCanModifyEnclosingType
+ && enclosing);
+ }
+
+ /**
+ * Hook method that gets called when the enclosing type name has changed.
+ * The method validates the enclosing type and returns the status of the
+ * validation. It also updates the enclosing type model.
+ *
+ * Subclasses may extend this method to perform their own validation.
+ *
+ *
+ * @return the status of the validation
+ */
+ // protected IStatus enclosingTypeChanged() {
+ // StatusInfo status= new StatusInfo();
+ // fCurrEnclosingType= null;
+ //
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ //
+ // fEnclosingTypeDialogField.enableButton(root != null);
+ // if (root == null) {
+ // status.setError(""); //$NON-NLS-1$
+ // return status;
+ // }
+ //
+ // String enclName= getEnclosingTypeText();
+ // if (enclName.length() == 0) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingTypeEnterName"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ // try {
+ // IType type= findType(root.getJavaProject(), enclName);
+ // if (type == null) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingTypeNotExists"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ //
+ // if (type.getCompilationUnit() == null) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingNotInCU"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ // if (!JavaModelUtil.isEditable(type.getCompilationUnit())) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingNotEditable"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ //
+ // fCurrEnclosingType= type;
+ // IPackageFragmentRoot enclosingRoot=
+ // JavaModelUtil.getPackageFragmentRoot(type);
+ // if (!enclosingRoot.equals(root)) {
+ // status.setWarning(NewWizardMessages.getString("NewTypeWizardPage.warning.EnclosingNotInSourceFolder"));
+ // //$NON-NLS-1$
+ // }
+ // return status;
+ // } catch (JavaModelException e) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingTypeNotExists"));
+ // //$NON-NLS-1$
+ // PHPeclipsePlugin.log(e);
+ // return status;
+ // }
+ // }
+ /**
+ * Hook method that gets called when the type name has changed. The method
+ * validates the type name and returns the status of the validation.
+ *
+ * Subclasses may extend this method to perform their own validation.
+ *
+ *
+ * @return the status of the validation
+ */
+ protected IStatus typeNameChanged() {
+ StatusInfo status = new StatusInfo();
+ String typeName = getTypeName();
+ // must not be empty
+ if (typeName.length() == 0) {
+ status.setError(NewWizardMessages
+ .getString("NewTypeWizardPage.error.EnterTypeName")); //$NON-NLS-1$
+ return status;
+ }
+ if (typeName.indexOf('.') != -1) {
+ status.setError(NewWizardMessages
+ .getString("NewTypeWizardPage.error.QualifiedName")); //$NON-NLS-1$
+ return status;
+ }
+ // IStatus val= JavaConventions.validateJavaTypeName(typeName);
+ // if (val.getSeverity() == IStatus.ERROR) {
+ // status.setError(NewWizardMessages.getFormattedString("NewTypeWizardPage.error.InvalidTypeName",
+ // val.getMessage())); //$NON-NLS-1$
+ // return status;
+ // } else if (val.getSeverity() == IStatus.WARNING) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.TypeNameDiscouraged",
+ // val.getMessage())); //$NON-NLS-1$
+ // // continue checking
+ // }
+
+ // must not exist
+ if (!isEnclosingTypeSelected()) {
+ IPackageFragment pack = getPackageFragment();
+ if (pack != null) {
+ ICompilationUnit cu = pack.getCompilationUnit(typeName
+ + ".java"); //$NON-NLS-1$
+ if (cu.getResource().exists()) {
+ status
+ .setError(NewWizardMessages
+ .getString("NewTypeWizardPage.error.TypeNameExists")); //$NON-NLS-1$
+ return status;
+ }
+ }
+ } else {
+ IType type = getEnclosingType();
+ if (type != null) {
+ IType member = type.getType(typeName);
+ if (member.exists()) {
+ status
+ .setError(NewWizardMessages
+ .getString("NewTypeWizardPage.error.TypeNameExists")); //$NON-NLS-1$
+ return status;
+ }
+ }
+ }
+ return status;
+ }
+
+ /**
+ * Hook method that gets called when the superclass name has changed. The
+ * method validates the superclass name and returns the status of the
+ * validation.
+ *
+ * Subclasses may extend this method to perform their own validation.
+ *
+ *
+ * @return the status of the validation
+ */
+ // protected IStatus superClassChanged() {
+ // StatusInfo status= new StatusInfo();
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ // fSuperClassDialogField.enableButton(root != null);
+ //
+ // fSuperClass= null;
+ //
+ // String sclassName= getSuperClass();
+ // if (sclassName.length() == 0) {
+ // // accept the empty field (stands for java.lang.Object)
+ // return status;
+ // }
+ // IStatus val= JavaConventions.validateJavaTypeName(sclassName);
+ // if (val.getSeverity() == IStatus.ERROR) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.InvalidSuperClassName"));
+ // //$NON-NLS-1$
+ // return status;
+ // }
+ // if (root != null) {
+ // try {
+ // IType type= resolveSuperTypeName(root.getJavaProject(), sclassName);
+ // if (type == null) {
+ // status.setWarning(NewWizardMessages.getString("NewTypeWizardPage.warning.SuperClassNotExists"));
+ // //$NON-NLS-1$
+ // return status;
+ // } else {
+ // if (type.isInterface()) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.SuperClassIsNotClass",
+ // sclassName)); //$NON-NLS-1$
+ // return status;
+ // }
+ // int flags= type.getFlags();
+ // if (Flags.isFinal(flags)) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.SuperClassIsFinal",
+ // sclassName)); //$NON-NLS-1$
+ // return status;
+ // } else if (!JavaModelUtil.isVisible(type, getPackageFragment())) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.SuperClassIsNotVisible",
+ // sclassName)); //$NON-NLS-1$
+ // return status;
+ // }
+ // }
+ // fSuperClass= type;
+ // } catch (JavaModelException e) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.InvalidSuperClassName"));
+ // //$NON-NLS-1$
+ // PHPeclipsePlugin.log(e);
+ // }
+ // } else {
+ // status.setError(""); //$NON-NLS-1$
+ // }
+ // return status;
+ //
+ // }
+ // private IType resolveSuperTypeName(IJavaProject jproject, String
+ // sclassName) throws JavaModelException {
+ // if (!jproject.exists()) {
+ // return null;
+ // }
+ // IType type= null;
+ // if (isEnclosingTypeSelected()) {
+ // // search in the context of the enclosing type
+ // IType enclosingType= getEnclosingType();
+ // if (enclosingType != null) {
+ // String[][] res= enclosingType.resolveType(sclassName);
+ // if (res != null && res.length > 0) {
+ // type= jproject.findType(res[0][0], res[0][1]);
+ // }
+ // }
+ // } else {
+ // IPackageFragment currPack= getPackageFragment();
+ // if (type == null && currPack != null) {
+ // String packName= currPack.getElementName();
+ // // search in own package
+ // if (!currPack.isDefaultPackage()) {
+ // type= jproject.findType(packName, sclassName);
+ // }
+ // // search in java.lang
+ // if (type == null && !"java.lang".equals(packName)) { //$NON-NLS-1$
+ // type= jproject.findType("java.lang", sclassName); //$NON-NLS-1$
+ // }
+ // }
+ // // search fully qualified
+ // if (type == null) {
+ // type= jproject.findType(sclassName);
+ // }
+ // }
+ // return type;
+ // }
+ // private IType findType(IJavaProject project, String typeName) throws
+ // JavaModelException {
+ // if (project.exists()) {
+ // return project.findType(typeName);
+ // }
+ // return null;
+ // }
+ /**
+ * Hook method that gets called when the list of super interface has
+ * changed. The method validates the superinterfaces and returns the status
+ * of the validation.
+ *
+ * Subclasses may extend this method to perform their own validation.
+ *
+ *
+ * @return the status of the validation
+ */
+ // protected IStatus superInterfacesChanged() {
+ // StatusInfo status= new StatusInfo();
+ //
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ // fSuperInterfacesDialogField.enableButton(0, root != null);
+ //
+ // if (root != null) {
+ // List elements= fSuperInterfacesDialogField.getElements();
+ // int nElements= elements.size();
+ // for (int i= 0; i < nElements; i++) {
+ // String intfname= (String)elements.get(i);
+ // try {
+ // IType type= findType(root.getJavaProject(), intfname);
+ // if (type == null) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.InterfaceNotExists",
+ // intfname)); //$NON-NLS-1$
+ // return status;
+ // } else {
+ // if (type.isClass()) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.InterfaceIsNotInterface",
+ // intfname)); //$NON-NLS-1$
+ // return status;
+ // }
+ // if (!JavaModelUtil.isVisible(type, getPackageFragment())) {
+ // status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.InterfaceIsNotVisible",
+ // intfname)); //$NON-NLS-1$
+ // return status;
+ // }
+ // }
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e);
+ // // let pass, checking is an extra
+ // }
+ // }
+ // }
+ // return status;
+ // }
+ /**
+ * Hook method that gets called when the modifiers have changed. The method
+ * validates the modifiers and returns the status of the validation.
+ *
+ * Subclasses may extend this method to perform their own validation.
+ *
+ *
+ * @return the status of the validation
+ */
+ protected IStatus modifiersChanged() {
+ StatusInfo status = new StatusInfo();
+ int modifiers = getModifiers();
+ // if (Flags.isFinal(modifiers) && Flags.isAbstract(modifiers)) {
+ // status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.ModifiersFinalAndAbstract"));
+ // //$NON-NLS-1$
+ // }
+ return status;
+ }
+
+ // selection dialogs
+
+ // private IPackageFragment choosePackage() {
+ // IPackageFragmentRoot froot= getPackageFragmentRoot();
+ // IJavaElement[] packages= null;
+ // try {
+ // if (froot != null && froot.exists()) {
+ // packages= froot.getChildren();
+ // }
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e);
+ // }
+ // if (packages == null) {
+ // packages= new IJavaElement[0];
+ // }
+ //
+ // ElementListSelectionDialog dialog= new
+ // ElementListSelectionDialog(getShell(), new
+ // JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT));
+ // dialog.setIgnoreCase(false);
+ // dialog.setTitle(NewWizardMessages.getString("NewTypeWizardPage.ChoosePackageDialog.title"));
+ // //$NON-NLS-1$
+ // dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.ChoosePackageDialog.description"));
+ // //$NON-NLS-1$
+ // dialog.setEmptyListMessage(NewWizardMessages.getString("NewTypeWizardPage.ChoosePackageDialog.empty"));
+ // //$NON-NLS-1$
+ // dialog.setElements(packages);
+ // IPackageFragment pack= getPackageFragment();
+ // if (pack != null) {
+ // dialog.setInitialSelections(new Object[] { pack });
+ // }
+ //
+ // if (dialog.open() == ElementListSelectionDialog.OK) {
+ // return (IPackageFragment) dialog.getFirstResult();
+ // }
+ // return null;
+ // }
+
+ // private IType chooseEnclosingType() {
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ // if (root == null) {
+ // return null;
+ // }
+ //
+ // IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new
+ // IJavaElement[] { root });
+ //
+ // TypeSelectionDialog dialog= new TypeSelectionDialog(getShell(),
+ // getWizard().getContainer(), IJavaSearchConstants.TYPE, scope);
+ // dialog.setTitle(NewWizardMessages.getString("NewTypeWizardPage.ChooseEnclosingTypeDialog.title"));
+ // //$NON-NLS-1$
+ // dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.ChooseEnclosingTypeDialog.description"));
+ // //$NON-NLS-1$
+ // dialog.setFilter(Signature.getSimpleName(getEnclosingTypeText()));
+ //
+ // if (dialog.open() == TypeSelectionDialog.OK) {
+ // return (IType) dialog.getFirstResult();
+ // }
+ // return null;
+ // }
+
+ // private IType chooseSuperType() {
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ // if (root == null) {
+ // return null;
+ // }
+ //
+ // IJavaElement[] elements= new IJavaElement[] { root.getJavaProject() };
+ // IJavaSearchScope scope= SearchEngine.createJavaSearchScope(elements);
+ //
+ // TypeSelectionDialog dialog= new TypeSelectionDialog(getShell(),
+ // getWizard().getContainer(), IJavaSearchConstants.CLASS, scope);
+ // dialog.setTitle(NewWizardMessages.getString("NewTypeWizardPage.SuperClassDialog.title"));
+ // //$NON-NLS-1$
+ // dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.SuperClassDialog.message"));
+ // //$NON-NLS-1$
+ // dialog.setFilter(getSuperClass());
+ //
+ // if (dialog.open() == TypeSelectionDialog.OK) {
+ // return (IType) dialog.getFirstResult();
+ // }
+ // return null;
+ // }
+
+ // private void chooseSuperInterfaces() {
+ // IPackageFragmentRoot root= getPackageFragmentRoot();
+ // if (root == null) {
+ // return;
+ // }
+ //
+ // IJavaProject project= root.getJavaProject();
+ // SuperInterfaceSelectionDialog dialog= new
+ // SuperInterfaceSelectionDialog(getShell(), getWizard().getContainer(),
+ // fSuperInterfacesDialogField, project);
+ // dialog.setTitle(fIsClass ?
+ // NewWizardMessages.getString("NewTypeWizardPage.InterfacesDialog.class.title")
+ // :
+ // NewWizardMessages.getString("NewTypeWizardPage.InterfacesDialog.interface.title"));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.InterfacesDialog.message"));
+ // //$NON-NLS-1$
+ // dialog.open();
+ // return;
+ // }
+
+ // ---- creation ----------------
+
+ /**
+ * Creates the new type using the entered field values.
+ *
+ * @param monitor
+ * a progress monitor to report progress.
+ */
+ public void createType(IProgressMonitor monitor) throws CoreException,
+ InterruptedException {
+ if (monitor == null) {
+ monitor = new NullProgressMonitor();
+ }
+
+ monitor.beginTask(NewWizardMessages
+ .getString("NewTypeWizardPage.operationdesc"), 10); //$NON-NLS-1$
+ ICompilationUnit createdWorkingCopy = null;
+ try {
+ // IPackageFragmentRoot root = getPackageFragmentRoot();
+ // IPackageFragment pack = getPackageFragment();
+ // if (pack == null) {
+ // pack = root.getPackageFragment(""); //$NON-NLS-1$
+ // }
+ //
+ // if (!pack.exists()) {
+ // String packName = pack.getElementName();
+ // pack = root.createPackageFragment(packName, true, null);
+ // }
+
+ monitor.worked(1);
+
+ String clName = getTypeName();
+
+ boolean isInnerClass = isEnclosingTypeSelected();
+
+ IType createdType;
+ // ImportsStructure imports;
+ int indent = 0;
+
+ IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+ // String[] prefOrder =
+ // JavaPreferencesSettings.getImportOrderPreference(store);
+ // int threshold =
+ // JavaPreferencesSettings.getImportNumberThreshold(store);
+ //
+ String lineDelimiter = null;
+ // if (!isInnerClass) {
+ lineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ //
+ // ICompilationUnit parentCU = pack.createCompilationUnit(clName +
+ // ".php", "", false, new SubProgressMonitor(monitor, 2));
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // createdWorkingCopy = (ICompilationUnit)
+ // parentCU.getSharedWorkingCopy(null, JavaUI.getBufferFactory(),
+ // null);
+ //
+ // imports = new ImportsStructure(createdWorkingCopy, prefOrder,
+ // threshold, false);
+ // // add an import that will be removed again. Having this import
+ // solves 14661
+ // imports.addImport(pack.getElementName(), getTypeName());
+ //
+ String typeContent = constructTypeStub(lineDelimiter);// new
+ // ImportsManager(imports),
+ // lineDelimiter);
+
+ // String cuContent = constructCUContent(parentCU, typeContent,
+ // lineDelimiter);
+
+ // createdWorkingCopy.getBuffer().setContents(cuContent);
+ //
+ createdType = createdWorkingCopy.getType(clName);
+ // } else {
+ // IType enclosingType = getEnclosingType();
+ //
+ // // if we are working on a enclosed type that is open in an
+ // editor,
+ // // then replace the enclosing type with its working copy
+ // IType workingCopy = (IType)
+ // EditorUtility.getWorkingCopy(enclosingType);
+ // if (workingCopy != null) {
+ // enclosingType = workingCopy;
+ // }
+ //
+ // ICompilationUnit parentCU = enclosingType.getCompilationUnit();
+ // imports = new ImportsStructure(parentCU, prefOrder, threshold,
+ // true);
+ //
+ // // add imports that will be removed again. Having the imports
+ // solves 14661
+ // IType[] topLevelTypes = parentCU.getTypes();
+ // for (int i = 0; i < topLevelTypes.length; i++) {
+ // imports.addImport(topLevelTypes[i].getFullyQualifiedName('.'));
+ // }
+ //
+ // lineDelimiter = StubUtility.getLineDelimiterUsed(enclosingType);
+ // StringBuffer content = new StringBuffer();
+ // String comment = getTypeComment(parentCU);
+ // if (comment != null) {
+ // content.append(comment);
+ // content.append(lineDelimiter);
+ // }
+ // content.append(constructTypeStub(new ImportsManager(imports),
+ // lineDelimiter));
+ // IJavaElement[] elems = enclosingType.getChildren();
+ // IJavaElement sibling = elems.length > 0 ? elems[0] : null;
+ //
+ // createdType = enclosingType.createType(content.toString(),
+ // sibling, false, new SubProgressMonitor(monitor, 1));
+ //
+ // indent = StubUtility.getIndentUsed(enclosingType) + 1;
+ // }
+ //
+ // // add imports for superclass/interfaces, so types can be
+ // resolved correctly
+ // imports.create(false, new SubProgressMonitor(monitor, 1));
+ //
+ ICompilationUnit cu = createdType.getCompilationUnit();
+ synchronized (cu) {
+ cu.reconcile();
+ }
+ // createTypeMembers(createdType, new ImportsManager(imports), new
+ // SubProgressMonitor(monitor, 1));
+ //
+ // // add imports
+ // imports.create(false, new SubProgressMonitor(monitor, 1));
+
+ synchronized (cu) {
+ cu.reconcile();
+ }
+ ISourceRange range = createdType.getSourceRange();
+
+ IBuffer buf = cu.getBuffer();
+ String originalContent = buf.getText(range.getOffset(), range
+ .getLength());
+ String formattedContent = StubUtility.codeFormat(originalContent,
+ indent, lineDelimiter);
+ buf.replace(range.getOffset(), range.getLength(), formattedContent);
+ if (!isInnerClass) {
+ String fileComment = getFileComment(cu);
+ if (fileComment != null && fileComment.length() > 0) {
+ buf.replace(0, 0, fileComment + lineDelimiter);
+ }
+ cu.commit(false, new SubProgressMonitor(monitor, 1));
+ } else {
+ monitor.worked(1);
+ }
+ fCreatedType = createdType;
+ } finally {
+ if (createdWorkingCopy != null) {
+ createdWorkingCopy.destroy();
+ }
+ monitor.done();
+ }
+ }
+
+ /**
+ * Uses the New Java file template from the code template page to generate a
+ * compilation unit with the given type content.
+ *
+ * @param cu
+ * The new created compilation unit
+ * @param typeContent
+ * The content of the type, including signature and type body.
+ * @param lineDelimiter
+ * The line delimiter to be used.
+ * @return String Returns the result of evaluating the new file template
+ * with the given type content.
+ * @throws CoreException
+ * @since 2.1
+ */
+ // protected String constructCUContent(ICompilationUnit cu, String
+ // typeContent, String lineDelimiter) throws CoreException {
+ // StringBuffer typeQualifiedName= new StringBuffer();
+ // if (isEnclosingTypeSelected()) {
+ // typeQualifiedName.append(JavaModelUtil.getTypeQualifiedName(getEnclosingType())).append('.');
+ // }
+ // typeQualifiedName.append(getTypeName());
+ // String typeComment= CodeGeneration.getTypeComment(cu,
+ // typeQualifiedName.toString(), lineDelimiter);
+ // IPackageFragment pack= (IPackageFragment) cu.getParent();
+ // String content= CodeGeneration.getCompilationUnitContent(cu, typeComment,
+ // typeContent, lineDelimiter);
+ // if (content != null) {
+ // CompilationUnit unit= AST.parseCompilationUnit(content.toCharArray());
+ // if ((pack.isDefaultPackage() || unit.getPackage() != null) &&
+ // !unit.types().isEmpty()) {
+ // return content;
+ // }
+ // }
+ // StringBuffer buf= new StringBuffer();
+ // if (!pack.isDefaultPackage()) {
+ // buf.append("package ").append(pack.getElementName()).append(';');
+ // //$NON-NLS-1$
+ // }
+ // buf.append(lineDelimiter).append(lineDelimiter);
+ // if (typeComment != null) {
+ // buf.append(typeComment).append(lineDelimiter);
+ // }
+ // buf.append(typeContent);
+ // return buf.toString();
+ // }
+ /**
+ * Returns the created type. The method only returns a valid type after
+ * createType
has been called.
+ *
+ * @return the created type
+ * @see #createType(IProgressMonitor)
+ */
+ public IType getCreatedType() {
+ return fCreatedType;
+ }
+
+ // ---- construct cu body----------------
+
+ // private void writeSuperClass(StringBuffer buf, ImportsManager imports) {
+ // String typename= getSuperClass();
+ // if (fIsClass && typename.length() > 0 &&
+ // !"java.lang.Object".equals(typename)) { //$NON-NLS-1$
+ // buf.append(" extends "); //$NON-NLS-1$
+ //
+ // String qualifiedName= fSuperClass != null ?
+ // JavaModelUtil.getFullyQualifiedName(fSuperClass) : typename;
+ // buf.append(imports.addImport(qualifiedName));
+ // }
+ // }
+
+ // private void writeSuperInterfaces(StringBuffer buf, ImportsManager
+ // imports) {
+ // List interfaces= getSuperInterfaces();
+ // int last= interfaces.size() - 1;
+ // if (last >= 0) {
+ // if (fIsClass) {
+ // buf.append(" implements "); //$NON-NLS-1$
+ // } else {
+ // buf.append(" extends "); //$NON-NLS-1$
+ // }
+ // for (int i= 0; i <= last; i++) {
+ // String typename= (String) interfaces.get(i);
+ // buf.append(imports.addImport(typename));
+ // if (i < last) {
+ // buf.append(',');
+ // }
+ // }
+ // }
+ // }
+
+ /*
+ * Called from createType to construct the source for this type
+ */
+ private String constructTypeStub(String lineDelimiter) { // ImportsManager
+ // imports,
+ // String
+ // lineDelimiter)
+ // {
+ StringBuffer buf = new StringBuffer();
+
+ int modifiers = getModifiers();
+ buf.append(Flags.toString(modifiers));
+ if (modifiers != 0) {
+ buf.append(' ');
+ }
+ buf.append(fIsClass ? "class " : "interface "); //$NON-NLS-2$ //$NON-NLS-1$
+ buf.append(getTypeName());
+ // writeSuperClass(buf, imports);
+ // writeSuperInterfaces(buf, imports);
+ buf.append('{');
+ buf.append(lineDelimiter);
+ buf.append(lineDelimiter);
+ buf.append('}');
+ buf.append(lineDelimiter);
+ return buf.toString();
+ }
+
+ /**
+ * @deprecated Overwrite createTypeMembers(IType, IImportsManager,
+ * IProgressMonitor) instead
+ */
+ // protected void createTypeMembers(IType newType, IImportsStructure
+ // imports, IProgressMonitor monitor) throws CoreException {
+ // //deprecated
+ // }
+ /**
+ * Hook method that gets called from createType
to support
+ * adding of unanticipated methods, fields, and inner types to the created
+ * type.
+ *
+ * Implementers can use any methods defined on IType
to
+ * manipulate the new type.
+ *
+ *
+ * The source code of the new type will be formtted using the platform's
+ * formatter. Needed imports are added by the wizard at the end of the type
+ * creation process using the given import manager.
+ *
+ *
+ * @param newType
+ * the new type created via createType
+ * @param imports
+ * an import manager which can be used to add new imports
+ * @param monitor
+ * a progress monitor to report progress. Must not be
+ * null
+ *
+ * @see #createType(IProgressMonitor)
+ */
+ // protected void createTypeMembers(IType newType, ImportsManager imports,
+ // IProgressMonitor monitor) throws CoreException {
+ // // call for compatibility
+ // createTypeMembers(newType,
+ // ((ImportsManager)imports).getImportsStructure(), monitor);
+ //
+ // // default implementation does nothing
+ // // example would be
+ // // String mainMathod= "public void foo(Vector vec) {}"
+ // // createdType.createMethod(main, null, false, null);
+ // // imports.addImport("java.lang.Vector");
+ // }
+ /**
+ * @deprecated Instead of file templates, the new type code template
+ * specifies the stub for a compilation unit.
+ */
+ protected String getFileComment(ICompilationUnit parentCU) {
+ return null;
+ }
+
+ private boolean isValidComment(String template) {
+ IScanner scanner = ToolFactory.createScanner(true, false, false); // ,
+ // false);
+ scanner.setSource(template.toCharArray());
+ try {
+ int next = scanner.getNextToken();
+ while (next == ITerminalSymbols.TokenNameCOMMENT_LINE
+ || next == ITerminalSymbols.TokenNameCOMMENT_PHPDOC
+ || next == ITerminalSymbols.TokenNameCOMMENT_BLOCK) {
+ next = scanner.getNextToken();
+ }
+ return next == ITerminalSymbols.TokenNameEOF;
+ } catch (InvalidInputException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Hook method that gets called from createType
to retrieve a
+ * type comment. This default implementation returns the content of the
+ * 'typecomment' template.
+ *
+ * @return the type comment or null
if a type comment is not
+ * desired
+ */
+ protected String getTypeComment(ICompilationUnit parentCU) {
+ if (PreferenceConstants.getPreferenceStore().getBoolean(
+ PreferenceConstants.CODEGEN_ADD_COMMENTS)) {
+ try {
+ StringBuffer typeName = new StringBuffer();
+ if (isEnclosingTypeSelected()) {
+ typeName.append(
+ JavaModelUtil
+ .getTypeQualifiedName(getEnclosingType()))
+ .append('.');
+ }
+ typeName.append(getTypeName());
+ String comment = CodeGeneration.getTypeComment(parentCU,
+ typeName.toString(), String.valueOf('\n'));
+ if (comment != null && isValidComment(comment)) {
+ return comment;
+ }
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated Use getTemplate(String,ICompilationUnit,int)
+ */
+ protected String getTemplate(String name, ICompilationUnit parentCU) {
+ return getTemplate(name, parentCU, 0);
+ }
+
+ /**
+ * Returns the string resulting from evaluation the given template in the
+ * context of the given compilation unit. This accesses the normal template
+ * page, not the code templates. To use code templates use
+ * constructCUContent
to construct a compilation unit stub or
+ * getTypeComment for the comment of the type.
+ *
+ * @param name
+ * the template to be evaluated
+ * @param parentCU
+ * the templates evaluation context
+ * @param pos
+ * a source offset into the parent compilation unit. The template
+ * is evalutated at the given source offset
+ */
+ protected String getTemplate(String name, ICompilationUnit parentCU, int pos) {
+ try {
+ Template[] templates = Templates.getInstance().getTemplates(name);
+ if (templates.length > 0) {
+ return JavaContext
+ .evaluateTemplate(templates[0], parentCU, pos);
+ }
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ } catch (BadLocationException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ } catch (TemplateException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated Use
+ * createInheritedMethods(IType,boolean,boolean,IImportsManager,IProgressMonitor)
+ */
+ // protected IMethod[] createInheritedMethods(IType type, boolean
+ // doConstructors, boolean doUnimplementedMethods, IImportsStructure
+ // imports, IProgressMonitor monitor) throws CoreException {
+ // return createInheritedMethods(type, doConstructors,
+ // doUnimplementedMethods, new ImportsManager(imports), monitor);
+ // }
+ /**
+ * Creates the bodies of all unimplemented methods and constructors and adds
+ * them to the type. Method is typically called by implementers of
+ * NewTypeWizardPage
to add needed method and constructors.
+ *
+ * @param type
+ * the type for which the new methods and constructor are to be
+ * created
+ * @param doConstructors
+ * if true
unimplemented constructors are created
+ * @param doUnimplementedMethods
+ * if true
unimplemented methods are created
+ * @param imports
+ * an import manager to add all neded import statements
+ * @param monitor
+ * a progress monitor to report progress
+ */
+ // protected IMethod[] createInheritedMethods(IType type, boolean
+ // doConstructors, boolean doUnimplementedMethods, ImportsManager imports,
+ // IProgressMonitor monitor) throws CoreException {
+ // ArrayList newMethods= new ArrayList();
+ // ITypeHierarchy hierarchy= null;
+ // CodeGenerationSettings settings=
+ // JavaPreferencesSettings.getCodeGenerationSettings();
+ //
+ // if (doConstructors) {
+ // hierarchy= type.newSupertypeHierarchy(monitor);
+ // IType superclass= hierarchy.getSuperclass(type);
+ // if (superclass != null) {
+ // String[] constructors= StubUtility.evalConstructors(type, superclass,
+ // settings, imports.getImportsStructure());
+ // if (constructors != null) {
+ // for (int i= 0; i < constructors.length; i++) {
+ // newMethods.add(constructors[i]);
+ // }
+ // }
+ //
+ // }
+ // }
+ // if (doUnimplementedMethods) {
+ // if (hierarchy == null) {
+ // hierarchy= type.newSupertypeHierarchy(monitor);
+ // }
+ // String[] unimplemented= StubUtility.evalUnimplementedMethods(type,
+ // hierarchy, false, settings, null, imports.getImportsStructure());
+ // if (unimplemented != null) {
+ // for (int i= 0; i < unimplemented.length; i++) {
+ // newMethods.add(unimplemented[i]);
+ // }
+ // }
+ // }
+ // IMethod[] createdMethods= new IMethod[newMethods.size()];
+ // for (int i= 0; i < newMethods.size(); i++) {
+ // String content= (String) newMethods.get(i) + '\n'; // content will be
+ // formatted, ok to use \n
+ // createdMethods[i]= type.createMethod(content, null, false, null);
+ // }
+ // return createdMethods;
+ // }
+ // ---- creation ----------------
+ /**
+ * Returns the runnable that creates the type using the current settings.
+ * The returned runnable must be executed in the UI thread.
+ *
+ * @return the runnable to create the new type
+ */
+ // public IRunnableWithProgress getRunnable() {
+ // return new IRunnableWithProgress() {
+ // public void run(IProgressMonitor monitor) throws
+ // InvocationTargetException, InterruptedException {
+ // try {
+ // if (monitor == null) {
+ // monitor= new NullProgressMonitor();
+ // }
+ // createType(monitor);
+ // } catch (CoreException e) {
+ // throw new InvocationTargetException(e);
+ // }
+ // }
+ // };
+ // }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/IncludesScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/IncludesScanner.java
new file mode 100644
index 0000000..3858ed8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/IncludesScanner.java
@@ -0,0 +1,183 @@
+package net.sourceforge.phpeclipse.actions;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.ui.IFileEditorInput;
+
+public class IncludesScanner implements ITerminalSymbols {
+ // private final PHPOpenAllIncludesEditorAction fOpenAllIncludesAction;
+ private IProject fProject;
+
+ private IFileEditorInput fEditorInput;
+
+ private HashSet fSet;
+
+ public IncludesScanner(IProject project, IFileEditorInput editorInput) {
+ fProject = project;
+ // fOpenAllIncludesAction = action;
+ fEditorInput = editorInput;
+ fSet = new HashSet();
+ }
+
+ /**
+ * Add the information for a given IFile resource
+ *
+ */
+ public void addFile(IFile fileToParse) {
+
+ try {
+ if (fileToParse.exists()) {
+ addInputStream(new BufferedInputStream(fileToParse
+ .getContents()), fileToParse.getProjectRelativePath()
+ .toString());
+ }
+ } catch (CoreException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ private void addInputStream(InputStream stream, String filePath)
+ throws CoreException {
+ try {
+ if (fSet.add(filePath)) { // new entry in set
+ parseIdentifiers(Util.getInputStreamAsCharArray(stream, -1,
+ null));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ /**
+ * Get the next token from input
+ */
+ private int getNextToken(Scanner scanner) {
+ int token;
+ try {
+ token = scanner.getNextToken();
+ if (Scanner.DEBUG) {
+ int currentEndPosition = scanner.getCurrentTokenEndPosition();
+ int currentStartPosition = scanner
+ .getCurrentTokenStartPosition();
+ System.out.print(currentStartPosition + ","
+ + currentEndPosition + ": ");
+ System.out.println(scanner.toStringAction(token));
+ }
+ return token;
+ } catch (InvalidInputException e) {
+ }
+ return TokenNameERROR;
+ }
+
+ private void parseIdentifiers(char[] charArray) {
+ IFile file;
+ Scanner scanner = new Scanner(false, false, false, false, true, null,
+ null, true /* taskCaseSensitive */);
+ scanner.setSource(charArray);
+ scanner.setPHPMode(false);
+ int token = getNextToken(scanner);
+ try {
+ while (token != TokenNameEOF) { // && fToken != TokenNameERROR) {
+ if (token == TokenNameinclude || token == TokenNameinclude_once
+ || token == TokenNamerequire
+ || token == TokenNamerequire_once) {
+ while (token != TokenNameEOF && token != TokenNameERROR
+ && token != TokenNameSEMICOLON
+ && token != TokenNameRPAREN
+ && token != TokenNameLBRACE
+ && token != TokenNameRBRACE) {
+ token = getNextToken(scanner);
+ if (token == TokenNameStringDoubleQuote
+ || token == TokenNameStringSingleQuote) {
+ char[] includeName = scanner
+ .getCurrentStringLiteralSource();
+ try {
+ System.out.println(includeName);
+ file = getIncludeFile(new String(includeName));
+ addFile(file);
+ } catch (Exception e) {
+ // ignore
+ }
+ break;
+ }
+ }
+ }
+ token = getNextToken(scanner);
+ }
+ } catch (SyntaxError e) {
+ // e.printStackTrace();
+ }
+ }
+
+ private IContainer getWorkingLocation(IFileEditorInput editorInput) {
+ if (editorInput == null || editorInput.getFile() == null) {
+ return null;
+ }
+ return editorInput.getFile().getParent();
+ }
+
+ public IFile getIncludeFile(String relativeFilename) {
+ IContainer container = getWorkingLocation(fEditorInput);
+ IFile file = null;
+ if (relativeFilename.startsWith("../")) {
+ Path path = new Path(relativeFilename);
+ file = container.getFile(path);
+ return file;
+ }
+ int index = relativeFilename.lastIndexOf('/');
+
+ if (index >= 0) {
+ Path path = new Path(relativeFilename);
+ file = fProject.getFile(path);
+ if (file.exists()) {
+ return file;
+ }
+ }
+ Path path = new Path(relativeFilename);
+ file = container.getFile(path);
+
+ return file;
+ }
+
+ /**
+ * Returns a list of includes
+ *
+ * @return the determined list of includes
+ */
+ public List getList() {
+ ArrayList list = new ArrayList();
+ list.addAll(fSet);
+ return list;
+ }
+
+ /**
+ * @return Returns the set.
+ */
+ public Set getSet() {
+ return fSet;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/OpenDeclarationEditorAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/OpenDeclarationEditorAction.java
new file mode 100644
index 0000000..7492195
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/OpenDeclarationEditorAction.java
@@ -0,0 +1,308 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: www.phpeclipse.de
+ **********************************************************************************************************************************/
+package net.sourceforge.phpeclipse.actions;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ListContentProvider;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+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.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.dialogs.ListSelectionDialog;
+
+public class OpenDeclarationEditorAction {
+
+ private PHPEditor fEditor;
+
+ private IProject fProject;
+
+ private boolean isIncludeString;
+
+ public OpenDeclarationEditorAction(PHPEditor editor) {
+ fEditor = editor;
+ fProject = null;
+ isIncludeString = false;
+ }
+
+ /**
+ * @param selection
+ */
+ protected void openSelectedElement(ITextSelection selection) {
+ IDocument doc = fEditor.getDocumentProvider().getDocument(
+ fEditor.getEditorInput());
+ int pos = selection.getOffset();
+ openSelectedPosition(doc, pos);
+ }
+
+ protected void openSelectedPosition(IDocument doc, int position) {
+ IFile f = ((IFileEditorInput) fEditor.getEditorInput()).getFile();
+ fProject = f.getProject();
+ // System.out.println(selection.getText());
+ String identifierOrInclude = getIdentifierOrInclude(doc, position);
+ // System.out.println(word);
+ if (identifierOrInclude != null && !identifierOrInclude.equals("")) {
+ if (isIncludeString) {
+ openIncludeFile(identifierOrInclude);
+ } else {
+ openIdentifierDeclaration(f, identifierOrInclude);
+ }
+ }
+ }
+
+ /**
+ * @param filename
+ */
+ private void openIncludeFile(String filename) {
+ if (filename != null && !filename.equals("")) {
+ try {
+ IFile currentFile = ((IFileEditorInput) fEditor
+ .getEditorInput()).getFile();
+ IPath path = PHPFileUtil.determineFilePath(filename,
+ currentFile, fProject);
+ if (path != null) {
+ //IFile file = PHPFileUtil.createFile(path, fProject);
+ //if (file != null && file.exists()) {
+ // PHPeclipsePlugin.getDefault().openFileInTextEditor(
+ // file.getLocation().toString());
+ // return;
+ //}
+ WebUI.getDefault().openFileInTextEditor(
+ path.toString());
+ return;
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+
+ try {
+
+ IdentifierIndexManager indexManager = WebUI
+ .getDefault().getIndexManager(fProject);
+ // filename = StringUtil.replaceRegExChars(filename);
+ List list = indexManager.getFileList(filename);
+ if (list != null && list.size() > 0) {
+ // String workspaceLocation =
+ // PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
+ String workspaceLocation = fProject.getFullPath()
+ .toString()
+ + java.io.File.separatorChar;
+
+ ListSelectionDialog listSelectionDialog = new ListSelectionDialog(
+ WebUI.getDefault().getWorkbench()
+ .getActiveWorkbenchWindow().getShell(),
+ list, new ListContentProvider(),
+ new LabelProvider(), "Select the includes to open.");
+ listSelectionDialog.setTitle("Multiple includes found");
+ if (listSelectionDialog.open() == Window.OK) {
+ Object[] locations = listSelectionDialog.getResult();
+ if (locations != null) {
+ try {
+ for (int i = 0; i < locations.length; i++) {
+ // PHPIdentifierLocation location =
+ // (PHPIdentifierLocation)
+ // locations[i];
+ String openFilename = workspaceLocation
+ + ((String) locations[i]);
+ WebUI.getDefault()
+ .openFileInTextEditor(openFilename);
+ }
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+ } catch (Exception e) {
+ }
+
+ }
+ return;
+ }
+
+ /**
+ * @param f
+ * @param identiifer
+ */
+ private void openIdentifierDeclaration(IFile f, String identiifer) {
+ if (identiifer != null && !identiifer.equals("")) {
+ IdentifierIndexManager indexManager = WebUI.getDefault()
+ .getIndexManager(fProject);
+ List locationsList = indexManager.getLocations(identiifer);
+ if (locationsList != null && locationsList.size() > 0) {
+
+ // String workspaceLocation =
+ // PHPeclipsePlugin.getWorkspace().getRoot()
+ // .getLocation().toString();
+
+ String workspaceLocation = fProject.getFullPath().toString()
+ + java.io.File.separatorChar;
+ // TODO show all entries of the list in a dialog box
+ // at the moment always the first entry will be opened
+ if (locationsList.size() > 1) {
+ // determine all includes:
+ IncludesScanner includesScanner = new IncludesScanner(
+ fProject, (IFileEditorInput) fEditor
+ .getEditorInput());
+ includesScanner.addFile(f);
+ Set exactIncludeSet = includesScanner.getSet();
+
+ PHPIdentifierLocation includeName;
+ for (int i = 0; i < locationsList.size(); i++) {
+ includeName = (PHPIdentifierLocation) locationsList
+ .get(i);
+ if (exactIncludeSet.contains(includeName.getFilename())) {
+ includeName
+ .setMatch(PHPIdentifierLocation.EXACT_MATCH);
+ } else {
+ includeName
+ .setMatch(PHPIdentifierLocation.UNDEFINED_MATCH);
+ }
+ }
+ Collections.sort(locationsList);
+
+ ListSelectionDialog listSelectionDialog = new ListSelectionDialog(
+ WebUI.getDefault().getWorkbench()
+ .getActiveWorkbenchWindow().getShell(),
+ locationsList, new ListContentProvider(),
+ new LabelProvider(),
+ "Select the resources to open.");
+ listSelectionDialog.setTitle("Multiple declarations found");
+ if (listSelectionDialog.open() == Window.OK) {
+ Object[] locations = listSelectionDialog.getResult();
+ if (locations != null) {
+ try {
+ for (int i = 0; i < locations.length; i++) {
+ PHPIdentifierLocation location = (PHPIdentifierLocation) locations[i];
+ String filename = workspaceLocation
+ + location.getFilename();
+ // System.out.println(filename);
+ if (location.getOffset() >= 0) {
+ WebUI.getDefault()
+ .openFileAndGotoOffset(
+ filename,
+ location.getOffset(),
+ identiifer.length());
+ } else {
+ WebUI.getDefault()
+ .openFileAndFindString(
+ filename, identiifer);
+ }
+ }
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ } else {
+ try {
+ PHPIdentifierLocation location = (PHPIdentifierLocation) locationsList
+ .get(0);
+ String filename = workspaceLocation
+ + location.getFilename();
+ // System.out.println(filename);
+ if (location.getOffset() >= 0) {
+ WebUI.getDefault()
+ .openFileAndGotoOffset(filename,
+ location.getOffset(),
+ identiifer.length());
+ } else {
+ WebUI
+ .getDefault()
+ .openFileAndFindString(filename, identiifer);
+ }
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ private String getIdentifierOrInclude(IDocument doc, int pos) {
+ // private String getPHPIncludeText(IDocument doc, int pos) {
+ Point word = null;
+ int start = -1;
+ int end = -1;
+ isIncludeString = false;
+ try {
+ // try to find an include string
+ int position = pos;
+ char character = ' ';
+
+ while (position >= 0) {
+ character = doc.getChar(position);
+ if ((character == '\"') || (character == '\'')
+ || (character == '\r') || (character == '\n'))
+ break;
+ --position;
+ }
+ if ((character == '\"') || (character == '\'')) {
+ start = position;
+
+ position = pos;
+ int length = doc.getLength();
+ character = ' ';
+ while (position < length) {
+ character = doc.getChar(position);
+ if ((character == '\"') || (character == '\'')
+ || (character == '\r') || (character == '\n'))
+ break;
+ ++position;
+ }
+ if ((character == '\"') || (character == '\'')) {
+ start++;
+ end = position;
+
+ if (end > start) {
+ word = new Point(start, end - start); // include name
+ // found
+ isIncludeString = true;
+ }
+ }
+ }
+
+ // try to find an identifier
+ if (word == null) {
+ word = PHPWordExtractor.findWord(doc, pos); // identifier found
+ isIncludeString = false;
+ }
+ } catch (BadLocationException x) {
+ }
+
+ if (word != null) {
+ try {
+ return doc.get(word.x, word.y);
+ } catch (BadLocationException e) {
+ }
+ }
+ return "";
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPActionMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPActionMessages.java
new file mode 100644
index 0000000..7851c84
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPActionMessages.java
@@ -0,0 +1,31 @@
+/*
+ * (c) Copyright Improve S.A., 2002.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpeclipse.actions;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class PHPActionMessages {
+
+ private static final String RESOURCE_BUNDLE = "net.sourceforge.phpeclipse.actions.PHPActionMessages";//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private PHPActionMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+
+ public static ResourceBundle getResourceBundle() {
+ return fgResourceBundle;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPActionMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPActionMessages.properties
new file mode 100644
index 0000000..417a814
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPActionMessages.properties
@@ -0,0 +1,4 @@
+## Actions
+
+PHPStartApacheAction.consoleViewOpeningProblem=A problem occured while opening the PHP console view
+
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPEclipseShowAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPEclipseShowAction.java
new file mode 100644
index 0000000..d9f7db6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPEclipseShowAction.java
@@ -0,0 +1,160 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - Initial implementation
+ * www.phpeclipse.de
+ **********************************************************************************************************************************/
+package net.sourceforge.phpeclipse.actions;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.IPreferenceConstants;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.editor.ShowExternalPreviewAction;
+import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.internal.BrowserManager;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IActionDelegate;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class PHPEclipseShowAction implements IObjectActionDelegate {
+ private IWorkbenchPart workbenchPart;
+
+ /**
+ * Constructor for Action1.
+ */
+ public PHPEclipseShowAction() {
+ super();
+ }
+
+ /**
+ * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ workbenchPart = targetPart;
+ }
+
+ public void run(IAction action) {
+ ISelectionProvider selectionProvider = null;
+ selectionProvider = workbenchPart.getSite().getSelectionProvider();
+ StructuredSelection selection = null;
+ selection = (StructuredSelection) selectionProvider.getSelection();
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ Shell shell = null;
+ Iterator iterator = null;
+ iterator = selection.iterator();
+ while (iterator.hasNext()) {
+ // obj => selected object in the view
+ Object obj = iterator.next();
+ // is it a resource
+ if (obj instanceof IResource) {
+ IResource resource = (IResource) obj;
+ // check if it's a file resource
+ switch (resource.getType()) {
+ case IResource.FILE:
+ // single file:
+ IFile previewFile = (IFile) resource;
+ String extension = previewFile.getFileExtension()
+ .toLowerCase();
+ boolean bringToTopPreview = ProjectPrefUtil
+ .getPreviewBooleanValue(
+ previewFile,
+ IPreferenceConstants.PHP_BRING_TO_TOP_PREVIEW_DEFAULT);
+ // boolean showHTMLFilesLocal =
+ // ProjectPrefUtil.getPreviewBooleanValue(previewFile,
+ // IPreferenceConstants.PHP_SHOW_HTML_FILES_LOCAL);
+ // boolean showXMLFilesLocal =
+ // ProjectPrefUtil.getPreviewBooleanValue(previewFile,
+ // IPreferenceConstants.PHP_SHOW_XML_FILES_LOCAL);
+ boolean isHTMLFileName = "html".equals(extension)
+ || "htm".equals(extension)
+ || "xhtml".equals(extension);
+ boolean isXMLFileName = "xml".equals(extension)
+ || "xsd".equals(extension)
+ || "dtd".equals(extension);
+
+ String localhostURL;
+ // if (showHTMLFilesLocal && isHTMLFileName) {
+ // localhostURL =
+ // "file://"+previewFile.getLocation().toString();
+ // } else if (showXMLFilesLocal && isXMLFileName) {
+ // localhostURL =
+ // "file://"+previewFile.getLocation().toString();
+ // } else
+ if ((localhostURL = ShowExternalPreviewAction
+ .getLocalhostURL(store, previewFile)) == null) {
+ MessageDialog
+ .openInformation(shell,
+ "Couldn't create localhost URL",
+ "Please configure your localhost and documentRoot");
+ return;
+ }
+
+ try {
+ // if
+ // (store.getBoolean(PHPeclipsePlugin.USE_EXTERNAL_BROWSER_PREF))
+ // {
+ // String[] arguments = { localhostURL };
+ // MessageFormat form = new
+ // MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_BROWSER_PREF));
+ // Runtime runtime = Runtime.getRuntime();
+ // String command = form.format(arguments);
+ // // console.write("External Browser command: " +
+ // command + "\n");
+ // runtime.exec(command);
+ // } else {
+ open(new URL(localhostURL), shell, localhostURL);
+ // }
+ } catch (MalformedURLException e) {
+ MessageDialog.openInformation(shell,
+ "MalformedURLException: ", e.toString());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @see IActionDelegate#selectionChanged(IAction, ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+ public static void open(final URL url, final Shell shell,
+ final String dialogTitle) {
+ // if (WebBrowserUtil.canUseInternalWebBrowser()) {
+ // IWorkbenchPage page = PHPeclipsePlugin.getActivePage();
+ // try {
+ // IViewPart part = page.findView(BrowserView.ID_BROWSER);
+ // if (part == null) {
+ // part = page.showView(BrowserView.ID_BROWSER);
+ // } else {
+ // page.bringToTop(part);
+ // }
+ // ((BrowserView) part).setUrl(url.toExternalForm());
+ // } catch (Exception e) {
+ // }
+ // } else {
+ BrowserManager manager = BrowserManager.getInstance();
+ IWebBrowser browser = manager.getCurrentWebBrowser();
+ browser.openURL(url);
+ // }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenAllIncludesEditorAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenAllIncludesEditorAction.java
new file mode 100644
index 0000000..86d2090
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenAllIncludesEditorAction.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Common Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: www.phpeclipse.de
+ ******************************************************************************/
+package net.sourceforge.phpeclipse.actions;
+
+import java.io.File;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.viewsupport.ListContentProvider;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionDelegate;
+import org.eclipse.ui.dialogs.ListSelectionDialog;
+
+public class PHPOpenAllIncludesEditorAction extends ActionDelegate implements
+ IEditorActionDelegate {
+
+ private IWorkbenchWindow fWindow;
+
+ private PHPEditor fEditor;
+
+ private IProject fProject;
+
+ private IncludesScanner fIncludesScanner;
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ this.fWindow = window;
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (!selection.isEmpty()) {
+ if (selection instanceof TextSelection) {
+ action.setEnabled(true);
+ } else if (fWindow.getActivePage() != null
+ && fWindow.getActivePage().getActivePart() != null) {
+ //
+ }
+ }
+ }
+
+ private IWorkbenchPage getActivePage() {
+ IWorkbenchWindow workbenchWindow = fEditor.getEditorSite()
+ .getWorkbenchWindow();
+ IWorkbenchPage page = workbenchWindow.getActivePage();
+ return page;
+ }
+
+ public IContainer getWorkingLocation(IFileEditorInput editorInput) {
+ if (editorInput == null || editorInput.getFile() == null) {
+ return null;
+ }
+ return editorInput.getFile().getParent();
+ }
+
+ private IFile getIncludeFile(IProject project,
+ IFileEditorInput editorInput, String relativeFilename) {
+ IContainer container = getWorkingLocation(editorInput);
+ String fullPath = project.getFullPath().toString();
+ IFile file = null;
+ if (relativeFilename.startsWith("../")) {
+ Path path = new Path(relativeFilename);
+ file = container.getFile(path);
+ return file;
+ }
+ int index = relativeFilename.lastIndexOf('/');
+
+ if (index >= 0) {
+ Path path = new Path(relativeFilename);
+ file = project.getFile(path);
+ if (file.exists()) {
+ return file;
+ }
+ }
+
+ Path path = new Path(relativeFilename);
+ file = container.getFile(path);
+
+ return file;
+ }
+
+ public void run(IAction action) {
+ if (fEditor == null) {
+ IEditorPart targetEditor = fWindow.getActivePage()
+ .getActiveEditor();
+ if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+ fEditor = (PHPEditor) targetEditor;
+ }
+ }
+ if (fEditor != null) {
+ // determine the current Project from a (file-based) Editor
+ IFile f = ((IFileEditorInput) fEditor.getEditorInput()).getFile();
+ fProject = f.getProject();
+ // System.out.println(fProject.toString());
+
+ ITextSelection selection = (ITextSelection) fEditor
+ .getSelectionProvider().getSelection();
+ IDocument doc = fEditor.getDocumentProvider().getDocument(
+ fEditor.getEditorInput());
+ fIncludesScanner = new IncludesScanner(fProject,
+ (IFileEditorInput) fEditor.getEditorInput());
+ int pos = selection.getOffset();
+ // System.out.println(selection.getText());
+ String filename = getPHPIncludeText(doc, pos);
+
+ if (filename != null && !filename.equals("")) {
+ try {
+ IFile file = fIncludesScanner.getIncludeFile(filename);
+ fIncludesScanner.addFile(file);
+ } catch (Exception e) {
+ // ignore
+ }
+
+ try {
+
+ List list = fIncludesScanner.getList();
+ if (list != null && list.size() > 0) {
+ // String workspaceLocation =
+ // PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
+ String workspaceLocation = fProject.getFullPath()
+ .toString()
+ + File.separatorChar;
+
+ ListSelectionDialog listSelectionDialog = new ListSelectionDialog(
+ WebUI.getDefault().getWorkbench()
+ .getActiveWorkbenchWindow().getShell(),
+ list, new ListContentProvider(),
+ new LabelProvider(),
+ "Select the includes to open.");
+ listSelectionDialog.setTitle("Multiple includes found");
+ if (listSelectionDialog.open() == Window.OK) {
+ Object[] locations = listSelectionDialog
+ .getResult();
+ if (locations != null) {
+ try {
+ for (int i = 0; i < locations.length; i++) {
+ // PHPIdentifierLocation location =
+ // (PHPIdentifierLocation)
+ // locations[i];
+ String openFilename = workspaceLocation
+ + ((String) locations[i]);
+ WebUI.getDefault()
+ .openFileInTextEditor(
+ openFilename);
+ }
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+ } catch (Exception e) {
+ }
+
+ }
+ }
+ }
+
+ public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+ if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+ fEditor = (PHPEditor) targetEditor;
+ }
+ }
+
+ private String getPHPIncludeText(IDocument doc, int pos) {
+ Point word = null;
+ int start = -1;
+ int end = -1;
+
+ try {
+
+ int position = pos;
+ char character;
+
+ while (position >= 0) {
+ character = doc.getChar(position);
+ if ((character == '\"') || (character == '\'')
+ || (character == '\r') || (character == '\n'))
+ break;
+ --position;
+ }
+
+ start = position;
+
+ position = pos;
+ int length = doc.getLength();
+
+ while (position < length) {
+ character = doc.getChar(position);
+ if ((character == '\"') || (character == '\'')
+ || (character == '\r') || (character == '\n'))
+ break;
+ ++position;
+ }
+
+ start++;
+ end = position;
+
+ if (end > start)
+ word = new Point(start, end - start);
+
+ } catch (BadLocationException x) {
+ }
+
+ if (word != null) {
+ try {
+ return doc.get(word.x, word.y);
+ } catch (BadLocationException e) {
+ }
+ }
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenDeclarationAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenDeclarationAction.java
new file mode 100644
index 0000000..47edccb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenDeclarationAction.java
@@ -0,0 +1,113 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: www.phpeclipse.de
+ **********************************************************************************************************************************/
+package net.sourceforge.phpeclipse.actions;
+
+import net.sourceforge.phpdt.internal.ui.actions.ActionUtil;
+import net.sourceforge.phpdt.internal.ui.actions.SelectionConverter;
+import net.sourceforge.phpdt.ui.actions.SelectionDispatchAction;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.IWorkbenchWindow;
+
+public class PHPOpenDeclarationAction extends SelectionDispatchAction {
+ private IWorkbenchWindow fWindow;
+
+ private PHPEditor fEditor;
+
+ public void dispose() {
+ }
+
+ public PHPOpenDeclarationAction(IWorkbenchSite site) {
+ super(site);
+ // setText(ActionMessages.getString("OpenAction.label")); //$NON-NLS-1$
+ // setToolTipText(ActionMessages.getString("OpenAction.tooltip"));
+ // //$NON-NLS-1$
+ // setDescription(ActionMessages.getString("OpenAction.description"));
+ // //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(this, IJavaHelpContextIds.OPEN_ACTION);
+ }
+
+ /**
+ * Note: This constructor is for internal use only. Clients should not call
+ * this constructor.
+ */
+ public PHPOpenDeclarationAction(PHPEditor editor) {
+ this(editor.getEditorSite());
+ fEditor = editor;
+ // setText(ActionMessages.getString("OpenAction.declaration.label"));
+ // //$NON-NLS-1$
+ setEnabled(SelectionConverter.canOperateOn(fEditor));
+ }
+
+ public void init(IWorkbenchWindow window) {
+ this.fWindow = window;
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (!selection.isEmpty()) {
+ if (selection instanceof TextSelection) {
+ action.setEnabled(true);
+ } else if (fWindow.getActivePage() != null
+ && fWindow.getActivePage().getActivePart() != null) {
+ //
+ }
+ }
+ }
+
+ private boolean checkEnabled(IStructuredSelection selection) {
+ if (selection.isEmpty())
+ return false;
+ return true;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SelectionDispatchAction.
+ */
+ public void run(ITextSelection selection) {
+ if (!ActionUtil.isProcessable(getShell(), fEditor))
+ return;
+ OpenDeclarationEditorAction openAction = new OpenDeclarationEditorAction(
+ fEditor);
+ openAction.openSelectedElement(selection);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on SelectionDispatchAction.
+ */
+ public void run(IStructuredSelection selection) {
+ if (!checkEnabled(selection))
+ return;
+ run(selection.toArray());
+ }
+
+ /**
+ * Note: this method is for internal use only. Clients should not call this
+ * method.
+ */
+ public void run(Object[] elements) {
+ if (elements != null && elements.length > 0) {
+ ITextSelection selection = (ITextSelection) fEditor
+ .getSelectionProvider().getSelection();
+ IDocument doc = fEditor.getDocumentProvider().getDocument(
+ fEditor.getEditorInput());
+ int pos = selection.getOffset();
+
+ OpenDeclarationEditorAction openAction = new OpenDeclarationEditorAction(
+ fEditor);
+ openAction.openSelectedPosition(doc, pos);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenDeclarationEditorAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenDeclarationEditorAction.java
new file mode 100644
index 0000000..d800960
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/actions/PHPOpenDeclarationEditorAction.java
@@ -0,0 +1,72 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: www.phpeclipse.de
+ **********************************************************************************************************************************/
+package net.sourceforge.phpeclipse.actions;
+
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionDelegate;
+
+public class PHPOpenDeclarationEditorAction extends ActionDelegate implements
+ IEditorActionDelegate {
+ private IWorkbenchWindow fWindow;
+
+ private PHPEditor fEditor;
+
+ public void init(IWorkbenchWindow window) {
+ this.fWindow = window;
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (!selection.isEmpty()) {
+ if (selection instanceof TextSelection) {
+ action.setEnabled(true);
+ } else if (fWindow.getActivePage() != null
+ && fWindow.getActivePage().getActivePart() != null) {
+ //
+ }
+ }
+ }
+
+ private boolean checkEnabled(IStructuredSelection selection) {
+ if (selection.isEmpty())
+ return false;
+ return true;
+ }
+
+ public void run(IAction action) {
+ if (fEditor == null) {
+ IEditorPart targetEditor = fWindow.getActivePage()
+ .getActiveEditor();
+ if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+ fEditor = (PHPEditor) targetEditor;
+ }
+ }
+ if (fEditor != null) {
+ ITextSelection selection = (ITextSelection) fEditor
+ .getSelectionProvider().getSelection();
+ OpenDeclarationEditorAction openAction = new OpenDeclarationEditorAction(
+ fEditor);
+ openAction.openSelectedElement(selection);
+ }
+ }
+
+ public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+ if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+ fEditor = (PHPEditor) targetEditor;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/ExternalEditorInput.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/ExternalEditorInput.java
new file mode 100644
index 0000000..07be7dc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/ExternalEditorInput.java
@@ -0,0 +1,101 @@
+package net.sourceforge.phpeclipse.builder;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IPersistableElement;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * An EditorInput for an external file.
+ */
+public class ExternalEditorInput implements IStorageEditorInput {
+
+ IStorage externalFile;
+
+ /**
+ * Two ExternalEditorInputs are equal if their IStorage's are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof ExternalEditorInput))
+ return false;
+ ExternalEditorInput other = (ExternalEditorInput) obj;
+ return externalFile.equals(other.externalFile);
+ }
+
+ /*
+ * @see IEditorInput#exists()
+ */
+ public boolean exists() {
+ // External file can not be deleted
+ return true;
+ }
+
+ /*
+ * @see IAdaptable#getAdapter(Class)
+ */
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+
+ /*
+ * @see IEditorInput#getContentType()
+ */
+ public String getContentType() {
+ return externalFile.getFullPath().getFileExtension();
+ }
+
+ /*
+ * @see IEditorInput#getFullPath()
+ */
+ public String getFullPath() {
+ return externalFile.getFullPath().toString();
+ }
+
+ /*
+ * @see IEditorInput#getImageDescriptor()
+ */
+ public ImageDescriptor getImageDescriptor() {
+ IEditorRegistry registry = PlatformUI.getWorkbench()
+ .getEditorRegistry();
+ return registry.getImageDescriptor(externalFile.getFullPath()
+ .getFileExtension());
+ }
+
+ /*
+ * @see IEditorInput#getName()
+ */
+ public String getName() {
+ return externalFile.getName();
+ }
+
+ /*
+ * @see IEditorInput#getPersistable()
+ */
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ /*
+ * see IStorageEditorInput#getStorage()
+ */
+ public IStorage getStorage() {
+ return externalFile;
+ }
+
+ /*
+ * @see IEditorInput#getToolTipText()
+ */
+ public String getToolTipText() {
+ return externalFile.getFullPath().toString();
+ }
+
+ public ExternalEditorInput(IStorage exFile) {
+ externalFile = exFile;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/ExternalStorageDocumentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/ExternalStorageDocumentProvider.java
new file mode 100644
index 0000000..c1d2ad5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/ExternalStorageDocumentProvider.java
@@ -0,0 +1,60 @@
+package net.sourceforge.phpeclipse.builder;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.editors.text.StorageDocumentProvider;
+
+/**
+ * @author ed
+ * @version 1.0, May 19, 2003
+ */
+public class ExternalStorageDocumentProvider extends StorageDocumentProvider {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSaveDocument(org.eclipse.core.runtime.IProgressMonitor,
+ * java.lang.Object, org.eclipse.jface.text.IDocument, boolean)
+ */
+ protected void doSaveDocument(IProgressMonitor monitor, Object element,
+ IDocument document, boolean overwrite) throws CoreException {
+ if (element instanceof ExternalEditorInput) {
+ ExternalEditorInput external = (ExternalEditorInput) element;
+ FileStorage storage = (FileStorage) external.getStorage();
+ String encoding = getEncoding(element);
+ if (encoding == null)
+ encoding = getDefaultEncoding();
+ try {
+ InputStream stream = new ByteArrayInputStream(document.get()
+ .getBytes(encoding));
+ try {
+ // inform about the upcoming content change
+ fireElementStateChanging(element);
+ storage.setContents(stream, overwrite, true, monitor);
+ } catch (RuntimeException e) {
+ // inform about failure
+ fireElementStateChangeFailed(element);
+ throw e;
+ }
+ } catch (IOException e) {
+ IStatus s = new Status(IStatus.ERROR,
+ PHPeclipsePlugin.PLUGIN_ID, IStatus.OK, e.getMessage(),
+ e);
+ throw new CoreException(s);
+ }
+
+ } else {
+ super.doSaveDocument(monitor, element, document, overwrite);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/FileStorage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/FileStorage.java
new file mode 100644
index 0000000..685ff79
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/FileStorage.java
@@ -0,0 +1,137 @@
+package net.sourceforge.phpeclipse.builder;
+
+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 net.sourceforge.phpdt.internal.core.util.StreamUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IStorage;
+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.PlatformObject;
+import org.eclipse.core.runtime.Status;
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+/**
+ *
+ * @see IStorage
+ */
+public class FileStorage extends PlatformObject implements IStorage {
+ private boolean forceReadOnly;
+
+ private final IPath path;
+
+ private final File file;
+
+ /**
+ * Two FileStorages are equal if their IPaths are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof FileStorage))
+ return false;
+ FileStorage other = (FileStorage) obj;
+ return path.equals(other.path);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IStorage#getContents()
+ */
+ public InputStream getContents() throws CoreException {
+ try {
+ return new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ PHPeclipsePlugin.PLUGIN_ID, IStatus.ERROR, e.toString(), e));
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IStorage#getFullPath()
+ */
+ public IPath getFullPath() {
+ return this.path;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IStorage#getName()
+ */
+ public String getName() {
+ return this.path.lastSegment();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IStorage#isReadOnly()
+ */
+ public boolean isReadOnly() {
+ return forceReadOnly || !file.canWrite();
+ }
+
+ /**
+ * Method FileStorage.
+ *
+ * @param path
+ */
+ public FileStorage(IPath path) {
+ this.path = path;
+ this.file = path.toFile();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return path.toOSString();
+ }
+
+ /**
+ * @param stream
+ * @param overwrite
+ * @param b
+ * @param monitor
+ */
+ public void setContents(InputStream stream, boolean overwrite, boolean b,
+ IProgressMonitor monitor) throws CoreException {
+ try {
+ StreamUtil.transferStreams(stream, new FileOutputStream(file));
+ } catch (FileNotFoundException e) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ PHPeclipsePlugin.PLUGIN_ID, IStatus.ERROR, e.toString(), e));
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ PHPeclipsePlugin.PLUGIN_ID, IStatus.ERROR, e.toString(), e));
+ }
+ }
+
+ /**
+ * Some document providers (notably CompilationUnitDocumentProvider) can't
+ * handle read/write storage.
+ */
+ public void setReadOnly() {
+ forceReadOnly = true;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java
new file mode 100644
index 0000000..18f3458
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java
@@ -0,0 +1,1029 @@
+package net.sourceforge.phpeclipse.builder;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.obfuscator.PHPIdentifier;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Manages the identifer index information for a specific project
+ *
+ */
+public class IdentifierIndexManager {
+ public class LineCreator implements ITerminalSymbols {
+ private Scanner fScanner;
+
+ private int fToken;
+
+ public LineCreator() {
+ fScanner = new Scanner(true, false, false, false, true, null, null,
+ true /* taskCaseSensitive */);
+ }
+
+ /**
+ * Add the information of the current identifier to the line
+ *
+ * @param typeOfIdentifier
+ * the type of the identifier ('c'lass, 'd'efine, 'f'unction,
+ * 'm'ethod(class), 'v'ariable(class) 'g'lobal variable)
+ * @param identifier
+ * current identifier
+ * @param line
+ * Buffer for the current index line
+ */
+ private void addIdentifierInformation(char typeOfIdentifier,
+ char[] identifier, StringBuffer line) {
+ line.append('\t');
+ line.append(typeOfIdentifier);
+ line.append(identifier);
+ }
+
+ /**
+ * Add the information of the current identifier to the line
+ *
+ * @param typeOfIdentifier
+ * the type of the identifier ('c'lass, 'd'efine, 'f'unction,
+ * 'm'ethod(class), 'v'ariable(class) 'g'lobal variable)
+ * @param identifier
+ * current identifier
+ * @param line
+ * Buffer for the current index line
+ * @param phpdocOffset
+ * the offset of the PHPdoc comment if available
+ * @param phpdocLength
+ * the length of the PHPdoc comment if available
+ */
+ private void addIdentifierInformation(char typeOfIdentifier,
+ char[] identifier, StringBuffer line, int phpdocOffset,
+ int phpdocLength) {
+ line.append('\t');
+ line.append(typeOfIdentifier);
+ line.append(identifier);
+ line.append("\to"); // Offset
+ line.append(fScanner.getCurrentTokenStartPosition());
+ if (phpdocOffset >= 0) {
+ line.append("\tp"); // phpdoc offset
+ line.append(phpdocOffset);
+ line.append("\tl"); // phpdoc length
+ line.append(phpdocLength);
+ }
+ }
+
+ private void addClassVariableInformation(char typeOfIdentifier,
+ char[] identifier, StringBuffer line, int phpdocOffset,
+ int phpdocLength) {
+ line.append('\t');
+ line.append(typeOfIdentifier);
+ line.append(identifier);
+ line.append("\to"); // Offset
+ // we don't store the '$' in the index for class variables:
+ line.append(fScanner.getCurrentTokenStartPosition() + 1);
+ if (phpdocOffset >= 0) {
+ line.append("\tp"); // phpdoc offset
+ line.append(phpdocOffset);
+ line.append("\tl"); // phpdoc length
+ line.append(phpdocLength);
+ }
+ }
+
+ /**
+ * Get the next token from input
+ */
+ private void getNextToken() throws InvalidInputException {
+ // try {
+ fToken = fScanner.getNextToken();
+ if (Scanner.DEBUG) {
+ int currentEndPosition = fScanner.getCurrentTokenEndPosition();
+ int currentStartPosition = fScanner
+ .getCurrentTokenStartPosition();
+ System.out.print(currentStartPosition + ","
+ + currentEndPosition + ": ");
+ System.out.println(fScanner.toStringAction(fToken));
+ }
+ return;
+ }
+
+ private void skipComments()
+ {
+ try {
+ getNextToken();
+ while (fToken == TokenNameCOMMENT_BLOCK || fToken == TokenNameCOMMENT_PHPDOC) {
+ getNextToken();
+ }
+ } catch (InvalidInputException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ }
+
+ private void parseDeclarations(char[] parent, StringBuffer buf,
+ boolean goBack) {
+ char[] ident;
+ char[] classVariable;
+ int counter = 0;
+ boolean hasModifiers = false;
+ int phpdocOffset = -1;
+ int phpdocLength = -1;
+ try {
+ while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
+ phpdocOffset = -1;
+ hasModifiers = false;
+ if (fToken == TokenNameCOMMENT_PHPDOC) {
+ phpdocOffset = fScanner.getCurrentTokenStartPosition();
+ phpdocLength = fScanner.getCurrentTokenEndPosition()
+ - fScanner.getCurrentTokenStartPosition() + 1;
+ getNextToken();
+ while (fToken == TokenNamestatic
+ || fToken == TokenNamefinal
+ || fToken == TokenNamepublic
+ || fToken == TokenNameprotected
+ || fToken == TokenNameprivate
+ || fToken == TokenNameabstract) {
+ hasModifiers = true;
+ getNextToken();
+ }
+ if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
+ break;
+ }
+ }
+ if (fToken == TokenNamefunction) {
+ skipComments();
+ if (fToken == TokenNameAND) {
+ getNextToken();
+ }
+ if (fToken == TokenNameIdentifier) {
+ ident = fScanner.getCurrentIdentifierSource();
+ if (parent != null
+ && equalCharArrays(parent, ident)) {
+ // constructor function
+ addIdentifierInformation('k', ident, buf,
+ phpdocOffset, phpdocLength);
+ } else {
+ if (parent != null) {
+ // class method function
+ addIdentifierInformation('m', ident, buf,
+ phpdocOffset, phpdocLength);
+ } else {
+ // nested function ?!
+ addIdentifierInformation('f', ident, buf,
+ phpdocOffset, phpdocLength);
+ }
+ }
+ skipComments();
+ parseDeclarations(null, buf, true);
+ }
+ } else if (fToken == TokenNameclass
+ || fToken == TokenNameinterface) {
+ skipComments();
+ if (fToken == TokenNameIdentifier) {
+ ident = fScanner.getCurrentIdentifierSource();
+ addIdentifierInformation('c', ident, buf,
+ phpdocOffset, phpdocLength);
+ skipComments();
+ if (fToken == TokenNameextends) {
+ skipComments();
+ while (fToken == TokenNameIdentifier) {
+ ident = fScanner
+ .getCurrentIdentifierSource();
+ // extends ident
+ addIdentifierInformation('e', ident, buf);
+ skipComments();
+ if (fToken == TokenNameCOMMA) {
+ skipComments();
+ }
+ }
+ }
+ if (fToken == TokenNameimplements) {
+ skipComments();
+ while (fToken == TokenNameIdentifier) {
+ ident = fScanner
+ .getCurrentIdentifierSource();
+ // implements ident
+ addIdentifierInformation('e', ident, buf);
+ skipComments();
+ if (fToken == TokenNameCOMMA) {
+ skipComments();
+// getNextToken();
+ }
+ }
+ }
+ // skip tokens for classname, extends and others
+ // until we have
+ // the opening '{'
+ while (fToken != TokenNameLBRACE
+ && fToken != TokenNameEOF
+ && fToken != TokenNameERROR) {
+ getNextToken();
+ }
+ parseDeclarations(ident, buf, true);
+ }
+ } else if (fToken == TokenNamevar || hasModifiers
+ || fToken == TokenNamestatic
+ || fToken == TokenNamefinal
+ || fToken == TokenNamepublic
+ || fToken == TokenNameprotected
+ || fToken == TokenNameprivate) {
+ while (fToken == TokenNamevar
+ || fToken == TokenNamestatic
+ || fToken == TokenNamefinal
+ || fToken == TokenNamepublic
+ || fToken == TokenNameprotected
+ || fToken == TokenNameprivate) {
+ skipComments();
+ }
+ while (fToken == TokenNameVariable) {
+ ident = fScanner.getCurrentIdentifierSource();
+ classVariable = new char[ident.length - 1];
+ System.arraycopy(ident, 1, classVariable, 0,
+ ident.length - 1);
+ addClassVariableInformation('v', classVariable,
+ buf, phpdocOffset, phpdocLength);
+ skipComments();
+ if (fToken == TokenNameCOMMA) {
+ skipComments();
+ }
+ }
+ } else if (!hasModifiers && fToken == TokenNameIdentifier) {
+ ident = fScanner.getCurrentIdentifierSource();
+ getNextToken();
+ if (ident.length == 6 && ident[0] == 'd'
+ && ident[1] == 'e' && ident[2] == 'f'
+ && ident[3] == 'i' && ident[4] == 'n'
+ && ident[5] == 'e') {
+ if (fToken == TokenNameLPAREN) {
+ getNextToken();
+ if (fToken == TokenNameStringDoubleQuote) {
+ ident = fScanner
+ .getCurrentStringLiteralSource();
+ addIdentifierInformation('d', ident, buf,
+ phpdocOffset, phpdocLength);
+ getNextToken();
+ } else if (fToken == TokenNameStringSingleQuote) {
+ ident = fScanner
+ .getCurrentStringLiteralSource();
+ addIdentifierInformation('d', ident, buf,
+ phpdocOffset, phpdocLength);
+ getNextToken();
+ }
+ }
+ }
+ } else if (fToken == TokenNameglobal) {
+ // global variable
+ while (fToken != TokenNameEOF
+ && fToken != TokenNameERROR
+ && fToken != TokenNameSEMICOLON
+ && fToken != TokenNameLBRACE
+ && fToken != TokenNameRBRACE) {
+ getNextToken();
+ if (fToken == TokenNameVariable) {
+ ident = fScanner.getCurrentIdentifierSource();
+ addIdentifierInformation('g', ident, buf,
+ phpdocOffset, phpdocLength);
+ }
+ }
+ } else if (fToken == TokenNameLBRACE) {
+ getNextToken();
+ counter++;
+ } else if (fToken == TokenNameRBRACE) {
+ getNextToken();
+ --counter;
+ if (counter == 0 && goBack) {
+ return;
+ }
+ } else {
+ getNextToken();
+ }
+ }
+ } catch (InvalidInputException e) {
+ // ignore errors
+ } catch (SyntaxError e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ synchronized public void parseIdentifiers(char[] charArray,
+ StringBuffer buf) {
+ char[] ident;
+ String identifier;
+ boolean hasModifiers = false;
+ int phpdocOffset = -1;
+ int phpdocLength = -1;
+ fScanner.setSource(charArray);
+ fScanner.setPHPMode(false);
+ fToken = TokenNameEOF;
+ try {
+ getNextToken();
+ while (fToken != TokenNameEOF) { // && fToken !=
+ // TokenNameERROR) {
+ phpdocOffset = -1;
+ hasModifiers = false;
+ switch (fToken) {
+ case TokenNameCOMMENT_PHPDOC:
+ phpdocOffset = fScanner.getCurrentTokenStartPosition();
+ phpdocLength = fScanner.getCurrentTokenEndPosition()
+ - fScanner.getCurrentTokenStartPosition() + 1;
+ getNextToken();
+ while (fToken == TokenNamestatic
+ || fToken == TokenNamefinal
+ || fToken == TokenNamepublic
+ || fToken == TokenNameprotected
+ || fToken == TokenNameprivate
+ || fToken == TokenNameabstract) {
+ hasModifiers = true;
+ getNextToken();
+ }
+ if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
+ break;
+ }
+ break;
+
+ case TokenNamefunction:
+ skipComments();
+ if (fToken == TokenNameAND) {
+ getNextToken();
+ }
+ if (fToken == TokenNameIdentifier) {
+ ident = fScanner.getCurrentIdentifierSource();
+ addIdentifierInformation('f', ident, buf,
+ phpdocOffset, phpdocLength);
+ skipComments();
+ if (fToken == TokenNameLPAREN) {
+ skipComments();
+ do {
+ if (fToken == TokenNameVariable) {
+ ident = fScanner.getCurrentIdentifierSource();
+ addIdentifierInformation('v', ident, buf,
+ phpdocOffset, phpdocLength);
+ skipComments();
+ if (fToken == TokenNameCOMMA) {
+ skipComments();
+ }
+ }
+ } while (fToken != TokenNameRPAREN );
+ }
+ parseDeclarations(null, buf, true);
+ }
+ break;
+
+ case TokenNameclass:
+ case TokenNameinterface:
+ skipComments();
+ if (fToken == TokenNameIdentifier) {
+ ident = fScanner.getCurrentIdentifierSource();
+ addIdentifierInformation('c', ident, buf,
+ phpdocOffset, phpdocLength);
+ skipComments();
+ if (fToken == TokenNameextends) {
+ skipComments();
+ while (fToken == TokenNameIdentifier) {
+ ident = fScanner
+ .getCurrentIdentifierSource();
+ // extends ident
+ addIdentifierInformation('e', ident, buf);
+ skipComments();
+ if (fToken == TokenNameCOMMA) {
+ skipComments();
+ }
+ }
+ }
+ if (fToken == TokenNameimplements) {
+ skipComments();
+ while (fToken == TokenNameIdentifier) {
+ ident = fScanner
+ .getCurrentIdentifierSource();
+ // implements ident
+ addIdentifierInformation('e', ident, buf);
+ skipComments();
+ if (fToken == TokenNameCOMMA) {
+ skipComments();
+ }
+ }
+ }
+ // skip fTokens for classname, extends and others
+ // until we have
+ // the opening '{'
+ while (fToken != TokenNameLBRACE
+ && fToken != TokenNameEOF
+ && fToken != TokenNameERROR) {
+ getNextToken();
+ }
+ parseDeclarations(ident, buf, true);
+ }
+ break;
+
+ case TokenNameVariable:
+ // global variable
+ ident = fScanner.getCurrentIdentifierSource();
+ addIdentifierInformation('g', ident, buf, phpdocOffset,
+ phpdocLength);
+ getNextToken();
+ break;
+
+ default:
+ getNextToken();
+ }
+
+ }
+ } catch (InvalidInputException e) {
+ // ignore errors
+ } catch (SyntaxError e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ class StringComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ String s1 = (String) o1;
+ String s2 = (String) o2;
+ return s1.compareTo(s2);
+ // return s1.toUpperCase().compareTo(s2.toUpperCase());
+ }
+
+ public boolean equals(Object o) {
+ String s = (String) o;
+ return compare(this, o) == 0;
+ }
+ }
+
+ private HashMap fFileMap;
+
+ private String fFilename;
+
+ private TreeMap fIndentifierMap;
+
+ public IdentifierIndexManager(String filename) {
+ fFilename = filename;
+ initialize();
+ readFile();
+ }
+
+ /**
+ * Check if 2 char arrays are equal
+ *
+ * @param a
+ * @param b
+ * @return
+ */
+ private static boolean equalCharArrays(char[] a, char[] b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (int i = 0; i < b.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public LineCreator createLineCreator() {
+ return new LineCreator();
+ }
+
+ /**
+ * Add the information for a given IFile resource
+ *
+ */
+ public void addFile(IFile fileToParse) {
+ LineCreator lineCreator = createLineCreator();
+ try {
+ addInputStream(new BufferedInputStream(fileToParse.getContents()),
+ fileToParse.getProjectRelativePath().toString(),
+ lineCreator, fileToParse.getCharset());
+ } catch (CoreException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ }
+
+ /**
+ * @param fileToParse
+ * @param lineCreator
+ * @throws CoreException
+ */
+ public void addInputStream(InputStream stream, String filePath,
+ LineCreator lineCreator, String charset) throws CoreException {
+ try {
+ StringBuffer lineBuffer = new StringBuffer();
+ lineBuffer.append(filePath);
+ lineCreator.parseIdentifiers(Util.getInputStreamAsCharArray(stream,
+ -1, charset), lineBuffer);
+ addLine(lineBuffer.toString());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+
+ /**
+ * Adds a line of the index file for function, class, class-method and
+ * class-variable names
+ *
+ * @param line
+ */
+ private void addLine(String line) {
+ addLine(fIndentifierMap, fFileMap, line, null);
+ }
+
+ public TreeMap getIdentifiers(IFile file) {
+ TreeMap treeMap = new TreeMap(new StringComparator());
+ addIdentifiers(treeMap, file);
+ return treeMap;
+ }
+
+ public TreeMap getIdentifiers(String startClazz) {
+ TreeMap treeMap = new TreeMap(new StringComparator());
+ addIdentifiers(treeMap, startClazz);
+ return treeMap;
+ }
+
+ public void addIdentifiers(TreeMap treeMap, IFile file) {
+ String line = (String) fFileMap.get(file.getProjectRelativePath()
+ .toString());
+ if (line != null) {
+ PHPIdentifierLocation ident;
+ ArrayList allClassNames = new ArrayList();
+ addLine(treeMap, null, line, allClassNames);
+ int i = 0;
+ while (i < allClassNames.size()) {
+ String clazz = (String) allClassNames.get(i++);
+ addClassName(treeMap, clazz, allClassNames);
+ }
+ }
+ }
+
+ public void addIdentifiers(TreeMap treeMap, String startClazz) {
+ PHPIdentifierLocation ident;
+ ArrayList allClassNames = new ArrayList();
+ addClassName(treeMap, startClazz, allClassNames);
+ int i = 0;
+ while (i < allClassNames.size()) {
+ String clazz = (String) allClassNames.get(i++);
+ addClassName(treeMap, clazz, allClassNames);
+ }
+ }
+
+ /**
+ * @param treeMap
+ * @param clazz
+ * @param allClassNames
+ */
+ private boolean addClassName(TreeMap treeMap, String clazz,
+ List allClassNames) {
+ String line;
+ PHPIdentifierLocation ident;
+ List list = getLocations(clazz);
+ if (list == null) {
+ return false;
+ }
+ boolean result = false;
+ for (int i = 0; i < list.size(); i++) {
+ ident = (PHPIdentifierLocation) list.get(i);
+ if (ident.isClass()) {
+ line = (String) fFileMap.get(ident.getFilename());
+ addLine(treeMap, null, line, allClassNames);
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Adds a line of the index file for function, class, class-method and
+ * class-variable names
+ *
+ * @param line
+ */
+ public void addLine(TreeMap treeMap, HashMap fileMap, String line,
+ List allClassNames) {
+ StringTokenizer tokenizer;
+ String phpFileName = null;
+ String token;
+ String identifier = null;
+ String classname = null;
+ String offset = null;
+ PHPIdentifierLocation phpIdentifier = null;
+ boolean tokenExists = false;
+ tokenizer = new StringTokenizer(line, "\t");
+ // first token contains the filename:
+ try {
+ if (tokenizer.hasMoreTokens()) {
+ phpFileName = tokenizer.nextToken();
+ // System.out.println(token);
+ } else {
+ return;
+ }
+ // all the other tokens are identifiers:
+ while (tokenizer.hasMoreTokens()) {
+ token = tokenizer.nextToken();
+ // System.out.println(token);
+ switch (token.charAt(0)) {
+ case 'c':
+ // class name
+ identifier = token.substring(1);
+ classname = identifier;
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.CLASS, phpFileName);
+ break;
+ case 'd':
+ // define
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.DEFINE, phpFileName);
+ break;
+ case 'e':
+ // extends
+ // not in map
+ identifier = null;
+ phpIdentifier = null;
+ if (allClassNames != null) {
+ String extName = token.substring(1);
+ if (!allClassNames.contains(extName)) {
+ allClassNames.add(extName);
+ }
+ }
+ break;
+ case 'f':
+ // function name
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.FUNCTION, phpFileName);
+ break;
+ case 'g':
+ // global variable
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.GLOBAL_VARIABLE, phpFileName);
+ break;
+ case 'i':
+ // implements
+ // not in map
+ identifier = null;
+ phpIdentifier = null;
+ if (allClassNames != null) {
+ String implName = token.substring(1);
+ if (!allClassNames.contains(implName)) {
+ allClassNames.add(implName);
+ }
+ }
+ break;
+ case 'k':
+ // constructor function name
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.CONSTRUCTOR, phpFileName);
+ break;
+ case 'm':
+ // method inside a class
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.METHOD, phpFileName, classname);
+ break;
+ case 'v':
+ // variable inside a class
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.VARIABLE, phpFileName, classname);
+ break;
+ case 'o':
+ // offset information
+ identifier = null;
+ if (phpIdentifier != null) {
+ offset = token.substring(1);
+ phpIdentifier.setOffset(Integer.parseInt(offset));
+ }
+ break;
+ case 'p':
+ // PHPdoc offset information
+ identifier = null;
+ if (phpIdentifier != null) {
+ offset = token.substring(1);
+ phpIdentifier.setPHPDocOffset(Integer.parseInt(offset));
+ }
+ break;
+ case 'l':
+ // PHPdoc length information
+ identifier = null;
+ if (phpIdentifier != null) {
+ offset = token.substring(1);
+ phpIdentifier.setPHPDocLength(Integer.parseInt(offset));
+ }
+ break;
+ default:
+ PHPeclipsePlugin.log(IStatus.ERROR,
+ "Unknown token character in IdentifierIndexManager: "
+ + token.charAt(0));
+ identifier = null;
+ phpIdentifier = null;
+ classname = null;
+ }
+ if (identifier != null && phpIdentifier != null) {
+ tokenExists = true;
+ ArrayList list = (ArrayList) treeMap.get(identifier);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(phpIdentifier);
+ treeMap.put(identifier, list);
+ } else {
+ boolean flag = false;
+ for (int i = 0; i < list.size(); i++) {
+ if (list.get(i).equals(phpIdentifier)) {
+ flag = true;
+ break;
+ }
+ }
+ if (flag == false) {
+ list.add(phpIdentifier);
+ }
+ }
+ }
+ }
+ if (fileMap != null) {
+ fileMap.put(phpFileName, line);
+ }
+ } catch (Throwable e) {
+ // write to workspace/.metadata/.log file
+ PHPeclipsePlugin.log(e);
+ }
+ // if (tokenExists) {
+
+ // }
+ }
+
+ /**
+ * Change the information for a given IFile resource
+ *
+ */
+ public void changeFile(IFile fileToParse) {
+ removeFile(fileToParse);
+ addFile(fileToParse);
+ }
+
+ /**
+ * Get a list of all PHPIdentifierLocation object's associated with an
+ * identifier
+ *
+ * @param identifier
+ * @return
+ */
+ public List getLocations(String identifier) {
+ List list = (List) fIndentifierMap.get(identifier);
+ if (list != null) {
+ return list;
+ }
+ return new ArrayList();
+ }
+
+ /**
+ * Initialize (i.e. clear) the current index information
+ *
+ */
+ public void initialize() {
+ fIndentifierMap = new TreeMap(new StringComparator());
+ fFileMap = new HashMap();
+ }
+
+ private void readFile() {
+ FileReader fileReader;
+ try {
+ fileReader = new FileReader(fFilename);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+ String line;
+ while (bufferedReader.ready()) {
+ // all entries for one file are in a line
+ // separated by tabs !
+ line = bufferedReader.readLine();
+ addLine(line);
+ }
+ fileReader.close();
+ } catch (FileNotFoundException e) {
+ // ignore this
+ // TODO DialogBox which asks the user if she/he likes to build new
+ // index?
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Remove the information for a given IFile resource
+ *
+ */
+ public void removeFile(IFile fileToParse) {
+ // String line = (String)
+ // fFileMap.get(fileToParse.getLocation().toString());
+ String line = (String) fFileMap.get(fileToParse
+ .getProjectRelativePath().toString());
+ if (line != null) {
+ removeLine(line);
+ }
+ }
+
+ /**
+ * Removes a line of the index file for function, class, class-method and
+ * class-variable names
+ *
+ * @param line
+ */
+ private void removeLine(String line) {
+ StringTokenizer tokenizer;
+ String phpFileName = null;
+ String token;
+ String identifier = null;
+ String classname = null;
+ PHPIdentifier phpIdentifier = null;
+ boolean tokenExists = false;
+ tokenizer = new StringTokenizer(line, "\t");
+ // first token contains the filename:
+ if (tokenizer.hasMoreTokens()) {
+ phpFileName = tokenizer.nextToken();
+ // System.out.println(token);
+ } else {
+ return;
+ }
+ int offset = -1;
+ // all the other tokens are identifiers:
+ while (tokenizer.hasMoreTokens()) {
+ token = tokenizer.nextToken();
+ // System.out.println(token);
+ switch (token.charAt(0)) {
+ case 'c':
+ // class name
+ identifier = token.substring(1);
+ classname = identifier;
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.CLASS, phpFileName);
+ break;
+ case 'd':
+ // define
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.DEFINE, phpFileName);
+ break;
+ case 'e':
+ // extends
+ identifier = null;
+ phpIdentifier = null;
+ break;
+ case 'f':
+ // function name
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.FUNCTION, phpFileName);
+ break;
+ case 'g':
+ // global variable
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.GLOBAL_VARIABLE, phpFileName);
+ break;
+ case 'i':
+ // implements
+ identifier = null;
+ phpIdentifier = null;
+ break;
+ case 'k':
+ // constructor function name
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.CONSTRUCTOR, phpFileName);
+ break;
+ case 'm':
+ // method inside a class
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.METHOD, phpFileName, classname);
+ break;
+ case 'o':
+ // offset information
+ identifier = null;
+ break;
+ case 'p':
+ // PHPdoc offset information
+ identifier = null;
+ break;
+ case 'l':
+ // PHPdoc length information
+ identifier = null;
+ break;
+ case 'v':
+ // variable inside a class
+ identifier = token.substring(1);
+ phpIdentifier = new PHPIdentifierLocation(identifier,
+ PHPIdentifier.VARIABLE, phpFileName, classname);
+ break;
+ default:
+ PHPeclipsePlugin.log(IStatus.ERROR,
+ "Unknown token character in IdentifierIndexManager: "
+ + token.charAt(0));
+ identifier = null;
+ phpIdentifier = null;
+ classname = null;
+ }
+ if (identifier != null && phpIdentifier != null) {
+ ArrayList list = (ArrayList) fIndentifierMap.get(identifier);
+ if (list == null) {
+ } else {
+ for (int i = 0; i < list.size(); i++) {
+ if (list.get(i).equals(phpIdentifier)) {
+ list.remove(i);
+ break;
+ }
+ }
+ if (list.size() == 0) {
+ fIndentifierMap.remove(identifier);
+ }
+ }
+ }
+ }
+ fFileMap.remove(phpFileName);
+ }
+
+ /**
+ * Save the current index information in the projects index file
+ *
+ */
+ public void writeFile() {
+ FileWriter fileWriter;
+ try {
+ fileWriter = new FileWriter(fFilename);
+ String line;
+ Collection collection = fFileMap.values();
+ Iterator iterator = collection.iterator();
+ while (iterator.hasNext()) {
+ line = (String) iterator.next();
+ fileWriter.write(line + '\n');
+ }
+ fileWriter.close();
+ } catch (FileNotFoundException e) {
+ // ignore exception; project is deleted by user
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @param fromKey
+ * @param toKey
+ * @return
+ */
+ public SortedMap getIdentifierMap() {
+ return fIndentifierMap;
+ }
+
+ synchronized public List getFileList(String filePattern) {
+ Set set = fFileMap.keySet();
+ if (set.isEmpty()) {
+ return null;
+ }
+ Iterator iter = set.iterator();
+ ArrayList list = new ArrayList();
+ String fileName;
+ int index;
+ while (iter.hasNext()) {
+ fileName = (String) iter.next();
+ if ((index = fileName.indexOf(filePattern)) != -1
+ && fileName.length() == (index + filePattern.length())) {
+ list.add(fileName);
+ }
+ }
+ return list;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/PHPIdentifierLocation.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/PHPIdentifierLocation.java
new file mode 100644
index 0000000..afad5af
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/builder/PHPIdentifierLocation.java
@@ -0,0 +1,193 @@
+package net.sourceforge.phpeclipse.builder;
+
+import net.sourceforge.phpeclipse.obfuscator.PHPIdentifier;
+
+/**
+ *
+ */
+public class PHPIdentifierLocation extends PHPIdentifier implements Comparable {
+ final public static int UNDEFINED_MATCH = 0;
+
+ final public static int PATTERN_MATCH = 1;
+
+ final public static int EXACT_MATCH = 2;
+
+ private int fMatch;
+
+ private String fClassname;
+
+ private String fFilename;
+
+ private int fOffset;
+
+ private int fPHPDocLength;
+
+ private int fPHPDocOffset;
+
+ private String fUsage;
+
+ public PHPIdentifierLocation(String identifier, int type, String filename) {
+ this(identifier, type, filename, null);
+ }
+
+ public PHPIdentifierLocation(String identifier, int type, String filename,
+ String classname) {
+ super(identifier, type);
+ fFilename = filename;
+ fClassname = classname;
+ fOffset = -1;
+ fPHPDocLength = -1;
+ fPHPDocOffset = -1;
+ fUsage = null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof PHPIdentifierLocation)) {
+ return false;
+ }
+ return super.equals(obj)
+ && fFilename.equals(((PHPIdentifierLocation) obj).fFilename);
+ }
+
+ /**
+ * @return
+ */
+ public String getClassname() {
+ return fClassname;
+ }
+
+ /**
+ * @return
+ */
+ public String getFilename() {
+ return fFilename;
+ }
+
+ /**
+ * @return
+ */
+ public int getOffset() {
+ return fOffset;
+ }
+
+ /**
+ * @return
+ */
+ public int getPHPDocLength() {
+ return fPHPDocLength;
+ }
+
+ /**
+ * @return
+ */
+ public int getPHPDocOffset() {
+ return fPHPDocOffset;
+ }
+
+ /**
+ * @return
+ */
+ public String getUsage() {
+ return fUsage;
+ }
+
+ /**
+ * @param string
+ */
+ public void setClassname(String string) {
+ fClassname = string;
+ }
+
+ /**
+ * @param string
+ */
+ public void setFilename(String string) {
+ fFilename = string;
+ }
+
+ /**
+ * @param i
+ */
+ public void setOffset(int i) {
+ fOffset = i;
+ }
+
+ /**
+ * @param i
+ */
+ public void setPHPDocLength(int i) {
+ fPHPDocLength = i;
+ }
+
+ /**
+ * @param i
+ */
+ public void setPHPDocOffset(int i) {
+ fPHPDocOffset = i;
+ }
+
+ /**
+ * @param string
+ */
+ public void setUsage(String string) {
+ fUsage = string;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ String result = null;
+ switch (fMatch) {
+ case UNDEFINED_MATCH:
+ result = " [";
+ break;
+ case PATTERN_MATCH:
+ result = " [pattern include][";
+ break;
+ case EXACT_MATCH:
+ result = " [exact include][";
+ break;
+ default:
+ result = "";
+ }
+ return super.toString() + result + fFilename + "]";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object o) {
+ PHPIdentifierLocation i = (PHPIdentifierLocation) o;
+ if (fMatch > i.fMatch) {
+ return -1;
+ } else if (fMatch < i.fMatch) {
+ return 1;
+ }
+ return fFilename.compareTo(i.fFilename);
+ }
+
+ /**
+ * @return Returns the match.
+ */
+ public int getMatch() {
+ return fMatch;
+ }
+
+ /**
+ * @param match
+ * The match to set.
+ */
+ public void setMatch(int match) {
+ fMatch = match;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnoreSet.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnoreSet.java
new file mode 100644
index 0000000..3c323aa
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnoreSet.java
@@ -0,0 +1,349 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpeclipse.obfuscator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * ObfuscatorIgnoreSet
manages a collection of templates and
+ * makes them persistent.
+ */
+public class ObfuscatorIgnoreSet {
+
+ // private static class TemplateComparator implements Comparator {
+ // public int compare(Object arg0, Object arg1) {
+ // if (arg0 == arg1)
+ // return 0;
+ //
+ // if (arg0 == null)
+ // return -1;
+ //
+ // Template template0= (Template) arg0;
+ // Template template1= (Template) arg1;
+ //
+ // return template0.getName().compareTo(template1.getName());
+ // }
+ // }
+
+ private static final String TEMPLATE_TAG = "ignore"; //$NON-NLS-1$
+
+ // private static final String NAME_ATTRIBUTE= "name"; //$NON-NLS-1$
+ // private static final String DESCRIPTION_ATTRIBUTE= "description";
+ // //$NON-NLS-1$
+ // private static final String CONTEXT_ATTRIBUTE= "context"; //$NON-NLS-1$
+ // private static final String ENABLED_ATTRIBUTE= "enabled"; //$NON-NLS-1$
+
+ // private List fTemplates= new ArrayList();
+ private HashMap fIdentifierMap = new HashMap();
+
+ // private Comparator fTemplateComparator= new TemplateComparator();
+ // private Template[] fSortedTemplates= new Template[0];
+
+ /**
+ * Convenience method for reading templates from a file.
+ *
+ * @see #addFromStream(InputStream)
+ */
+ public void addFromFile(File file) throws CoreException {
+ InputStream stream = null;
+
+ try {
+ stream = new FileInputStream(file);
+ addFromStream(stream);
+
+ } catch (IOException e) {
+ throwReadException(e);
+
+ } finally {
+ try {
+ if (stream != null)
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ /**
+ * Reads templates from a XML stream and adds them to the template set.
+ */
+ public void addFromStream(InputStream stream) throws CoreException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder parser = factory.newDocumentBuilder();
+ Document document = parser.parse(new InputSource(stream));
+ NodeList elements = document.getElementsByTagName(TEMPLATE_TAG);
+
+ int count = elements.getLength();
+ for (int i = 0; i != count; i++) {
+ Node node = elements.item(i);
+ NamedNodeMap attributes = node.getAttributes();
+
+ if (attributes == null)
+ continue;
+
+ // String name= getAttributeValue(attributes, NAME_ATTRIBUTE);
+ // String description= getAttributeValue(attributes,
+ // DESCRIPTION_ATTRIBUTE);
+ // String context= getAttributeValue(attributes,
+ // CONTEXT_ATTRIBUTE);
+ // Node enabledNode= attributes.getNamedItem(ENABLED_ATTRIBUTE);
+
+ // if (name == null || description == null || context == null)
+ // throw new
+ // SAXException(ObfuscatorMessages.getString("TemplateSet.error.missing.attribute"));
+ // //$NON-NLS-1$
+
+ // boolean enabled= true; //(enabledNode == null) ||
+ // (enabledNode.getNodeValue().equals("true")); //$NON-NLS-1$
+
+ StringBuffer buffer = new StringBuffer();
+ NodeList children = node.getChildNodes();
+ for (int j = 0; j != children.getLength(); j++) {
+ String value = children.item(j).getNodeValue();
+ if (value != null)
+ buffer.append(value);
+ }
+ String pattern = buffer.toString().trim();
+ fIdentifierMap.put(pattern, new PHPIdentifier(pattern,
+ PHPIdentifier.VARIABLE));
+ // Template template= new Template(name, description, context,
+ // pattern);
+ // template.setEnabled(enabled);
+ // add(template);
+ }
+
+ // sort();
+
+ } catch (ParserConfigurationException e) {
+ throwReadException(e);
+ } catch (IOException e) {
+ throwReadException(e);
+ } catch (SAXException e) {
+ throwReadException(e);
+ }
+ }
+
+ private String getAttributeValue(NamedNodeMap attributes, String name) {
+ Node node = attributes.getNamedItem(name);
+
+ return node == null ? null : node.getNodeValue();
+ }
+
+ /**
+ * Convenience method for saving to a file.
+ *
+ * @see #saveToStream(OutputStream)
+ */
+ public void saveToFile(File file) throws CoreException {
+ OutputStream stream = null;
+
+ try {
+ stream = new FileOutputStream(file);
+ saveToStream(stream);
+ } catch (IOException e) {
+ throwWriteException(e);
+
+ } finally {
+ try {
+ if (stream != null)
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ /**
+ * Saves the template set as XML.
+ */
+ public void saveToStream(OutputStream stream) throws CoreException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document document = builder.newDocument();
+
+ Node root = document.createElement("obfuscator"); // $NON-NLS-1$
+ // //$NON-NLS-1$
+ document.appendChild(root);
+ Iterator iter = fIdentifierMap.keySet().iterator();
+ while (iter.hasNext()) {
+ // for (int i= 0; i != fTemplates.size(); i++) {
+ // Template template= (Template) fTemplates.get(i);
+
+ Node node = document.createElement("ignore"); // $NON-NLS-1$
+ // //$NON-NLS-1$
+ root.appendChild(node);
+
+ // NamedNodeMap attributes= node.getAttributes();
+ //
+ // Attr name= document.createAttribute(NAME_ATTRIBUTE);
+ // name.setValue(template.getName());
+ // attributes.setNamedItem(name);
+ //
+ // Attr description=
+ // document.createAttribute(DESCRIPTION_ATTRIBUTE);
+ // description.setValue(template.getDescription());
+ // attributes.setNamedItem(description);
+ //
+ // Attr context= document.createAttribute(CONTEXT_ATTRIBUTE);
+ // context.setValue(template.getContextTypeName());
+ // attributes.setNamedItem(context);
+ //
+ // Attr enabled= document.createAttribute(ENABLED_ATTRIBUTE);
+ // enabled.setValue(template.isEnabled() ? "true" : "false");
+ // //$NON-NLS-1$ //$NON-NLS-2$
+ // attributes.setNamedItem(enabled);
+
+ Text pattern = document.createTextNode((String) iter.next());
+ node.appendChild(pattern);
+ }
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(stream);
+
+ transformer.transform(source, result);
+
+ } catch (ParserConfigurationException e) {
+ throwWriteException(e);
+ } catch (TransformerException e) {
+ throwWriteException(e);
+ }
+ // OutputFormat format = new OutputFormat();
+ // format.setPreserveSpace(true);
+ // Serializer serializer =
+ // SerializerFactory.getSerializerFactory("xml").makeSerializer(stream,
+ // format); //$NON-NLS-1$
+ // serializer.asDOMSerializer().serialize(document);
+ //
+ // } catch (ParserConfigurationException e) {
+ // throwWriteException(e);
+ // } catch (IOException e) {
+ // throwWriteException(e);
+ // }
+ }
+
+ private static void throwReadException(Throwable t) throws CoreException {
+ PHPeclipsePlugin.log(t);
+ // IStatus status= new
+ // JavaUIStatus(JavaStatusConstants.TEMPLATE_IO_EXCEPTION,
+ // ObfuscatorMessages.getString("TemplateSet.error.read"), t);
+ // //$NON-NLS-1$
+ // throw new JavaUIException(status);
+ }
+
+ private static void throwWriteException(Throwable t) throws CoreException {
+ PHPeclipsePlugin.log(t);
+ // IStatus status= new
+ // JavaUIStatus(JavaStatusConstants.TEMPLATE_IO_EXCEPTION,
+ // ObfuscatorMessages.getString("TemplateSet.error.write"), t);
+ // //$NON-NLS-1$
+ // throw new JavaUIException(status);
+ }
+
+ /**
+ * Adds a template to the set.
+ */
+ // public void add(Template template) {
+ // if (exists(template))
+ // return; // ignore duplicate
+ //
+ // fTemplates.add(template);
+ // sort();
+ // }
+ // private boolean exists(Template template) {
+ // for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) {
+ // Template anotherTemplate = (Template) iterator.next();
+ //
+ // if (template.equals(anotherTemplate))
+ // return true;
+ // }
+ //
+ // return false;
+ // }
+ //
+ // /**
+ // * Removes a template to the set.
+ // */
+ // public void remove(Template template) {
+ // fTemplates.remove(template);
+ // sort();
+ // }
+ //
+ /**
+ * Empties the set.
+ */
+ public void clear() {
+ fIdentifierMap.clear();
+ // fTemplates.clear();
+ // sort();
+ }
+
+ //
+ // /**
+ // * Returns all templates.
+ // */
+ // public Template[] getTemplates() {
+ // return (Template[]) fTemplates.toArray(new Template[fTemplates.size()]);
+ // }
+
+ /**
+ * Returns all templates with a given name.
+ */
+ // public Template[] getTemplates(String name) {
+ // ArrayList res= new ArrayList();
+ // for (Iterator iterator= fTemplates.iterator(); iterator.hasNext();) {
+ // Template curr= (Template) iterator.next();
+ // if (curr.getName().equals(name)) {
+ // res.add(curr);
+ // }
+ // }
+ // return (Template[]) res.toArray(new Template[res.size()]);
+ // }
+ //
+ // private void sort() {
+ // fSortedTemplates= (Template[]) fTemplates.toArray(new
+ // Template[fTemplates.size()]);
+ // Arrays.sort(fSortedTemplates, fTemplateComparator);
+ // }
+ /**
+ * @return
+ */
+ public HashMap getIdentifierMap() {
+ return fIdentifierMap;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnores.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnores.java
new file mode 100644
index 0000000..8cc826e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnores.java
@@ -0,0 +1,119 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpeclipse.obfuscator;
+
+import java.io.File;
+import java.io.InputStream;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.ErrorDialog;
+
+/**
+ * ObfuscatorIgnores
gives access to the available templates.
+ */
+public class ObfuscatorIgnores extends ObfuscatorIgnoreSet {
+
+ private static final String DEFAULT_FILE = "default-obfuscator.xml"; //$NON-NLS-1$
+
+ private static final String TEMPLATE_FILE = "obfuscator.xml"; //$NON-NLS-1$
+
+ /** Singleton. */
+ private static ObfuscatorIgnores fgIgnores;
+
+ private IProject fProject;
+
+ public ObfuscatorIgnores(IProject project) {
+ fProject = project;
+ try {
+ File templateFile = getTemplateFile();
+ if (templateFile.exists()) {
+ addFromFile(templateFile);
+ } else {
+ addFromStream(getDefaultsAsStream());
+ saveToFile(templateFile);
+ }
+
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ ErrorDialog.openError(null, ObfuscatorMessages
+ .getString("Obfuscator.error.title"), //$NON-NLS-1$
+ e.getMessage(), e.getStatus());
+
+ clear();
+ }
+ }
+
+ /**
+ * Returns an instance of templates.
+ */
+ // public static ObfuscatorIgnores getInstance() {
+ // if (fgIgnores == null)
+ // fgIgnores = create();
+ //
+ // return fgIgnores;
+ // }
+ //
+ // private static ObfuscatorIgnores create() {
+ // ObfuscatorIgnores templates = new ObfuscatorIgnores();
+ //
+ // try {
+ // File templateFile = getTemplateFile();
+ // if (templateFile.exists()) {
+ // templates.addFromFile(templateFile);
+ // } else {
+ // templates.addFromStream(getDefaultsAsStream());
+ // templates.saveToFile(templateFile);
+ // }
+ //
+ // } catch (CoreException e) {
+ // PHPeclipsePlugin.log(e);
+ // ErrorDialog.openError(null,
+ // ObfuscatorMessages.getString("Templates.error.title"), //$NON-NLS-1$
+ // e.getMessage(), e.getStatus());
+ //
+ // templates.clear();
+ // }
+ //
+ // return templates;
+ // }
+ /**
+ * Resets the template set.
+ */
+ public void reset() throws CoreException {
+ clear();
+ addFromFile(getTemplateFile());
+ }
+
+ /**
+ * Resets the template set with the default templates.
+ */
+ public void restoreDefaults() throws CoreException {
+ clear();
+ addFromStream(getDefaultsAsStream());
+ }
+
+ /**
+ * Saves the template set.
+ */
+ public void save() throws CoreException {
+ saveToFile(getTemplateFile());
+ }
+
+ private InputStream getDefaultsAsStream() {
+ return ObfuscatorIgnores.class.getResourceAsStream(DEFAULT_FILE);
+ }
+
+ private File getTemplateFile() {
+ IPath path = fProject.getFullPath();
+ // PHPeclipsePlugin.getDefault().getStateLocation();
+ path = path.append(TEMPLATE_FILE);
+
+ return path.toFile();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorMessages.java
new file mode 100644
index 0000000..2f99776
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorMessages.java
@@ -0,0 +1,46 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpeclipse.obfuscator;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class ObfuscatorMessages {
+
+ private static final String RESOURCE_BUNDLE = ObfuscatorMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private ObfuscatorMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorMessages.properties
new file mode 100644
index 0000000..7fd4c12
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorMessages.properties
@@ -0,0 +1,9 @@
+#########################################
+# (c) Copyright IBM Corp. 2000, 2001.
+# All Rights Reserved.
+#########################################
+
+# obfuscator ignore list:
+Obfuscator.error.title=Error accessing obfuscator ignore list.
+Obfuscator.error.read=Error occurred while reading obfuscator ignore list.
+Obfuscator.error.write=Error occurred while writing obfuscator ignore list.
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorPass1Exporter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorPass1Exporter.java
new file mode 100644
index 0000000..7084482
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorPass1Exporter.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.obfuscator;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Analyzing php files in a first pass over all resources !
+ */
+public class ObfuscatorPass1Exporter implements ITerminalSymbols {
+
+ protected Scanner fScanner;
+
+ protected int fToken;
+
+ protected HashMap fIdentifierMap;
+
+ public ObfuscatorPass1Exporter(Scanner scanner, HashMap identifierMap) {
+ fScanner = scanner;
+ fIdentifierMap = identifierMap;
+ }
+
+ /**
+ * Get the next token from input
+ */
+ private void getNextToken() {
+
+ try {
+ fToken = fScanner.getNextToken();
+ if (Scanner.DEBUG) {
+ int currentEndPosition = fScanner.getCurrentTokenEndPosition();
+ int currentStartPosition = fScanner
+ .getCurrentTokenStartPosition();
+
+ System.out.print(currentStartPosition + ","
+ + currentEndPosition + ": ");
+ System.out.println(fScanner.toStringAction(fToken));
+ }
+ return;
+ } catch (InvalidInputException e) {
+
+ }
+ fToken = TokenNameERROR;
+ }
+
+ private void parseIdentifiers(boolean goBack) {
+ char[] ident;
+ String identifier;
+ PHPIdentifier value;
+ int counter = 0;
+
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ try {
+ while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
+ if (fToken == TokenNameVariable) {
+ identifier = new String(fScanner
+ .getCurrentIdentifierSource());
+ value = (PHPIdentifier) fIdentifierMap.get(identifier);
+ if (value == null) {
+ fIdentifierMap.put(identifier, new PHPIdentifier(null,
+ PHPIdentifier.VARIABLE));
+ }
+ getNextToken();
+ // } else if (fToken == TokenNamefunction) {
+ // getNextToken();
+ // if (fToken == TokenNameAND) {
+ // getNextToken();
+ // }
+ // if (fToken == TokenNameIdentifier) {
+ // ident = fScanner.getCurrentIdentifierSource();
+ // outlineInfo.addVariable(new String(ident));
+ // temp = new PHPFunctionDeclaration(current, new
+ // String(ident), fScanner.getCurrentTokenStartPosition());
+ // current.add(temp);
+ // getNextToken();
+ // parseDeclarations(outlineInfo, temp, true);
+ // }
+ // } else if (fToken == TokenNameclass) {
+ // getNextToken();
+ // if (fToken == TokenNameIdentifier) {
+ // ident = fScanner.getCurrentIdentifierSource();
+ // outlineInfo.addVariable(new String(ident));
+ // temp = new PHPClassDeclaration(current, new
+ // String(ident), fScanner.getCurrentTokenStartPosition());
+ // current.add(temp);
+ // getNextToken();
+ //
+ // //skip fTokens for classname, extends and others until we
+ // have the opening '{'
+ // while (fToken != TokenNameLBRACE && fToken !=
+ // TokenNameEOF && fToken != TokenNameERROR) {
+ // getNextToken();
+ // }
+ // parseDeclarations(outlineInfo, temp, true);
+ // // stack.pop();
+ // }
+ } else if (fToken == TokenNameStringDoubleQuote) {
+ char currentCharacter;
+ int i = fScanner.startPosition;
+ ArrayList varList = new ArrayList();
+
+ while (i < fScanner.currentPosition) {
+ currentCharacter = fScanner.source[i++];
+ if (currentCharacter == '$'
+ && fScanner.source[i - 2] != '\\') {
+ StringBuffer varName = new StringBuffer();
+ varName.append("$");
+ while (i < fScanner.currentPosition) {
+ currentCharacter = fScanner.source[i++];
+ if (!Scanner
+ .isPHPIdentifierPart(currentCharacter)) {
+ break; // while loop
+ }
+ varName.append(currentCharacter);
+ }
+ varList.add(varName.toString());
+ }
+ }
+
+ for (i = 0; i < varList.size(); i++) {
+ identifier = (String) varList.get(i);
+ value = (PHPIdentifier) fIdentifierMap.get(identifier);
+ if (value == null) {
+ fIdentifierMap.put(identifier, new PHPIdentifier(
+ null, PHPIdentifier.VARIABLE));
+ }
+ }
+
+ getNextToken();
+ } else if (fToken == TokenNameLBRACE) {
+ getNextToken();
+ counter++;
+ } else if (fToken == TokenNameRBRACE) {
+ getNextToken();
+ --counter;
+ if (counter == 0 && goBack) {
+ return;
+ }
+ } else {
+ getNextToken();
+ }
+ }
+ } catch (SyntaxError sytaxErr) {
+ // do nothing
+ }
+ }
+
+ /**
+ * Do nothing in first pass
+ */
+ public void createFolder(IPath destinationPath) {
+ // do nothing here
+ // new File(destinationPath.toOSString()).mkdir();
+ }
+
+ /**
+ * Writes the passed resource to the specified location recursively
+ */
+ public void write(IResource resource, IPath destinationPath)
+ throws CoreException, IOException {
+ if (resource.getType() == IResource.FILE)
+ writeFile((IFile) resource, destinationPath);
+ else
+ writeChildren((IContainer) resource, destinationPath);
+ }
+
+ /**
+ * Exports the passed container's children
+ */
+ protected void writeChildren(IContainer folder, IPath destinationPath)
+ throws CoreException, IOException {
+ if (folder.isAccessible()) {
+ IResource[] children = folder.members();
+ for (int i = 0; i < children.length; i++) {
+ IResource child = children[i];
+ writeResource(child, destinationPath.append(child.getName()));
+ }
+ }
+ }
+
+ /**
+ * Analyzes the passed file resource for the PHP obfuscator
+ */
+ protected void writeFile(IFile file, IPath destinationPath)
+ throws IOException, CoreException {
+ if (!PHPFileUtil.isPHPFile(file)) {
+ return;
+ }
+ InputStream stream = null;
+ char[] charArray = null;
+ try {
+ stream = new BufferedInputStream(file.getContents());
+ charArray = Util.getInputStreamAsCharArray(stream, -1, null);
+ } catch (IOException e) {
+ return;
+ } finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ if (charArray == null) {
+ // TODO show error message
+ return;
+ }
+ /* fScanner initialization */
+ fScanner.setSource(charArray);
+ fScanner.setPHPMode(false);
+ fToken = TokenNameEOF;
+ getNextToken();
+ parseIdentifiers(false);
+ }
+
+ /**
+ * Writes the passed resource to the specified location recursively
+ */
+ protected void writeResource(IResource resource, IPath destinationPath)
+ throws CoreException, IOException {
+ if (resource.getType() == IResource.FILE)
+ writeFile((IFile) resource, destinationPath);
+ else {
+ createFolder(destinationPath);
+ writeChildren((IContainer) resource, destinationPath);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorPass2Exporter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorPass2Exporter.java
new file mode 100644
index 0000000..7898633
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorPass2Exporter.java
@@ -0,0 +1,382 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.obfuscator;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Helper class for exporting resources to the file system.
+ */
+public class ObfuscatorPass2Exporter implements ITerminalSymbols {
+ private Scanner fScanner;
+
+ private int fToken;
+
+ private int fCounter;
+
+ protected HashMap fIdentifierMap;
+
+ public ObfuscatorPass2Exporter(Scanner scanner, HashMap identifierMap) {
+ fScanner = scanner;
+ fIdentifierMap = identifierMap;
+ fCounter = 0;
+ }
+
+ /**
+ * gets the next token from input
+ */
+ private void getNextToken() {
+
+ try {
+ fToken = fScanner.getNextToken();
+ if (Scanner.DEBUG) {
+ int currentEndPosition = fScanner.getCurrentTokenEndPosition();
+ int currentStartPosition = fScanner
+ .getCurrentTokenStartPosition();
+
+ System.out.print(currentStartPosition + ","
+ + currentEndPosition + ": ");
+ System.out.println(fScanner.toStringAction(fToken));
+ }
+ return;
+ } catch (InvalidInputException e) {
+
+ }
+ fToken = TokenNameERROR;
+ }
+
+ private boolean obfuscate(StringBuffer buf) {
+ char[] ident;
+ String identifier;
+ PHPIdentifier value;
+
+ int startPosition = 0;
+ int lastPosition = 0;
+
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ try {
+ while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
+ if (fToken == TokenNameVariable) {
+ identifier = new String(fScanner
+ .getCurrentIdentifierSource());
+ lastPosition = fScanner.startPosition;
+ int len = lastPosition - startPosition;
+ buf.append(fScanner.source, startPosition, len);
+ value = (PHPIdentifier) fIdentifierMap.get(identifier);
+ if (value != null) {
+ String obfuscatedIdentifier = value.getIdentifier();
+ if (obfuscatedIdentifier == null) {
+ buf.append("$v" + Integer.toString(fCounter));
+ value.setIdentifier("$v"
+ + Integer.toString(fCounter++));
+ } else {
+ buf.append(obfuscatedIdentifier);
+ }
+ // System.out.println(hexString.toString());
+ } else {
+ buf.append(identifier);
+ }
+ startPosition = fScanner.currentPosition;
+ getNextToken();
+ } else if (fToken == TokenNameIdentifier) {
+ identifier = new String(fScanner
+ .getCurrentIdentifierSource());
+ lastPosition = fScanner.startPosition;
+ int len = lastPosition - startPosition;
+ buf.append(fScanner.source, startPosition, len);
+ value = (PHPIdentifier) fIdentifierMap.get(identifier);
+ if (value != null) {
+ String obfuscatedIdentifier = value.getIdentifier();
+ if (obfuscatedIdentifier == null) {
+ buf.append("_" + Integer.toString(fCounter));
+ value.setIdentifier("_"
+ + Integer.toString(fCounter++));
+ } else {
+ buf.append(obfuscatedIdentifier);
+ }
+ // System.out.println(hexString.toString());
+ } else {
+ buf.append(identifier);
+ }
+ startPosition = fScanner.currentPosition;
+ getNextToken();
+
+ } else if (fToken == TokenNameCOMMENT_LINE
+ || fToken == TokenNameCOMMENT_BLOCK
+ || fToken == TokenNameCOMMENT_PHPDOC) {
+ lastPosition = fScanner.startPosition;
+ buf.append(fScanner.source, startPosition, lastPosition
+ - startPosition);
+ startPosition = fScanner.currentPosition;
+ getNextToken();
+ } else if (fToken == TokenNameStringDoubleQuote) {
+ char currentCharacter;
+ int i = fScanner.startPosition;
+ ArrayList varList = new ArrayList();
+
+ lastPosition = fScanner.startPosition;
+ int len = lastPosition - startPosition;
+ buf.append(fScanner.source, startPosition, len);
+
+ while (i < fScanner.currentPosition) {
+ currentCharacter = fScanner.source[i++];
+ if (currentCharacter == '$'
+ && fScanner.source[i - 2] != '\\') {
+ StringBuffer varName = new StringBuffer();
+ varName.append("$");
+ while (i < fScanner.currentPosition) {
+ currentCharacter = fScanner.source[i++];
+ if (!Scanner
+ .isPHPIdentifierPart(currentCharacter)) {
+ break; // while loop
+ }
+ varName.append(currentCharacter);
+ }
+ varList.add(varName.toString());
+ }
+ }
+ StringBuffer stringLiteral = new StringBuffer();
+ stringLiteral.append(fScanner.source,
+ fScanner.startPosition, fScanner.currentPosition
+ - fScanner.startPosition);
+ String stringIdent;
+ String replacement;
+ int index;
+
+ for (int j = 0; j < varList.size(); j++) {
+ stringIdent = (String) varList.get(j);
+ len = stringIdent.length();
+ value = (PHPIdentifier) fIdentifierMap.get(stringIdent);
+ if (value != null) {
+ String obfuscatedIdentifier = value.getIdentifier();
+ if (obfuscatedIdentifier == null) {
+ replacement = "$v" + Integer.toString(fCounter);
+ value.setIdentifier("$v"
+ + Integer.toString(fCounter++));
+ } else {
+ replacement = obfuscatedIdentifier;
+ }
+ // System.out.println(hexString.toString());
+ } else {
+ replacement = stringIdent;
+ }
+ index = stringLiteral.indexOf(stringIdent);
+ if (index >= 0) {
+ if (index > 0
+ && stringLiteral.charAt(index - 1) != '\\') {
+ stringLiteral.replace(index, index
+ + stringIdent.length(), replacement);
+ } else if (index == 0) {
+ stringLiteral.replace(index, index
+ + stringIdent.length(), replacement);
+ }
+ }
+ }
+ buf.append(stringLiteral);
+ startPosition = fScanner.currentPosition;
+ getNextToken();
+ }
+ if (fToken == TokenNameMINUS_GREATER) { // i.e. $this->var_name
+ getNextToken();
+ if (fToken == TokenNameIdentifier) {
+ // assuming this is a dereferenced variable
+ identifier = new String(fScanner
+ .getCurrentIdentifierSource());
+ lastPosition = fScanner.startPosition;
+ int len = lastPosition - startPosition;
+ buf.append(fScanner.source, startPosition, len);
+ value = (PHPIdentifier) fIdentifierMap.get("$"
+ + identifier);
+ if (value != null && value.isVariable()) {
+ String obfuscatedIdentifier = value.getIdentifier();
+ if (obfuscatedIdentifier == null) {
+ // note: don't place a $ before the identifier
+ buf.append("v" + Integer.toString(fCounter));
+ value.setIdentifier("$v"
+ + Integer.toString(fCounter++));
+ } else {
+ if (obfuscatedIdentifier.charAt(0) == '$') {
+ buf.append(obfuscatedIdentifier
+ .substring(1));
+ } else {
+ buf.append(obfuscatedIdentifier);
+ }
+ }
+ } else {
+ buf.append(identifier);
+ }
+ startPosition = fScanner.currentPosition;
+ getNextToken();
+ }
+
+ } else {
+ getNextToken();
+ }
+ }
+ if (startPosition < fScanner.source.length) {
+ buf.append(fScanner.source, startPosition,
+ fScanner.source.length - startPosition);
+ }
+ return true;
+ } catch (SyntaxError sytaxErr) {
+ // do nothing
+ }
+
+ return false;
+ }
+
+ /**
+ * Creates the specified file system directory at
+ * destinationPath
. This creates a new file system
+ * directory.
+ */
+ public void createFolder(IPath destinationPath) {
+ new File(destinationPath.toOSString()).mkdir();
+ }
+
+ /**
+ * Writes the passed resource to the specified location recursively
+ */
+ public void write(IResource resource, IPath destinationPath)
+ throws CoreException, IOException {
+ if (resource.getType() == IResource.FILE)
+ writeFile((IFile) resource, destinationPath);
+ else
+ writeChildren((IContainer) resource, destinationPath);
+ }
+
+ /**
+ * Exports the passed container's children
+ */
+ protected void writeChildren(IContainer folder, IPath destinationPath)
+ throws CoreException, IOException {
+ if (folder.isAccessible()) {
+ IResource[] children = folder.members();
+ for (int i = 0; i < children.length; i++) {
+ IResource child = children[i];
+ writeResource(child, destinationPath.append(child.getName()));
+ }
+ }
+ }
+
+ /**
+ * Writes the passed file resource to the specified destination on the local
+ * file system
+ */
+ protected void writeFile(IFile file, IPath destinationPath)
+ throws IOException, CoreException {
+ if (PHPFileUtil.isPHPFile(file)) {
+ InputStream stream = null;
+ char[] charArray = null;
+ try {
+ stream = new BufferedInputStream(file.getContents());
+ charArray = Util.getInputStreamAsCharArray(stream, -1, null);
+ } catch (IOException e) {
+ return;
+ } finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ if (charArray == null) {
+ // TODO show error message
+ return;
+ }
+
+ fScanner.setSource(charArray);
+ fScanner.setPHPMode(false);
+ fToken = TokenNameEOF;
+ getNextToken();
+
+ StringBuffer buf = new StringBuffer();
+ if (!obfuscate(buf)) {
+ copyFile(file, destinationPath);
+ } else {
+ // charArray = buf.toString().toCharArray();
+ // File targetFile = new File(destinationPath.toOSString());
+ BufferedWriter bw = new BufferedWriter(new FileWriter(
+ destinationPath.toOSString()));
+ bw.write(buf.toString());
+ bw.close();
+ }
+
+ } else {
+ copyFile(file, destinationPath);
+ }
+ }
+
+ private void copyFile(IFile file, IPath destinationPath)
+ throws FileNotFoundException, CoreException, IOException {
+ FileOutputStream output = null;
+ InputStream contentStream = null;
+
+ try {
+ output = new FileOutputStream(destinationPath.toOSString());
+ contentStream = file.getContents(false);
+ int chunkSize = contentStream.available();
+ byte[] readBuffer = new byte[chunkSize];
+ int n = contentStream.read(readBuffer);
+
+ while (n > 0) {
+ output.write(readBuffer);
+ n = contentStream.read(readBuffer);
+ }
+ } finally {
+ if (output != null)
+ output.close();
+ if (contentStream != null)
+ contentStream.close();
+ }
+ }
+
+ /**
+ * Writes the passed resource to the specified location recursively
+ */
+ protected void writeResource(IResource resource, IPath destinationPath)
+ throws CoreException, IOException {
+ if (resource.getType() == IResource.FILE)
+ writeFile((IFile) resource, destinationPath);
+ else {
+ createFolder(destinationPath);
+ writeChildren((IContainer) resource, destinationPath);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/PHPIdentifier.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/PHPIdentifier.java
new file mode 100644
index 0000000..53369ef
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/PHPIdentifier.java
@@ -0,0 +1,119 @@
+package net.sourceforge.phpeclipse.obfuscator;
+
+/**
+ * Object which holds an PHP identifier name (i.e. class, function,
+ * variable,...)
+ *
+ */
+public class PHPIdentifier {
+
+ public final static int CLASS = 1;
+
+ public final static int FUNCTION = 2;
+
+ public final static int VARIABLE = 3;
+
+ public final static int METHOD = 4;
+
+ public final static int DEFINE = 5;
+
+ public final static int CONSTRUCTOR = 6;
+
+ public final static int GLOBAL_VARIABLE = 7;
+
+ public final static int EXTENDS = 8;
+
+ public final static int IMPLEMENTS = 9;
+
+ private String fIdentifier;
+
+ private int fType;
+
+ public PHPIdentifier(String identifier, int type) {
+ fType = type;
+ fIdentifier = identifier;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof PHPIdentifier)) {
+ return false;
+ }
+ return ((PHPIdentifier) obj).fType == fType
+ && ((PHPIdentifier) obj).fIdentifier.equals(fIdentifier);
+ }
+
+ public String getIdentifier() {
+ return fIdentifier;
+ }
+
+ public int getType() {
+ return fType;
+ }
+
+ public boolean isClass() {
+ return fType == CLASS;
+ }
+
+ public boolean isFunction() {
+ return fType == FUNCTION;
+ }
+
+ public boolean isVariable() {
+ return fType == VARIABLE;
+ }
+
+ public boolean isMethod() {
+ return fType == METHOD;
+ }
+
+ public boolean isDefine() {
+ return fType == DEFINE;
+ }
+
+ public boolean isGlobalVariable() {
+ return fType == GLOBAL_VARIABLE;
+ }
+
+ public boolean isConstructor() {
+ return fType == CONSTRUCTOR;
+ }
+
+ public void setIdentifier(String fIdentifier) {
+ this.fIdentifier = fIdentifier;
+ }
+
+ public void setType(int fType) {
+ this.fType = fType;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ switch (fType) {
+ case CLASS:
+ return "class - ";
+ case CONSTRUCTOR:
+ return "constructor - ";
+ case DEFINE:
+ return "define - ";
+ case FUNCTION:
+ return "function - ";
+ case GLOBAL_VARIABLE:
+ return "global variable - ";
+ case METHOD:
+ return "method - ";
+ case VARIABLE:
+ return "variable - ";
+ }
+ return "";
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/default-obfuscator.xml b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/default-obfuscator.xml
new file mode 100644
index 0000000..bd85d37
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/default-obfuscator.xml
@@ -0,0 +1,62 @@
+
+
+ $this
+ $_COOKIE
+ $_ENV
+ $_FILES
+ $_GET
+ $_POST
+ $_REQUEST
+ $_SERVER
+ $_SESSION
+ $argc
+ $argv
+ $AUTH_TYPE
+ $CONTENT_LENGTH
+ $CONTENT_TYPE
+ $DOCUMENT_ROOT
+ $GATEWAY_INTERFACE
+ $GLOBALS
+ $HTTP_ACCEPT
+ $HTTP_ACCEPT_ENCODING
+ $HTTP_ACCEPT_LANGUAGE
+ $HTTP_CACHE_CONTROL
+ $HTTP_CONNECTION
+ $HTTP_COOKIE
+ $HTTP_COOKIE_VARS
+ $HTTP_ENV_VARS
+ $HTTP_GET_VARS
+ $HTTP_HOST
+ $HTTP_HOST_FILES
+ $HTTP_POST_VARS
+ $HTTP_SERVER_VARS
+ $HTTP_SESSION_VARS
+ $HTTP_REFERER
+ $HTTP_USER_AGENT
+ $PATH
+ $PATH_INFO
+ $PATH_TRANSLATED
+ $PHP_AUTH_PW
+ $PHP_AUTH_USER
+ $PHP_ERRORMSG
+ $PHP_SELF
+ $QUERY_STRING
+ $REDIRECT_STATUS
+ $REDIRECT_URL
+ $REMOTE_ADDR
+ $REMOTE_HOST
+ $REMOTE_IDENT
+ $REMOTE_PORT
+ $REMOTE_USER
+ $REQUEST_METHOD
+ $REQUEST_URI
+ $SCRIPT_FILENAME
+ $SCRIPT_NAME
+ $SERVER_ADDR
+ $SERVER_ADMIN
+ $SERVER_NAME
+ $SERVER_PORT
+ $SERVER_PROTOCOL
+ $SERVER_SIGNATURE
+ $SERVER_SOFTWARE
+
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportMessages.java
new file mode 100644
index 0000000..3878513
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportMessages.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.obfuscator.export;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class which helps managing messages
+ */
+class ObfuscatorExportMessages {
+ private static final String RESOURCE_BUNDLE = "net.sourceforge.phpeclipse.obfuscator.export.messages";//$NON-NLS-1$
+
+ private static ResourceBundle bundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private ObfuscatorExportMessages() {
+ // prevent instantiation of class
+ }
+
+ /**
+ * Returns the formatted message for the given key in the resource bundle.
+ *
+ * @param key
+ * the resource name
+ * @param args
+ * the message arguments
+ * @return the string
+ */
+ public static String format(String key, Object[] args) {
+ return MessageFormat.format(getString(key), args);
+ }
+
+ /**
+ * Returns the resource object with the given key in the resource bundle. If
+ * there isn't any value under the given key, the key is returned.
+ *
+ * @param key
+ * the resource name
+ * @return the string
+ */
+ public static String getString(String key) {
+ try {
+ return bundle.getString(key);
+ } catch (MissingResourceException e) {
+ return key;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportOperation.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportOperation.java
new file mode 100644
index 0000000..2c9d808
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportOperation.java
@@ -0,0 +1,742 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.obfuscator.export;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.obfuscator.ObfuscatorIgnores;
+import net.sourceforge.phpeclipse.obfuscator.ObfuscatorPass1Exporter;
+import net.sourceforge.phpeclipse.obfuscator.ObfuscatorPass2Exporter;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+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.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+
+/**
+ * Operation for exporting the contents of a resource to the local file system.
+ */
+/* package */
+class ObfuscatorExportOperation implements IRunnableWithProgress {
+ private IPath fPath;
+
+ private IProgressMonitor fMonitor;
+
+ private ObfuscatorPass1Exporter fExporter1 = null;
+
+ private ObfuscatorPass2Exporter fExporter2 = null;
+
+ private HashMap fCurrentIdentifierMap = null;
+
+ private HashMap fProjectMap = null;
+
+ private String fCurrentProjectName = "";
+
+ private List fResourcesToExport;
+
+ private IOverwriteQuery fOverwriteCallback;
+
+ private IResource fResource;
+
+ private List errorTable = new ArrayList(1);
+
+ // The constants for the overwrite 3 state
+ private static final int OVERWRITE_NOT_SET = 0;
+
+ private static final int OVERWRITE_NONE = 1;
+
+ private static final int OVERWRITE_ALL = 2;
+
+ private int overwriteState = OVERWRITE_NOT_SET;
+
+ // private boolean createLeadupStructure = true;
+ private boolean createContainerDirectories = true;
+
+ /**
+ * Create an instance of this class. Use this constructor if you wish to
+ * export specific resources without a common parent resource
+ */
+ // public ObfuscatorExportOperation(List resources, String destinationPath,
+ // IOverwriteQuery overwriteImplementor) {
+ // super();
+ //
+ // exporter1 = new ObfuscatorPass1Exporter(new Scanner(false, false),
+ // identifierMap);
+ // exporter2 = new ObfuscatorPass2Exporter(new Scanner(true, true),
+ // identifierMap);
+ // identifierMap = null;
+ //
+ // // Eliminate redundancies in list of resources being exported
+ // Iterator elementsEnum = resources.iterator();
+ // while (elementsEnum.hasNext()) {
+ // IResource currentResource = (IResource) elementsEnum.next();
+ // if (isDescendent(resources, currentResource))
+ // elementsEnum.remove(); //Remove currentResource
+ // }
+ //
+ // resourcesToExport = resources;
+ // path = new Path(destinationPath);
+ // overwriteCallback = overwriteImplementor;
+ // }
+ /**
+ * Create an instance of this class. Use this constructor if you wish to
+ * recursively export a single resource
+ */
+ public ObfuscatorExportOperation(IResource res, String destinationPath,
+ IOverwriteQuery overwriteImplementor) {
+ super();
+
+ fResource = res;
+ fPath = new Path(destinationPath);
+ fOverwriteCallback = overwriteImplementor;
+ }
+
+ /**
+ * Create an instance of this class. Use this constructor if you wish to
+ * export specific resources with a common parent resource (affects
+ * container directory creation)
+ */
+ public ObfuscatorExportOperation(IResource res, List resources,
+ String destinationPath, IOverwriteQuery overwriteImplementor) {
+ this(res, destinationPath, overwriteImplementor);
+ fResourcesToExport = resources;
+ }
+
+ /**
+ * Add a new entry to the error table with the passed information
+ */
+ protected void addError(String message, Throwable e) {
+ errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
+ message, e));
+ }
+
+ /**
+ * Answer the total number of file resources that exist at or below self in
+ * the resources hierarchy.
+ *
+ * @return int
+ * @param resource
+ * org.eclipse.core.resources.IResource
+ */
+ protected int countChildrenOf(IResource resource) throws CoreException {
+ if (resource.getType() == IResource.FILE)
+ return 1;
+
+ int count = 0;
+ if (resource.isAccessible()) {
+ IResource[] children = ((IContainer) resource).members();
+ for (int i = 0; i < children.length; i++)
+ count += countChildrenOf(children[i]);
+ }
+
+ return count;
+ }
+
+ /**
+ * Answer a boolean indicating the number of file resources that were
+ * specified for export
+ *
+ * @return int
+ */
+ protected int countSelectedResources() throws CoreException {
+ int result = 0;
+ Iterator resources = fResourcesToExport.iterator();
+
+ while (resources.hasNext())
+ result += countChildrenOf((IResource) resources.next());
+
+ return result;
+ }
+
+ /**
+ * Create the directories required for exporting the passed resource, based
+ * upon its container hierarchy
+ *
+ * @param resource
+ * org.eclipse.core.resources.IResource
+ */
+ protected void createLeadupDirectoriesFor(IResource resource) {
+ IPath resourcePath = resource.getFullPath().removeLastSegments(1);
+
+ for (int i = 0; i < resourcePath.segmentCount(); i++) {
+ fPath = fPath.append(resourcePath.segment(i));
+ fExporter2.createFolder(fPath);
+ }
+ }
+
+ /**
+ * Recursively export the previously-specified resource
+ */
+ protected void exportAllResources1() throws InterruptedException {
+ if (fResource.getType() == IResource.FILE) {
+ exportFile1((IFile) fResource, fPath);
+ } else {
+ try {
+ setExporters(fResource);
+ exportChildren1(((IContainer) fResource).members(), fPath);
+ } catch (CoreException e) {
+ // not safe to show a dialog
+ // should never happen because the file system export wizard
+ // ensures that the
+ // single resource chosen for export is both existent and
+ // accessible
+ errorTable.add(e);
+ }
+ }
+ }
+
+ /**
+ * Recursively export the previously-specified resource
+ */
+ protected void exportAllResources2() throws InterruptedException {
+ if (fResource.getType() == IResource.FILE) {
+ exportFile2((IFile) fResource, fPath);
+ } else {
+ try {
+ setExporters(fResource);
+ exportChildren2(((IContainer) fResource).members(), fPath);
+ } catch (CoreException e) {
+ // not safe to show a dialog
+ // should never happen because the file system export wizard
+ // ensures that the
+ // single resource chosen for export is both existent and
+ // accessible
+ errorTable.add(e);
+ }
+ }
+ }
+
+ /**
+ * Export all of the resources contained in the passed collection
+ *
+ * @param children
+ * java.util.Enumeration
+ * @param currentPath
+ * IPath
+ */
+ protected void exportChildren1(IResource[] children, IPath currentPath)
+ throws InterruptedException {
+ for (int i = 0; i < children.length; i++) {
+ IResource child = children[i];
+ if (!child.isAccessible())
+ continue;
+
+ if (child.getType() == IResource.FILE)
+ exportFile1((IFile) child, currentPath);
+ else {
+ IPath destination = currentPath.append(child.getName());
+ fExporter1.createFolder(destination);
+ try {
+ exportChildren1(((IContainer) child).members(), destination);
+ } catch (CoreException e) {
+ // not safe to show a dialog
+ // should never happen because:
+ // i. this method is called recursively iterating over the
+ // result of #members,
+ // which only answers existing children
+ // ii. there is an #isAccessible check done before #members
+ // is invoked
+ errorTable.add(e.getStatus());
+ }
+ }
+ }
+ }
+
+ /**
+ * Export all of the resources contained in the passed collection
+ *
+ * @param children
+ * java.util.Enumeration
+ * @param currentPath
+ * IPath
+ */
+ protected void exportChildren2(IResource[] children, IPath currentPath)
+ throws InterruptedException {
+ for (int i = 0; i < children.length; i++) {
+ IResource child = children[i];
+ if (!child.isAccessible())
+ continue;
+
+ if (child.getType() == IResource.FILE)
+ exportFile2((IFile) child, currentPath);
+ else {
+ IPath destination = currentPath.append(child.getName());
+ fExporter2.createFolder(destination);
+ try {
+ exportChildren2(((IContainer) child).members(), destination);
+ } catch (CoreException e) {
+ // not safe to show a dialog
+ // should never happen because:
+ // i. this method is called recursively iterating over the
+ // result of #members,
+ // which only answers existing children
+ // ii. there is an #isAccessible check done before #members
+ // is invoked
+ errorTable.add(e.getStatus());
+ }
+ }
+ }
+ }
+
+ protected void exportFile1(IFile file, IPath location)
+ throws InterruptedException {
+ IPath fullPath = location.append(file.getName());
+ fMonitor.subTask(file.getFullPath().toString());
+ String properPathString = fullPath.toOSString();
+ File targetFile = new File(properPathString);
+
+ // if (targetFile.exists()) {
+ // if (!targetFile.canWrite()) {
+ // errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
+ // ObfuscatorExportMessages.format("ObfuscatorTransfer.cannotOverwrite",
+ // //$NON-NLS-1$
+ // new Object[] { targetFile.getAbsolutePath()}), null));
+ // monitor.worked(1);
+ // return;
+ // }
+ //
+ // if (overwriteState == OVERWRITE_NONE)
+ // return;
+ //
+ // if (overwriteState != OVERWRITE_ALL) {
+ // String overwriteAnswer =
+ // overwriteCallback.queryOverwrite(properPathString);
+ //
+ // if (overwriteAnswer.equals(IOverwriteQuery.CANCEL))
+ // throw new InterruptedException();
+ //
+ // if (overwriteAnswer.equals(IOverwriteQuery.NO)) {
+ // monitor.worked(1);
+ // return;
+ // }
+ //
+ // if (overwriteAnswer.equals(IOverwriteQuery.NO_ALL)) {
+ // monitor.worked(1);
+ // overwriteState = OVERWRITE_NONE;
+ // return;
+ // }
+ //
+ // if (overwriteAnswer.equals(IOverwriteQuery.ALL))
+ // overwriteState = OVERWRITE_ALL;
+ // }
+ // }
+
+ try {
+ setExporters(file);
+ fExporter1.write(file, fullPath);
+ } catch (IOException e) {
+ errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
+ ObfuscatorExportMessages.format(
+ "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
+ new Object[] { fullPath, e.getMessage() }), e));
+ } catch (CoreException e) {
+ errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
+ ObfuscatorExportMessages.format(
+ "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
+ new Object[] { fullPath, e.getMessage() }), e));
+ }
+
+ fMonitor.worked(1);
+ ModalContext.checkCanceled(fMonitor);
+ }
+
+ /**
+ * Export the passed file to the specified location
+ *
+ * @param file
+ * org.eclipse.core.resources.IFile
+ * @param location
+ * org.eclipse.core.runtime.IPath
+ */
+ protected void exportFile2(IFile file, IPath location)
+ throws InterruptedException {
+ IPath fullPath = location.append(file.getName());
+ fMonitor.subTask(file.getFullPath().toString());
+ String properPathString = fullPath.toOSString();
+ File targetFile = new File(properPathString);
+
+ if (targetFile.exists()) {
+ if (!targetFile.canWrite()) {
+ errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
+ 0, ObfuscatorExportMessages.format(
+ "ObfuscatorTransfer.cannotOverwrite", //$NON-NLS-1$
+ new Object[] { targetFile.getAbsolutePath() }),
+ null));
+ fMonitor.worked(1);
+ return;
+ }
+
+ if (overwriteState == OVERWRITE_NONE)
+ return;
+
+ if (overwriteState != OVERWRITE_ALL) {
+ String overwriteAnswer = fOverwriteCallback
+ .queryOverwrite(properPathString);
+
+ if (overwriteAnswer.equals(IOverwriteQuery.CANCEL))
+ throw new InterruptedException();
+
+ if (overwriteAnswer.equals(IOverwriteQuery.NO)) {
+ fMonitor.worked(1);
+ return;
+ }
+
+ if (overwriteAnswer.equals(IOverwriteQuery.NO_ALL)) {
+ fMonitor.worked(1);
+ overwriteState = OVERWRITE_NONE;
+ return;
+ }
+
+ if (overwriteAnswer.equals(IOverwriteQuery.ALL))
+ overwriteState = OVERWRITE_ALL;
+ }
+ }
+
+ try {
+ setExporters(file);
+ fExporter2.write(file, fullPath);
+ } catch (IOException e) {
+ errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
+ ObfuscatorExportMessages.format(
+ "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
+ new Object[] { fullPath, e.getMessage() }), e));
+ } catch (CoreException e) {
+ errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
+ ObfuscatorExportMessages.format(
+ "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
+ new Object[] { fullPath, e.getMessage() }), e));
+ }
+
+ fMonitor.worked(1);
+ ModalContext.checkCanceled(fMonitor);
+ }
+
+ protected void exportSpecifiedResources1() throws InterruptedException {
+ Iterator resources = fResourcesToExport.iterator();
+ IPath initPath = (IPath) fPath.clone();
+
+ while (resources.hasNext()) {
+ IResource currentResource = (IResource) resources.next();
+ if (!currentResource.isAccessible())
+ continue;
+ setExporters(currentResource);
+ fPath = initPath;
+
+ if (fResource == null) {
+ // No root resource specified and creation of containment
+ // directories
+ // is required. Create containers from depth 2 onwards (ie.-
+ // project's
+ // child inclusive) for each resource being exported.
+ // if (createLeadupStructure)
+ // createLeadupDirectoriesFor(currentResource);
+
+ } else {
+ // Root resource specified. Must create containment directories
+ // from this point onwards for each resource being exported
+ IPath containersToCreate = currentResource.getFullPath()
+ .removeFirstSegments(
+ fResource.getFullPath().segmentCount())
+ .removeLastSegments(1);
+
+ for (int i = 0; i < containersToCreate.segmentCount(); i++) {
+ fPath = fPath.append(containersToCreate.segment(i));
+ fExporter1.createFolder(fPath);
+ }
+ }
+
+ if (currentResource.getType() == IResource.FILE)
+ exportFile1((IFile) currentResource, fPath);
+ else {
+ if (createContainerDirectories) {
+ fPath = fPath.append(currentResource.getName());
+ fExporter1.createFolder(fPath);
+ }
+
+ try {
+ exportChildren1(((IContainer) currentResource).members(),
+ fPath);
+ } catch (CoreException e) {
+ // should never happen because #isAccessible is called
+ // before #members is invoked,
+ // which implicitly does an existence check
+ errorTable.add(e.getStatus());
+ }
+ }
+ }
+ }
+
+ /**
+ * Export the resources contained in the previously-defined
+ * resourcesToExport collection
+ */
+ protected void exportSpecifiedResources2() throws InterruptedException {
+ Iterator resources = fResourcesToExport.iterator();
+ IPath initPath = (IPath) fPath.clone();
+
+ while (resources.hasNext()) {
+ IResource currentResource = (IResource) resources.next();
+ if (!currentResource.isAccessible())
+ continue;
+ setExporters(currentResource);
+
+ fPath = initPath;
+
+ if (fResource == null) {
+ // No root resource specified and creation of containment
+ // directories
+ // is required. Create containers from depth 2 onwards (ie.-
+ // project's
+ // child inclusive) for each resource being exported.
+ // if (createLeadupStructure)
+ // createLeadupDirectoriesFor(currentResource);
+
+ } else {
+ // Root resource specified. Must create containment directories
+ // from this point onwards for each resource being exported
+ IPath containersToCreate = currentResource.getFullPath()
+ .removeFirstSegments(
+ fResource.getFullPath().segmentCount())
+ .removeLastSegments(1);
+
+ for (int i = 0; i < containersToCreate.segmentCount(); i++) {
+ fPath = fPath.append(containersToCreate.segment(i));
+ fExporter2.createFolder(fPath);
+ }
+ }
+
+ if (currentResource.getType() == IResource.FILE)
+ exportFile2((IFile) currentResource, fPath);
+ else {
+ if (createContainerDirectories) {
+ fPath = fPath.append(currentResource.getName());
+ fExporter2.createFolder(fPath);
+ }
+
+ try {
+ exportChildren2(((IContainer) currentResource).members(),
+ fPath);
+ } catch (CoreException e) {
+ // should never happen because #isAccessible is called
+ // before #members is invoked,
+ // which implicitly does an existence check
+ errorTable.add(e.getStatus());
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the status of the export operation. If there were any errors, the
+ * result is a status object containing individual status objects for each
+ * error. If there were no errors, the result is a status object with error
+ * code OK
.
+ *
+ * @return the status
+ */
+ public IStatus getStatus() {
+ IStatus[] errors = new IStatus[errorTable.size()];
+ errorTable.toArray(errors);
+ return new MultiStatus(
+ PlatformUI.PLUGIN_ID,
+ IStatus.OK,
+ errors,
+ ObfuscatorExportMessages
+ .getString("ObfuscatorExportOperation.problemsExporting"), //$NON-NLS-1$
+ null);
+ }
+
+ /**
+ * Answer a boolean indicating whether the passed child is a descendent of
+ * one or more members of the passed resources collection
+ *
+ * @return boolean
+ * @param resources
+ * java.util.List
+ * @param child
+ * org.eclipse.core.resources.IResource
+ */
+ protected boolean isDescendent(List resources, IResource child) {
+ if (child.getType() == IResource.PROJECT)
+ return false;
+
+ IResource parent = child.getParent();
+ if (resources.contains(parent))
+ return true;
+
+ return isDescendent(resources, parent);
+ }
+
+ private void setExporters(IResource resource) {
+ if (fCurrentIdentifierMap == null) {
+ if (fProjectMap == null) {
+ fProjectMap = new HashMap();
+ }
+ createExporters(resource);
+ } else {
+ IProject project = resource.getProject();
+ if (!fCurrentProjectName.equals(project.getName())) {
+ HashMap temp = (HashMap) fProjectMap.get(project.getName());
+ if (temp != null) {
+ fCurrentProjectName = project.getName();
+ fCurrentIdentifierMap = temp;
+ fExporter1 = new ObfuscatorPass1Exporter(new Scanner(false,
+ false), fCurrentIdentifierMap);
+ fExporter2 = new ObfuscatorPass2Exporter(new Scanner(true,
+ true), fCurrentIdentifierMap);
+ return;
+ }
+ createExporters(resource);
+ }
+ }
+ }
+
+ private void createExporters(IResource resource) {
+ IProject project = resource.getProject();
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ ObfuscatorIgnores ignore = new ObfuscatorIgnores(project);
+ fCurrentIdentifierMap = ignore.getIdentifierMap();
+ fCurrentProjectName = project.getName();
+ fProjectMap.put(fCurrentProjectName, fCurrentIdentifierMap);
+ fExporter1 = new ObfuscatorPass1Exporter(new Scanner(false, false),
+ fCurrentIdentifierMap);
+ fExporter2 = new ObfuscatorPass2Exporter(new Scanner(true, true),
+ fCurrentIdentifierMap);
+ }
+
+ /**
+ * Export the resources that were previously specified for export (or if a
+ * single resource was specified then export it recursively)
+ */
+ public void run(IProgressMonitor monitor) throws InterruptedException {
+ this.fMonitor = monitor;
+ final IPath tempPath = (IPath) fPath.clone();
+ if (fResource != null) {
+ setExporters(fResource);
+ // if (createLeadupStructure)
+ // createLeadupDirectoriesFor(resource);
+
+ if (createContainerDirectories
+ && fResource.getType() != IResource.FILE) {
+ // ensure it's a container
+ fPath = fPath.append(fResource.getName());
+ fExporter2.createFolder(fPath);
+ }
+ }
+
+ try {
+ // reset variables for this run:
+ fCurrentIdentifierMap = null;
+ fProjectMap = null;
+ fCurrentProjectName = "";
+
+ // count number of files
+ int totalWork = IProgressMonitor.UNKNOWN;
+ try {
+ if (fResourcesToExport == null) {
+ totalWork = countChildrenOf(fResource);
+ } else {
+ totalWork = countSelectedResources();
+ }
+ } catch (CoreException e) {
+ // Should not happen
+ errorTable.add(e.getStatus());
+ }
+ monitor
+ .beginTask(
+ ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.exportingTitle1"), totalWork); //$NON-NLS-1$
+ if (fResourcesToExport == null) {
+ exportAllResources1();
+ } else {
+ exportSpecifiedResources1();
+ }
+
+ // try {
+ // if (resourcesToExport == null)
+ // totalWork = countChildrenOf(resource);
+ // else
+ // totalWork = countSelectedResources();
+ // } catch (CoreException e) {
+ // // Should not happen
+ // errorTable.add(e.getStatus());
+ // }
+
+ // reset path:
+ fPath = tempPath;
+ monitor
+ .beginTask(
+ ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.exportingTitle2"), totalWork); //$NON-NLS-1$
+ if (fResourcesToExport == null) {
+ exportAllResources2();
+ } else {
+ exportSpecifiedResources2();
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Set this boolean indicating whether a directory should be created for
+ * Folder resources that are explicitly passed for export
+ *
+ * @param value
+ * boolean
+ */
+ // public void setCreateContainerDirectories(boolean value) {
+ // createContainerDirectories = value;
+ // }
+ /**
+ * Set this boolean indicating whether each exported resource's complete
+ * path should include containment hierarchies as dictated by its parents
+ *
+ * @param value
+ * boolean
+ */
+ // public void setCreateLeadupStructure(boolean value) {
+ // createLeadupStructure = value;
+ // }
+ /**
+ * Set this boolean indicating whether exported resources should
+ * automatically overwrite existing files when a conflict occurs. If not
+ * query the user.
+ *
+ * @param value
+ * boolean
+ */
+ public void setOverwriteFiles(boolean value) {
+ if (value)
+ overwriteState = OVERWRITE_ALL;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportWizard.java
new file mode 100644
index 0000000..5111b04
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportWizard.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.obfuscator.export;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IExportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ * Standard workbench wizard for exporting resources from the workspace to the
+ * local file system.
+ *
+ * This class may be instantiated and used without further configuration; this
+ * class is not intended to be subclassed.
+ *
+ *
+ * Example:
+ *
+ *
+ * IWizard wizard = new ObfuscatorExportWizard();
+ * wizard.init(workbench, selection);
+ * WizardDialog dialog = new WizardDialog(shell, wizard);
+ * dialog.open();
+ *
+ *
+ * During the call to open
, the wizard dialog is presented to
+ * the user. When the user hits Finish, the user-selected workspace resources
+ * are exported to the user-specified location in the local file system, the
+ * dialog closes, and the call to open
returns.
+ *
+ */
+public class ObfuscatorExportWizard extends Wizard implements IExportWizard {
+ private IWorkbench workbench;
+
+ private IStructuredSelection selection;
+
+ private WizardObfuscatorResourceExportPage1 mainPage;
+
+ /**
+ * Creates a wizard for exporting workspace resources to the local file
+ * system.
+ */
+ public ObfuscatorExportWizard() {
+ AbstractUIPlugin plugin = (AbstractUIPlugin) Platform
+ .getPlugin(PlatformUI.PLUGIN_ID);
+ IDialogSettings workbenchSettings = plugin.getDialogSettings();
+ IDialogSettings section = workbenchSettings
+ .getSection("ObfuscatorExportWizard");//$NON-NLS-1$
+ if (section == null)
+ section = workbenchSettings.addNewSection("ObfuscatorExportWizard");//$NON-NLS-1$
+ setDialogSettings(section);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWizard.
+ */
+ public void addPages() {
+ super.addPages();
+ mainPage = new WizardObfuscatorResourceExportPage1(selection);
+ addPage(mainPage);
+ }
+
+ /**
+ * Returns the image descriptor with the given relative path.
+ */
+ private ImageDescriptor getImageDescriptor(String relativePath) {
+ String iconPath = "icons/full/";//$NON-NLS-1$
+ try {
+ AbstractUIPlugin plugin = (AbstractUIPlugin) Platform
+ .getPlugin(PlatformUI.PLUGIN_ID);
+ URL installURL = plugin.getBundle().getEntry("/");
+ URL url = new URL(installURL, iconPath + relativePath);
+ return ImageDescriptor.createFromURL(url);
+ } catch (MalformedURLException e) {
+ // Should not happen
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWorkbenchWizard.
+ */
+ public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
+ this.workbench = workbench;
+
+ // Make it the current selection by default but look it up otherwise
+
+ selection = currentSelection;
+
+ if (currentSelection.isEmpty()
+ && workbench.getActiveWorkbenchWindow() != null) {
+ IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
+ .getActivePage();
+ if (page != null) {
+ IEditorPart currentEditor = page.getActiveEditor();
+ if (currentEditor != null) {
+ Object selectedResource = currentEditor.getEditorInput()
+ .getAdapter(IResource.class);
+ if (selectedResource != null)
+ selection = new StructuredSelection(selectedResource);
+ }
+ }
+ }
+
+ setWindowTitle(ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.export")); //$NON-NLS-1$
+ setDefaultPageImageDescriptor(getImageDescriptor("wizban/exportdir_wiz.gif"));//$NON-NLS-1$
+ setNeedsProgressMonitor(true);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWizard.
+ */
+ public boolean performFinish() {
+ return mainPage.finish();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/WizardObfuscatorResourceExportPage1.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/WizardObfuscatorResourceExportPage1.java
new file mode 100644
index 0000000..276c8e5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/WizardObfuscatorResourceExportPage1.java
@@ -0,0 +1,505 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.obfuscator.export;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+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.DirectoryDialog;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.dialogs.WizardExportResourcesPage;
+
+/**
+ * Page 1 of the base resource export-to-file-system Wizard
+ */
+/* package */
+class WizardObfuscatorResourceExportPage1 extends WizardExportResourcesPage
+ implements Listener {
+
+ // widgets
+ private Combo destinationNameField;
+
+ private Button destinationBrowseButton;
+
+ protected Button overwriteExistingFilesCheckbox;
+
+ // protected Button createDirectoryStructureButton;
+ // protected Button createSelectionOnlyButton;
+
+ // constants
+ private static final int SIZING_TEXT_FIELD_WIDTH = 250;
+
+ // dialog store id constants
+ private static final String STORE_DESTINATION_NAMES_ID = "WizardObfuscatorResourceExportPage1.STORE_DESTINATION_NAMES_ID"; //$NON-NLS-1$
+
+ private static final String STORE_OVERWRITE_EXISTING_FILES_ID = "WizardObfuscatorResourceExportPage1.STORE_OVERWRITE_EXISTING_FILES_ID"; //$NON-NLS-1$
+ // private static final String STORE_CREATE_STRUCTURE_ID =
+ // "WizardObfuscatorResourceExportPage1.STORE_CREATE_STRUCTURE_ID";
+ // //$NON-NLS-1$
+
+ // messages
+ private static final String SELECT_DESTINATION_MESSAGE = ObfuscatorExportMessages
+ .getString("FileExport.selectDestinationMessage"); //$NON-NLS-1$
+
+ private static final String SELECT_DESTINATION_TITLE = ObfuscatorExportMessages
+ .getString("FileExport.selectDestinationTitle"); //$NON-NLS-1$
+
+ /**
+ * Create an instance of this class
+ */
+ protected WizardObfuscatorResourceExportPage1(String name,
+ IStructuredSelection selection) {
+ super(name, selection);
+ }
+
+ /**
+ * Create an instance of this class
+ */
+ public WizardObfuscatorResourceExportPage1(IStructuredSelection selection) {
+ this("fileSystemExportPage1", selection); //$NON-NLS-1$
+ setTitle(ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.fileSystemTitle")); //$NON-NLS-1$
+ setDescription(ObfuscatorExportMessages
+ .getString("FileExport.exportLocalFileSystem")); //$NON-NLS-1$
+ }
+
+ /**
+ * Add the passed value to self's destination widget's history
+ *
+ * @param value
+ * java.lang.String
+ */
+ protected void addDestinationItem(String value) {
+ destinationNameField.add(value);
+ }
+
+ /**
+ * (non-Javadoc) Method declared on IDialogPage.
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ giveFocusToDestination();
+ // WorkbenchHelp.setHelp(
+ // getControl(),
+ // IDataTransferHelpContextIds.FILE_SYSTEM_EXPORT_WIZARD_PAGE);
+ }
+
+ /**
+ * Create the export destination specification widgets
+ *
+ * @param parent
+ * org.eclipse.swt.widgets.Composite
+ */
+ protected void createDestinationGroup(Composite parent) {
+
+ Font font = parent.getFont();
+ // destination specification group
+ Composite destinationSelectionGroup = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ destinationSelectionGroup.setLayout(layout);
+ destinationSelectionGroup.setLayoutData(new GridData(
+ GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+ destinationSelectionGroup.setFont(font);
+
+ Label destinationLabel = new Label(destinationSelectionGroup, SWT.NONE);
+ destinationLabel.setText(getDestinationLabel());
+ destinationLabel.setFont(font);
+
+ // destination name entry field
+ destinationNameField = new Combo(destinationSelectionGroup, SWT.SINGLE
+ | SWT.BORDER);
+ destinationNameField.addListener(SWT.Modify, this);
+ destinationNameField.addListener(SWT.Selection, this);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.GRAB_HORIZONTAL);
+ data.widthHint = SIZING_TEXT_FIELD_WIDTH;
+ destinationNameField.setLayoutData(data);
+ destinationNameField.setFont(font);
+
+ // destination browse button
+ destinationBrowseButton = new Button(destinationSelectionGroup,
+ SWT.PUSH);
+ destinationBrowseButton.setText(ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.browse")); //$NON-NLS-1$
+ destinationBrowseButton.addListener(SWT.Selection, this);
+ destinationBrowseButton.setFont(font);
+ setButtonLayoutData(destinationBrowseButton);
+
+ new Label(parent, SWT.NONE); // vertical spacer
+ }
+
+ /**
+ * Create the buttons in the options group.
+ */
+
+ protected void createOptionsGroupButtons(Group optionsGroup) {
+
+ Font font = optionsGroup.getFont();
+ createOverwriteExisting(optionsGroup, font);
+
+ // createDirectoryStructureOptions(optionsGroup, font);
+ }
+
+ /**
+ * Create the buttons for the group that determine if the entire or selected
+ * directory structure should be created.
+ *
+ * @param optionsGroup
+ * @param font
+ */
+ // protected void createDirectoryStructureOptions(
+ // Group optionsGroup,
+ // Font font) {
+ // // create directory structure radios
+ // createDirectoryStructureButton =
+ // new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
+ // createDirectoryStructureButton.setText(ObfuscatorExportMessages.getString("FileExport.createDirectoryStructure"));
+ // //$NON-NLS-1$
+ // createDirectoryStructureButton.setSelection(false);
+ // createDirectoryStructureButton.setFont(font);
+ //
+ // // create directory structure radios
+ // createSelectionOnlyButton =
+ // new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
+ // createSelectionOnlyButton.setText(
+ // ObfuscatorExportMessages.getString(
+ // "FileExport.createSelectedDirectories"));//$NON-NLS-1$
+ // createSelectionOnlyButton.setSelection(true);
+ // createSelectionOnlyButton.setFont(font);
+ // }
+ /**
+ * Create the button for checking if we should ask if we are going to
+ * overwrite existing files.
+ *
+ * @param optionsGroup
+ * @param font
+ */
+ protected void createOverwriteExisting(Group optionsGroup, Font font) {
+ // overwrite... checkbox
+ overwriteExistingFilesCheckbox = new Button(optionsGroup, SWT.CHECK
+ | SWT.LEFT);
+ overwriteExistingFilesCheckbox.setText(ObfuscatorExportMessages
+ .getString("ExportFile.overwriteExisting")); //$NON-NLS-1$
+ overwriteExistingFilesCheckbox.setFont(font);
+ }
+
+ /**
+ * Attempts to ensure that the specified directory exists on the local file
+ * system. Answers a boolean indicating success.
+ *
+ * @return boolean
+ * @param directory
+ * java.io.File
+ */
+ protected boolean ensureDirectoryExists(File directory) {
+ if (!directory.exists()) {
+ if (!queryYesNoQuestion(ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.createTargetDirectory"))) //$NON-NLS-1$
+ return false;
+
+ if (!directory.mkdirs()) {
+ displayErrorDialog(ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.directoryCreationError")); //$NON-NLS-1$
+ giveFocusToDestination();
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * If the target for export does not exist then attempt to create it. Answer
+ * a boolean indicating whether the target exists (ie.- if it either
+ * pre-existed or this method was able to create it)
+ *
+ * @return boolean
+ */
+ protected boolean ensureTargetIsValid(File targetDirectory) {
+ if (targetDirectory.exists() && !targetDirectory.isDirectory()) {
+ displayErrorDialog(ObfuscatorExportMessages
+ .getString("FileExport.directoryExists")); //$NON-NLS-1$
+ giveFocusToDestination();
+ return false;
+ }
+
+ return ensureDirectoryExists(targetDirectory);
+ }
+
+ /**
+ * Set up and execute the passed Operation. Answer a boolean indicating
+ * success.
+ *
+ * @return boolean
+ */
+ protected boolean executeExportOperation(ObfuscatorExportOperation op) {
+ // op.setCreateLeadupStructure(
+ // createDirectoryStructureButton.getSelection());
+ op.setOverwriteFiles(overwriteExistingFilesCheckbox.getSelection());
+
+ try {
+ getContainer().run(true, true, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ displayErrorDialog(e.getTargetException());
+ return false;
+ }
+
+ IStatus status = op.getStatus();
+ if (!status.isOK()) {
+ ErrorDialog.openError(getContainer().getShell(),
+ ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.exportProblems"), //$NON-NLS-1$
+ null, // no special message
+ status);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * The Finish button was pressed. Try to do the required work now and answer
+ * a boolean indicating success. If false is returned then the wizard will
+ * not close.
+ *
+ * @return boolean
+ */
+ public boolean finish() {
+ if (!ensureTargetIsValid(new File(getDestinationValue())))
+ return false;
+
+ List resourcesToExport = getWhiteCheckedResources();
+
+ // Save dirty editors if possible but do not stop if not all are saved
+ saveDirtyEditors();
+ // about to invoke the operation so save our state
+ saveWidgetValues();
+
+ if (resourcesToExport.size() > 0)
+ return executeExportOperation(new ObfuscatorExportOperation(null,
+ resourcesToExport, getDestinationValue(), this));
+
+ MessageDialog.openInformation(getContainer().getShell(),
+ ObfuscatorExportMessages
+ .getString("ObfuscatorTransfer.information"), //$NON-NLS-1$
+ ObfuscatorExportMessages.getString("FileExport.noneSelected")); //$NON-NLS-1$
+
+ return false;
+ }
+
+ /**
+ * Answer the string to display in self as the destination type
+ *
+ * @return java.lang.String
+ */
+ protected String getDestinationLabel() {
+ return ObfuscatorExportMessages.getString("FileExport.toDirectory"); //$NON-NLS-1$
+ }
+
+ /**
+ * Answer the contents of self's destination specification widget
+ *
+ * @return java.lang.String
+ */
+ protected String getDestinationValue() {
+ return destinationNameField.getText().trim();
+ }
+
+ /**
+ * Set the current input focus to self's destination entry field
+ */
+ protected void giveFocusToDestination() {
+ destinationNameField.setFocus();
+ }
+
+ /**
+ * Open an appropriate destination browser so that the user can specify a
+ * source to import from
+ */
+ protected void handleDestinationBrowseButtonPressed() {
+ DirectoryDialog dialog = new DirectoryDialog(getContainer().getShell(),
+ SWT.SAVE);
+ dialog.setMessage(SELECT_DESTINATION_MESSAGE);
+ dialog.setText(SELECT_DESTINATION_TITLE);
+ dialog.setFilterPath(getDestinationValue());
+ String selectedDirectoryName = dialog.open();
+
+ if (selectedDirectoryName != null) {
+ setErrorMessage(null);
+ setDestinationValue(selectedDirectoryName);
+ }
+ }
+
+ /**
+ * Handle all events and enablements for widgets in this page
+ *
+ * @param e
+ * Event
+ */
+ public void handleEvent(Event e) {
+ Widget source = e.widget;
+
+ if (source == destinationBrowseButton)
+ handleDestinationBrowseButtonPressed();
+
+ updatePageCompletion();
+ }
+
+ /**
+ * Hook method for saving widget values for restoration by the next instance
+ * of this class.
+ */
+ protected void internalSaveWidgetValues() {
+ // update directory names history
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ String[] directoryNames = settings
+ .getArray(STORE_DESTINATION_NAMES_ID);
+ if (directoryNames == null)
+ directoryNames = new String[0];
+
+ directoryNames = addToHistory(directoryNames, getDestinationValue());
+ settings.put(STORE_DESTINATION_NAMES_ID, directoryNames);
+
+ // options
+ settings.put(STORE_OVERWRITE_EXISTING_FILES_ID,
+ overwriteExistingFilesCheckbox.getSelection());
+
+ // settings.put(
+ // STORE_CREATE_STRUCTURE_ID,
+ // createDirectoryStructureButton.getSelection());
+
+ }
+ }
+
+ /**
+ * Hook method for restoring widget values to the values that they held last
+ * time this wizard was used to completion.
+ */
+ protected void restoreWidgetValues() {
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ String[] directoryNames = settings
+ .getArray(STORE_DESTINATION_NAMES_ID);
+ if (directoryNames == null)
+ return; // ie.- no settings stored
+
+ // destination
+ setDestinationValue(directoryNames[0]);
+ for (int i = 0; i < directoryNames.length; i++)
+ addDestinationItem(directoryNames[i]);
+
+ // options
+ overwriteExistingFilesCheckbox.setSelection(settings
+ .getBoolean(STORE_OVERWRITE_EXISTING_FILES_ID));
+
+ // boolean createDirectories =
+ // settings.getBoolean(STORE_CREATE_STRUCTURE_ID);
+ // createDirectoryStructureButton.setSelection(createDirectories);
+ // createSelectionOnlyButton.setSelection(!createDirectories);
+ }
+ }
+
+ /**
+ * Set the contents of the receivers destination specification widget to the
+ * passed value
+ *
+ */
+ protected void setDestinationValue(String value) {
+ destinationNameField.setText(value);
+ }
+
+ /**
+ * Answer a boolean indicating whether the receivers destination
+ * specification widgets currently all contain valid values.
+ */
+ protected boolean validateDestinationGroup() {
+ String destinationValue = getDestinationValue();
+ if (destinationValue.length() == 0) {
+ setMessage(destinationEmptyMessage());
+ return false;
+ }
+
+ String conflictingContainer = getConflictingContainerNameFor(destinationValue);
+ if (conflictingContainer == null)
+ setErrorMessage(""); //$NON-NLS-1$
+ else {
+ setErrorMessage(ObfuscatorExportMessages.format(
+ "FileExport.conflictingContainer", //$NON-NLS-1$
+ new Object[] { conflictingContainer }));
+ giveFocusToDestination();
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the message used to denote an empty destination.
+ */
+ protected String destinationEmptyMessage() {
+ return ObfuscatorExportMessages
+ .getString("FileExport.destinationEmpty"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the name of a container with a location that encompasses
+ * targetDirectory. Returns null if there is no conflict.
+ *
+ * @param targetDirectory
+ * the path of the directory to check.
+ * @return the conflicting container name or null
+ */
+ protected String getConflictingContainerNameFor(String targetDirectory) {
+
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IPath testPath = new Path(targetDirectory);
+
+ if (root.getFullPath().isPrefixOf(testPath))
+ return ObfuscatorExportMessages.getString("FileExport.rootName"); //$NON-NLS-1$
+
+ IProject[] projects = root.getProjects();
+
+ for (int i = 0; i < projects.length; i++) {
+ if (projects[i].getFullPath().isPrefixOf(testPath))
+ return projects[i].getName();
+ }
+
+ return null;
+
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/messages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/messages.properties
new file mode 100644
index 0000000..baaf49d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/obfuscator/export/messages.properties
@@ -0,0 +1,64 @@
+###############################################################################
+# Copyright (c) 2000, 2003 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+# package: org.eclipse.ui.wizards.ObfuscatorTransfer
+
+
+# ==============================================================================
+# Data Transfer Wizards
+# ==============================================================================
+ObfuscatorTransfer.fileSystemTitle = File system
+
+ObfuscatorTransfer.browse = B&rowse...
+ObfuscatorTransfer.selectTypes = Filter &Types...
+ObfuscatorTransfer.selectAll = &Select All
+ObfuscatorTransfer.deselectAll = &Deselect All
+
+ObfuscatorTransfer.typeDelimiter = ,
+ObfuscatorTransfer.allFiles = All files matching this criteria
+ObfuscatorTransfer.oneSelected = 1 file selected
+ObfuscatorTransfer.details = Details...
+ObfuscatorTransfer.allTypes = All types
+
+ObfuscatorTransfer.cannotOverwrite = Cannot overwrite file: {0}
+ObfuscatorTransfer.emptyString =
+ObfuscatorTransfer.scanningChildren = Scanning for children...
+ObfuscatorTransfer.scanningMatching = Scanning for matching files...
+ObfuscatorTransfer.information = Information
+
+# --- Export Wizards ---
+ObfuscatorTransfer.export = Obfuscator Export
+
+ObfuscatorTransfer.exportingTitle1 = Obfuscating Pass 1:
+ObfuscatorTransfer.exportingTitle2 = Obfuscating Pass 2:
+ObfuscatorTransfer.selectDestination = Select the destination directory.
+ObfuscatorTransfer.directory = Director&y:
+ObfuscatorTransfer.createTargetDirectory = Target directory does not exist. Would you like to create it?
+ObfuscatorTransfer.directoryCreationError = Target directory could not be created.
+ObfuscatorTransfer.errorExporting = Error exporting {0}: {1}
+ObfuscatorTransfer.exportProblems = Export Problems
+
+ExportFile.overwriteExisting = &Overwrite existing files without warning
+ExportFile.createDirectoriesForSelected = Create directories for selected folders
+ExportFile.createDirectoryStructure = &Create directory structure
+
+FileExport.selectDestinationTitle= Export To Directory
+FileExport.selectDestinationMessage=Select a directory to export to.
+FileExport.exportLocalFileSystem = Export obfuscated PHP resources to the local file system.
+FileExport.destinationEmpty = Please enter a destination directory.
+FileExport.createDirectoryStructure = &Create directory structure for files
+FileExport.createSelectedDirectories = Create on&ly selected directories
+FileExport.noneSelected = There are no resources currently selected for export.
+FileExport.directoryExists = Target directory already exists as a file.
+FileExport.conflictingContainer = Destination directory conflicts with location of {0}.
+FileExport.rootName = workspace root
+ObfuscatorExportOperation.problemsExporting = Problems were encountered during export:
+FileExport.toDirectory = To director&y:
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/AnnotationType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/AnnotationType.java
new file mode 100644
index 0000000..6fadf0c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/AnnotationType.java
@@ -0,0 +1,59 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.jface.text.Assert;
+
+public final class AnnotationType {
+
+ public static final AnnotationType ALL = new AnnotationType();
+
+ public static final AnnotationType UNKNOWN = new AnnotationType();
+
+ public static final AnnotationType BOOKMARK = new AnnotationType();
+
+ public static final AnnotationType TASK = new AnnotationType();
+
+ public static final AnnotationType ERROR = new AnnotationType();
+
+ public static final AnnotationType WARNING = new AnnotationType();
+
+ public static final AnnotationType SEARCH = new AnnotationType();
+
+ private AnnotationType() {
+ }
+
+ public String toString() {
+ if (this == ALL)
+ return "AnnotationType.ALL"; //$NON-NLS-1$
+
+ if (this == UNKNOWN)
+ return "AnnotationType.UNKNOWN"; //$NON-NLS-1$
+
+ if (this == BOOKMARK)
+ return "AnnotationType.BOOKMARK"; //$NON-NLS-1$
+
+ if (this == TASK)
+ return "AnnotationType.TASK"; //$NON-NLS-1$
+
+ if (this == ERROR)
+ return "AnnotationType.ERROR"; //$NON-NLS-1$
+
+ if (this == WARNING)
+ return "AnnotationType.WARNING"; //$NON-NLS-1$
+
+ if (this == SEARCH)
+ return "AnnotationType.SEARCH"; //$NON-NLS-1$
+
+ Assert.isLegal(false);
+ return ""; //$NON-NLS-1$
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BasicEditorActionContributor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BasicEditorActionContributor.java
new file mode 100644
index 0000000..1f542a7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BasicEditorActionContributor.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.ui.IContextMenuConstants;
+import net.sourceforge.phpdt.ui.actions.PHPdtActionConstants;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.actions.RetargetAction;
+import org.eclipse.ui.editors.text.EncodingActionGroup;
+import org.eclipse.ui.ide.IDEActionFactory;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.RetargetTextEditorAction;
+
+public class BasicEditorActionContributor extends
+ BasicJavaEditorActionContributor {
+
+ protected RetargetAction fRetargetContentAssist;
+
+ protected RetargetTextEditorAction fContentAssist;
+
+ // protected RetargetTextEditorAction fContextInformation;
+ // protected RetargetTextEditorAction fCorrectionAssist;
+ private EncodingActionGroup fEncodingActionGroup;
+
+ public BasicEditorActionContributor() {
+
+ fRetargetContentAssist = new RetargetAction(
+ PHPdtActionConstants.CONTENT_ASSIST, PHPEditorMessages
+ .getString("ContentAssistProposal.label")); //$NON-NLS-1$
+ fRetargetContentAssist
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ markAsPartListener(fRetargetContentAssist);
+
+ fContentAssist = new RetargetTextEditorAction(PHPEditorMessages
+ .getResourceBundle(), "ContentAssistProposal."); //$NON-NLS-1$
+ fContentAssist
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ fContentAssist.setImageDescriptor(PHPUiImages.DESC_CLCL_CODE_ASSIST);
+ fContentAssist
+ .setDisabledImageDescriptor(PHPUiImages.DESC_DLCL_CODE_ASSIST);
+
+ // fContextInformation= new
+ // RetargetTextEditorAction(PHPEditorMessages.getResourceBundle(),
+ // "ContentAssistContextInformation."); //$NON-NLS-1$
+ // fContextInformation.setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
+
+ // fCorrectionAssist= new
+ // RetargetTextEditorAction(PHPEditorMessages.getResourceBundle(),
+ // "CorrectionAssistProposal."); //$NON-NLS-1$
+ // fCorrectionAssist.setActionDefinitionId(PHPEditorActionDefinitionIds.CORRECTION_ASSIST_PROPOSALS);
+
+ // character encoding
+ fEncodingActionGroup = new EncodingActionGroup();
+ }
+
+ /*
+ * @see EditorActionBarContributor#contributeToMenu(IMenuManager)
+ */
+ public void contributeToMenu(IMenuManager menu) {
+
+ super.contributeToMenu(menu);
+
+ IMenuManager editMenu = menu
+ .findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
+ if (editMenu != null) {
+ editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE,
+ fRetargetContentAssist);
+ // editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE,
+ // fCorrectionAssist);
+ // editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE,
+ // fContextInformation);
+ }
+ }
+
+ /*
+ * @see IEditorActionBarContributor#setActiveEditor(IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart part) {
+ super.setActiveEditor(part);
+
+ ITextEditor textEditor = null;
+ if (part instanceof ITextEditor)
+ textEditor = (ITextEditor) part;
+
+ fContentAssist
+ .setAction(getAction(textEditor, "ContentAssistProposal")); //$NON-NLS-1$
+ // fContextInformation.setAction(getAction(textEditor,
+ // "ContentAssistContextInformation")); //$NON-NLS-1$
+ // fCorrectionAssist.setAction(getAction(textEditor,
+ // "CorrectionAssistProposal")); //$NON-NLS-1$
+
+ IActionBars actionBars = getActionBars();
+ actionBars.setGlobalActionHandler(PHPdtActionConstants.SHIFT_RIGHT,
+ getAction(textEditor, "ShiftRight")); //$NON-NLS-1$
+ actionBars.setGlobalActionHandler(PHPdtActionConstants.SHIFT_LEFT,
+ getAction(textEditor, "ShiftLeft")); //$NON-NLS-1$
+
+ actionBars.setGlobalActionHandler(IDEActionFactory.ADD_TASK.getId(),
+ getAction(textEditor, IDEActionFactory.ADD_TASK.getId())); //$NON-NLS-1$
+ actionBars.setGlobalActionHandler(IDEActionFactory.BOOKMARK.getId(),
+ getAction(textEditor, IDEActionFactory.BOOKMARK.getId())); //$NON-NLS-1$
+
+ // character encoding
+ fEncodingActionGroup.retarget(textEditor);
+ }
+
+ /*
+ * @see IEditorActionBarContributor#init(IActionBars, IWorkbenchPage)
+ */
+ public void init(IActionBars bars, IWorkbenchPage page) {
+ super.init(bars, page);
+
+ // register actions that have a dynamic editor.
+ bars.setGlobalActionHandler(PHPdtActionConstants.CONTENT_ASSIST,
+ fContentAssist);
+ // character encoding
+ fEncodingActionGroup.fillActionBars(bars);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BasicJavaEditorActionContributor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BasicJavaEditorActionContributor.java
new file mode 100644
index 0000000..ebbc553
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BasicJavaEditorActionContributor.java
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpdt.internal.ui.actions.FoldingActionGroup;
+import net.sourceforge.phpdt.ui.IContextMenuConstants;
+import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.actions.RetargetAction;
+import org.eclipse.ui.texteditor.BasicTextEditorActionContributor;
+import org.eclipse.ui.texteditor.GotoAnnotationAction;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.RetargetTextEditorAction;
+
+/**
+ * Common base class for action contributors for Java editors.
+ */
+public class BasicJavaEditorActionContributor extends
+ BasicTextEditorActionContributor {
+
+ private List fPartListeners = new ArrayList();
+
+ private TogglePresentationAction fTogglePresentation;
+
+ private GotoAnnotationAction fPreviousAnnotation;
+ private GotoAnnotationAction fNextAnnotation;
+
+ private RetargetTextEditorAction fGotoMatchingBracket;
+
+ // private RetargetTextEditorAction fShowOutline;
+ // private RetargetTextEditorAction fOpenStructure;
+ // private RetargetTextEditorAction fOpenHierarchy;
+
+ // private RetargetAction fRetargetShowJavaDoc;
+ // private RetargetTextEditorAction fShowJavaDoc;
+
+ // private RetargetTextEditorAction fStructureSelectEnclosingAction;
+ // private RetargetTextEditorAction fStructureSelectNextAction;
+ // private RetargetTextEditorAction fStructureSelectPreviousAction;
+ // private RetargetTextEditorAction fStructureSelectHistoryAction;
+
+ private RetargetTextEditorAction fGotoNextMemberAction;
+
+ private RetargetTextEditorAction fGotoPreviousMemberAction;
+
+ //
+ // private RetargetTextEditorAction fRemoveOccurrenceAnnotationsAction;
+
+ public BasicJavaEditorActionContributor() {
+ super();
+
+ ResourceBundle b = PHPEditorMessages.getResourceBundle();
+
+ // fRetargetShowJavaDoc= new
+ // RetargetAction(PHPdtActionConstants.SHOW_JAVA_DOC,
+ // PHPEditorMessages.getString("ShowJavaDoc.label")); //$NON-NLS-1$
+ // fRetargetShowJavaDoc.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC);
+ // markAsPartListener(fRetargetShowJavaDoc);
+
+ // actions that are "contributed" to editors, they are considered
+ // belonging to the active editor
+ fTogglePresentation = new TogglePresentationAction();
+
+ fPreviousAnnotation = new GotoAnnotationAction(b,
+ "PreviousAnnotation.", null, false); //$NON-NLS-1$
+ fNextAnnotation = new GotoAnnotationAction(b,
+ "NextAnnotation.", null, true); //$NON-NLS-1$
+
+ fGotoMatchingBracket = new RetargetTextEditorAction(b,
+ "GotoMatchingBracket."); //$NON-NLS-1$
+ fGotoMatchingBracket
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
+
+ // fShowJavaDoc= new RetargetTextEditorAction(b, "ShowJavaDoc.");
+ // //$NON-NLS-1$
+ // fShowJavaDoc.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC);
+
+ // fShowOutline= new
+ // RetargetTextEditorAction(PHPEditorMessages.getResourceBundle(),
+ // "ShowOutline."); //$NON-NLS-1$
+ // fShowOutline.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE);
+ //
+ // fOpenHierarchy= new
+ // RetargetTextEditorAction(PHPEditorMessages.getResourceBundle(),
+ // "OpenHierarchy."); //$NON-NLS-1$
+ // fOpenHierarchy.setActionDefinitionId(PHPEditorActionDefinitionIds.OPEN_HIERARCHY);
+ //
+ // fOpenStructure= new
+ // RetargetTextEditorAction(PHPEditorMessages.getResourceBundle(),
+ // "OpenStructure."); //$NON-NLS-1$
+ // fOpenStructure.setActionDefinitionId(PHPEditorActionDefinitionIds.OPEN_STRUCTURE);
+
+ // fStructureSelectEnclosingAction= new RetargetTextEditorAction(b,
+ // "StructureSelectEnclosing."); //$NON-NLS-1$
+ // fStructureSelectEnclosingAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_ENCLOSING);
+ // fStructureSelectNextAction= new RetargetTextEditorAction(b,
+ // "StructureSelectNext."); //$NON-NLS-1$
+ // fStructureSelectNextAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_NEXT);
+ // fStructureSelectPreviousAction= new RetargetTextEditorAction(b,
+ // "StructureSelectPrevious."); //$NON-NLS-1$
+ // fStructureSelectPreviousAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_PREVIOUS);
+ // fStructureSelectHistoryAction= new RetargetTextEditorAction(b,
+ // "StructureSelectHistory."); //$NON-NLS-1$
+ // fStructureSelectHistoryAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_LAST);
+ //
+ fGotoNextMemberAction = new RetargetTextEditorAction(b,
+ "GotoNextMember."); //$NON-NLS-1$
+ fGotoNextMemberAction
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_NEXT_MEMBER);
+ fGotoPreviousMemberAction = new RetargetTextEditorAction(b,
+ "GotoPreviousMember."); //$NON-NLS-1$
+ fGotoPreviousMemberAction
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);
+ //
+ // fRemoveOccurrenceAnnotationsAction= new RetargetTextEditorAction(b,
+ // "RemoveOccurrenceAnnotations."); //$NON-NLS-1$
+ // fRemoveOccurrenceAnnotationsAction.setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
+ }
+
+ protected final void markAsPartListener(RetargetAction action) {
+ fPartListeners.add(action);
+ }
+
+ /*
+ * @see IEditorActionBarContributor#init(IActionBars, IWorkbenchPage)
+ */
+ public void init(IActionBars bars, IWorkbenchPage page) {
+ Iterator e = fPartListeners.iterator();
+ while (e.hasNext())
+ page.addPartListener((RetargetAction) e.next());
+
+ super.init(bars, page);
+
+ // register actions that have a dynamic editor.
+ bars.setGlobalActionHandler(ITextEditorActionDefinitionIds.GOTO_NEXT_ANNOTATION, fNextAnnotation);
+ bars.setGlobalActionHandler(ITextEditorActionDefinitionIds.GOTO_PREVIOUS_ANNOTATION, fPreviousAnnotation);
+ bars.setGlobalActionHandler(ITextEditorActionConstants.NEXT, fNextAnnotation);
+ bars.setGlobalActionHandler(ITextEditorActionConstants.PREVIOUS, fPreviousAnnotation);
+ bars
+ .setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.TOGGLE_SHOW_SELECTED_ELEMENT_ONLY,
+ fTogglePresentation);
+
+ // bars.setGlobalActionHandler(PHPdtActionConstants.SHOW_JAVA_DOC,
+ // fShowJavaDoc);
+ }
+
+ /*
+ * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToMenu(org.eclipse.jface.action.IMenuManager)
+ */
+ public void contributeToMenu(IMenuManager menu) {
+
+ super.contributeToMenu(menu);
+
+ IMenuManager editMenu = menu
+ .findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
+ if (editMenu != null) {
+
+ editMenu.add(new Separator(IContextMenuConstants.GROUP_OPEN));
+ editMenu.add(new Separator(IContextMenuConstants.GROUP_GENERATE));
+ editMenu.add(new Separator(IContextMenuConstants.GROUP_ADDITIONS));
+
+ // MenuManager structureSelection= new
+ // MenuManager(PHPEditorMessages.getString("ExpandSelectionMenu.label"),
+ // "expandSelection"); //$NON-NLS-1$ //$NON-NLS-2$
+ // structureSelection.add(fStructureSelectEnclosingAction);
+ // structureSelection.add(fStructureSelectNextAction);
+ // structureSelection.add(fStructureSelectPreviousAction);
+ // structureSelection.add(fStructureSelectHistoryAction);
+ // editMenu.appendToGroup(IContextMenuConstants.GROUP_OPEN,
+ // structureSelection);
+
+ // editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE,
+ // fRetargetShowJavaDoc);
+ }
+
+ // IMenuManager navigateMenu=
+ // menu.findMenuUsingPath(IWorkbenchActionConstants.M_NAVIGATE);
+ // if (navigateMenu != null) {
+ // navigateMenu.appendToGroup(IWorkbenchActionConstants.SHOW_EXT,
+ // fShowOutline);
+ // navigateMenu.appendToGroup(IWorkbenchActionConstants.SHOW_EXT,
+ // fOpenHierarchy);
+ // }
+
+ IMenuManager gotoMenu = menu.findMenuUsingPath("navigate/goTo"); //$NON-NLS-1$
+ if (gotoMenu != null) {
+ gotoMenu.add(new Separator("additions2")); //$NON-NLS-1$
+ gotoMenu.appendToGroup("additions2", fGotoPreviousMemberAction); //$NON-NLS-1$
+ gotoMenu.appendToGroup("additions2", fGotoNextMemberAction); //$NON-NLS-1$
+ gotoMenu.appendToGroup("additions2", fGotoMatchingBracket); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * @see EditorActionBarContributor#setActiveEditor(IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart part) {
+
+ super.setActiveEditor(part);
+
+ IActionBars actionBars = getActionBars();
+ IStatusLineManager manager = actionBars.getStatusLineManager();
+ manager.setMessage(null);
+ manager.setErrorMessage(null);
+
+ ITextEditor textEditor = null;
+ if (part instanceof ITextEditor)
+ textEditor = (ITextEditor) part;
+
+ fTogglePresentation.setEditor(textEditor);
+ fPreviousAnnotation.setEditor(textEditor);
+ fNextAnnotation.setEditor(textEditor);
+
+ fGotoMatchingBracket.setAction(getAction(textEditor,
+ GotoMatchingBracketAction.GOTO_MATCHING_BRACKET));
+ // fShowJavaDoc.setAction(getAction(textEditor, "ShowJavaDoc"));
+ // //$NON-NLS-1$
+ // fShowOutline.setAction(getAction(textEditor,
+ // IJavaEditorActionDefinitionIds.SHOW_OUTLINE));
+ // fOpenHierarchy.setAction(getAction(textEditor,
+ // IJavaEditorActionDefinitionIds.OPEN_HIERARCHY));
+ // fOpenStructure.setAction(getAction(textEditor,
+ // IJavaEditorActionDefinitionIds.OPEN_STRUCTURE));
+
+ // fStructureSelectEnclosingAction.setAction(getAction(textEditor,
+ // StructureSelectionAction.ENCLOSING));
+ // fStructureSelectNextAction.setAction(getAction(textEditor,
+ // StructureSelectionAction.NEXT));
+ // fStructureSelectPreviousAction.setAction(getAction(textEditor,
+ // StructureSelectionAction.PREVIOUS));
+ // fStructureSelectHistoryAction.setAction(getAction(textEditor,
+ // StructureSelectionAction.HISTORY));
+
+ // fGotoNextMemberAction.setAction(getAction(textEditor,
+ // GoToNextPreviousMemberAction.NEXT_MEMBER));
+ // fGotoPreviousMemberAction.setAction(getAction(textEditor,
+ // GoToNextPreviousMemberAction.PREVIOUS_MEMBER));
+
+ // fRemoveOccurrenceAnnotationsAction.setAction(getAction(textEditor,
+ // "RemoveOccurrenceAnnotations")); //$NON-NLS-1$
+ if (part instanceof PHPEditor) {
+ PHPEditor javaEditor = (PHPEditor) part;
+ javaEditor.getActionGroup().fillActionBars(getActionBars());
+ FoldingActionGroup foldingActions = javaEditor
+ .getFoldingActionGroup();
+ if (foldingActions != null)
+ foldingActions.updateActionBars();
+ }
+ }
+
+ /*
+ * @see IEditorActionBarContributor#dispose()
+ */
+ public void dispose() {
+
+ Iterator e = fPartListeners.iterator();
+ while (e.hasNext())
+ getPage().removePartListener((RetargetAction) e.next());
+ fPartListeners.clear();
+
+ setActiveEditor(null);
+ super.dispose();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BracketPainter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BracketPainter.java
new file mode 100644
index 0000000..e73790b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BracketPainter.java
@@ -0,0 +1,179 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+
+public final class BracketPainter implements IPainter, PaintListener {
+
+ private PHPPairMatcher fMatcher = new PHPPairMatcher(new char[] { '{', '}',
+ '(', ')', '[', ']' });
+
+ private Position fBracketPosition = new Position(0, 0);
+
+ private int fAnchor;
+
+ private boolean fIsActive = false;
+
+ private ISourceViewer fSourceViewer;
+
+ private StyledText fTextWidget;
+
+ private Color fColor;
+
+ private IPositionManager fPositionManager;
+
+ public BracketPainter(ISourceViewer sourceViewer) {
+ fSourceViewer = sourceViewer;
+ fTextWidget = sourceViewer.getTextWidget();
+ }
+
+ public void setHighlightColor(Color color) {
+ fColor = color;
+ }
+
+ public void dispose() {
+ if (fMatcher != null) {
+ fMatcher.dispose();
+ fMatcher = null;
+ }
+
+ fColor = null;
+ fTextWidget = null;
+ }
+
+ public void deactivate(boolean redraw) {
+ if (fIsActive) {
+ fIsActive = false;
+ fTextWidget.removePaintListener(this);
+ if (fPositionManager != null)
+ fPositionManager.removeManagedPosition(fBracketPosition);
+ if (redraw)
+ handleDrawRequest(null);
+ }
+ }
+
+ public void paintControl(PaintEvent event) {
+ if (fTextWidget != null)
+ handleDrawRequest(event.gc);
+ }
+
+ private void handleDrawRequest(GC gc) {
+
+ if (fBracketPosition.isDeleted)
+ return;
+
+ int offset = fBracketPosition.getOffset();
+ int length = fBracketPosition.getLength();
+ if (length < 1)
+ return;
+
+ if (fSourceViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) fSourceViewer;
+ IRegion widgetRange = extension.modelRange2WidgetRange(new Region(
+ offset, length));
+ if (widgetRange == null)
+ return;
+
+ offset = widgetRange.getOffset();
+ length = widgetRange.getLength();
+
+ } else {
+ IRegion region = fSourceViewer.getVisibleRegion();
+ if (region.getOffset() > offset
+ || region.getOffset() + region.getLength() < offset
+ + length)
+ return;
+ offset -= region.getOffset();
+ }
+
+ if (PHPPairMatcher.RIGHT == fAnchor)
+ draw(gc, offset, 1);
+ else
+ draw(gc, offset + length - 1, 1);
+ }
+
+ private void draw(GC gc, int offset, int length) {
+ if (gc != null) {
+ Point left = fTextWidget.getLocationAtOffset(offset);
+ Point right = fTextWidget.getLocationAtOffset(offset + length);
+
+ gc.setForeground(fColor);
+ gc.drawRectangle(left.x, left.y, right.x - left.x - 1, gc
+ .getFontMetrics().getHeight() - 1);
+
+ } else {
+ fTextWidget.redrawRange(offset, length, true);
+ }
+ }
+
+ /*
+ * @see IPainter#paint(int)
+ */
+ public void paint(int reason) {
+ Point selection = fSourceViewer.getSelectedRange();
+ if (selection.y > 0) {
+ deactivate(true);
+ return;
+ }
+
+ IRegion pair = fMatcher.match(fSourceViewer.getDocument(), selection.x);
+ if (pair == null) {
+ deactivate(true);
+ return;
+ }
+
+ if (fIsActive) {
+ // only if different
+ if (pair.getOffset() != fBracketPosition.getOffset()
+ || pair.getLength() != fBracketPosition.getLength()
+ || fMatcher.getAnchor() != fAnchor) {
+
+ // remove old highlighting
+ handleDrawRequest(null);
+ // update position
+ fBracketPosition.isDeleted = false;
+ fBracketPosition.offset = pair.getOffset();
+ fBracketPosition.length = pair.getLength();
+ fAnchor = fMatcher.getAnchor();
+ // apply new highlighting
+ handleDrawRequest(null);
+
+ }
+ } else {
+
+ fIsActive = true;
+
+ fBracketPosition.isDeleted = false;
+ fBracketPosition.offset = pair.getOffset();
+ fBracketPosition.length = pair.getLength();
+ fAnchor = fMatcher.getAnchor();
+
+ fTextWidget.addPaintListener(this);
+ fPositionManager.addManagedPosition(fBracketPosition);
+ handleDrawRequest(null);
+ }
+ }
+
+ /*
+ * @see IPainter#setPositionManager(IPositionManager)
+ */
+ public void setPositionManager(IPositionManager manager) {
+ fPositionManager = manager;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BreakpointImageProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BreakpointImageProvider.java
new file mode 100644
index 0000000..b57d14d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/BreakpointImageProvider.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.texteditor.IAnnotationImageProvider;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+
+/**
+ * BreakpointImageProvider
+ *
+ * @since 3.0
+ */
+public class BreakpointImageProvider implements IAnnotationImageProvider {
+
+ private IDebugModelPresentation fPresentation;
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationImageProvider#getManagedImage(org.eclipse.jface.text.source.Annotation)
+ */
+ public Image getManagedImage(Annotation annotation) {
+ if (annotation instanceof MarkerAnnotation) {
+ MarkerAnnotation markerAnnotation = (MarkerAnnotation) annotation;
+ IMarker marker = markerAnnotation.getMarker();
+ if (marker != null && marker.exists())
+ return getPresentation().getImage(marker);
+ }
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationImageProvider#getImageDescriptorId(org.eclipse.jface.text.source.Annotation)
+ */
+ public String getImageDescriptorId(Annotation annotation) {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationImageProvider#getImageDescriptor(java.lang.String)
+ */
+ public ImageDescriptor getImageDescriptor(String imageDescritporId) {
+ return null;
+ }
+
+ private IDebugModelPresentation getPresentation() {
+ if (fPresentation == null)
+ fPresentation = DebugUITools.newDebugModelPresentation();
+ return fPresentation;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/CompilationUnitAnnotationModelEvent.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/CompilationUnitAnnotationModelEvent.java
new file mode 100644
index 0000000..fa55f33
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/CompilationUnitAnnotationModelEvent.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationModelEvent;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+
+/**
+ * Event sent out by changes of the compilation unit annotation model.
+ */
+public class CompilationUnitAnnotationModelEvent extends AnnotationModelEvent {
+
+ private boolean fIncludesProblemMarkerAnnotations;
+
+ private IResource fUnderlyingResource;
+
+ /**
+ * Constructor for CompilationUnitAnnotationModelEvent.
+ *
+ * @param model
+ * @param underlyingResource
+ * The annotation model's underlying resource
+ */
+ public CompilationUnitAnnotationModelEvent(IAnnotationModel model,
+ IResource underlyingResource) {
+ super(model);
+ fUnderlyingResource = underlyingResource;
+ fIncludesProblemMarkerAnnotations = false;
+ }
+
+ private void testIfProblemMarker(Annotation annotation) {
+ if (fIncludesProblemMarkerAnnotations) {
+ return;
+ }
+ if (annotation instanceof JavaMarkerAnnotation) {
+ fIncludesProblemMarkerAnnotations = ((JavaMarkerAnnotation) annotation)
+ .isProblem();
+ } else if (annotation instanceof MarkerAnnotation) {
+ try {
+ IMarker marker = ((MarkerAnnotation) annotation).getMarker();
+ if (!marker.exists() || marker.isSubtypeOf(IMarker.PROBLEM)) {
+ fIncludesProblemMarkerAnnotations = true;
+ }
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.AnnotationModelEvent#annotationAdded(org.eclipse.jface.text.source.Annotation)
+ */
+ public void annotationAdded(Annotation annotation) {
+ super.annotationAdded(annotation);
+ testIfProblemMarker(annotation);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.AnnotationModelEvent#annotationRemoved(org.eclipse.jface.text.source.Annotation)
+ */
+ public void annotationRemoved(Annotation annotation) {
+ super.annotationRemoved(annotation);
+ testIfProblemMarker(annotation);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.AnnotationModelEvent#annotationRemoved(org.eclipse.jface.text.source.Annotation,
+ * org.eclipse.jface.text.Position)
+ */
+ public void annotationRemoved(Annotation annotation, Position position) {
+ super.annotationRemoved(annotation, position);
+ testIfProblemMarker(annotation);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.AnnotationModelEvent#annotationChanged(org.eclipse.jface.text.source.Annotation)
+ */
+ public void annotationChanged(Annotation annotation) {
+ testIfProblemMarker(annotation);
+ super.annotationChanged(annotation);
+ }
+
+ /**
+ * Returns whether the change included problem marker annotations.
+ *
+ * @return true
if the change included marker annotations
+ */
+ public boolean includesProblemMarkerAnnotationChanges() {
+ return fIncludesProblemMarkerAnnotations;
+ }
+
+ /**
+ * Returns the annotation model's underlying resource
+ */
+ public IResource getUnderlyingResource() {
+ return fUnderlyingResource;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/CompilationUnitEditorActionContributor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/CompilationUnitEditorActionContributor.java
new file mode 100644
index 0000000..b77af3e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/CompilationUnitEditorActionContributor.java
@@ -0,0 +1,76 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ **********************************************************************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.ui.actions.PHPdtActionConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.editor.ShowExternalPreviewAction;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+public class CompilationUnitEditorActionContributor extends
+ BasicEditorActionContributor {
+ public CompilationUnitEditorActionContributor() {
+ super();
+ }
+
+ /*
+ * @see IEditorActionBarContributor#setActiveEditor(IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart part) {
+ super.setActiveEditor(part);
+
+ ITextEditor textEditor = null;
+ if (part instanceof ITextEditor)
+ textEditor = (ITextEditor) part;
+
+ // Source menu.
+ IActionBars bars = getActionBars();
+ bars.setGlobalActionHandler(PHPdtActionConstants.COMMENT, getAction(
+ textEditor, "Comment")); //$NON-NLS-1$
+ bars.setGlobalActionHandler(PHPdtActionConstants.UNCOMMENT, getAction(
+ textEditor, "Uncomment")); //$NON-NLS-1$
+ bars.setGlobalActionHandler(PHPdtActionConstants.TOGGLE_COMMENT,
+ getAction(textEditor, "ToggleComment")); //$NON-NLS-1$
+ bars.setGlobalActionHandler(PHPdtActionConstants.FORMAT, getAction(
+ textEditor, "Format")); //$NON-NLS-1$
+ bars.setGlobalActionHandler(PHPdtActionConstants.ADD_BLOCK_COMMENT,
+ getAction(textEditor, "AddBlockComment")); //$NON-NLS-1$
+ bars.setGlobalActionHandler(PHPdtActionConstants.REMOVE_BLOCK_COMMENT,
+ getAction(textEditor, "RemoveBlockComment")); //$NON-NLS-1$
+ // bars.setGlobalActionHandler(PHPdtActionConstants.INDENT, getAction(
+ // textEditor, "Indent")); //$NON-NLS-1$ //$NON-NLS-2$
+
+ if (textEditor != null) {
+ IFile file = null;
+ IEditorInput editorInput = textEditor.getEditorInput();
+
+ if (editorInput instanceof IFileEditorInput) {
+ file = ((IFileEditorInput) editorInput).getFile();
+ }
+
+ PHPeclipsePlugin.getDefault().setLastEditorFile(file);
+
+ ShowExternalPreviewAction fShowExternalPreviewAction = ShowExternalPreviewAction
+ .getInstance();
+ fShowExternalPreviewAction.setEditor(textEditor);
+ fShowExternalPreviewAction.update();
+ // if (fShowExternalPreviewAction != null) {
+ // fShowExternalPreviewAction
+ // .doRun(ShowExternalPreviewAction.PHP_TYPE);
+ // }
+ fShowExternalPreviewAction
+ .refresh(ShowExternalPreviewAction.PHP_TYPE);
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/DocumentAdapter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/DocumentAdapter.java
new file mode 100644
index 0000000..6c0bdff
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/DocumentAdapter.java
@@ -0,0 +1,513 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import net.sourceforge.phpdt.core.BufferChangedEvent;
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.IBufferChangedListener;
+import net.sourceforge.phpdt.core.IOpenable;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.ITextFileBufferManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+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.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Adapts IDocument
to IBuffer
. Uses the same
+ * algorithm as the text widget to determine the buffer's line delimiter. All
+ * text inserted into the buffer is converted to this line delimiter. This class
+ * is public
for test purposes only.
+ */
+public class DocumentAdapter implements IBuffer, IDocumentListener {
+
+ /**
+ * Internal implementation of a NULL instanceof IBuffer.
+ */
+ static private class NullBuffer implements IBuffer {
+ public void addBufferChangedListener(IBufferChangedListener listener) {
+ }
+
+ public void append(char[] text) {
+ }
+
+ public void append(String text) {
+ }
+
+ public void close() {
+ }
+
+ public char getChar(int position) {
+ return 0;
+ }
+
+ public char[] getCharacters() {
+ return null;
+ }
+
+ public String getContents() {
+ return null;
+ }
+
+ public int getLength() {
+ return 0;
+ }
+
+ public IOpenable getOwner() {
+ return null;
+ }
+
+ public String getText(int offset, int length) {
+ return null;
+ }
+
+ public IResource getUnderlyingResource() {
+ return null;
+ }
+
+ public boolean hasUnsavedChanges() {
+ return false;
+ }
+
+ public boolean isClosed() {
+ return false;
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public void removeBufferChangedListener(IBufferChangedListener listener) {
+ }
+
+ public void replace(int position, int length, char[] text) {
+ }
+
+ public void replace(int position, int length, String text) {
+ }
+
+ public void save(IProgressMonitor progress, boolean force)
+ throws JavaModelException {
+ }
+
+ public void setContents(char[] contents) {
+ }
+
+ public void setContents(String contents) {
+ }
+ }
+
+ /** NULL implementing IBuffer
*/
+ public final static IBuffer NULL = new NullBuffer();
+
+ /**
+ * Executes a document set content call in the ui thread.
+ */
+ protected class DocumentSetCommand implements Runnable {
+
+ private String fContents;
+
+ public void run() {
+ fDocument.set(fContents);
+ }
+
+ public void set(String contents) {
+ fContents = contents;
+ Display.getDefault().syncExec(this);
+ }
+ }
+
+ /**
+ * Executes a document replace call in the ui thread.
+ */
+ protected class DocumentReplaceCommand implements Runnable {
+
+ private int fOffset;
+
+ private int fLength;
+
+ private String fText;
+
+ public void run() {
+ try {
+ fDocument.replace(fOffset, fLength, fText);
+ } catch (BadLocationException x) {
+ // ignore
+ }
+ }
+
+ public void replace(int offset, int length, String text) {
+ fOffset = offset;
+ fLength = length;
+ fText = text;
+ Display.getDefault().syncExec(this);
+ }
+ }
+
+ private static final boolean DEBUG_LINE_DELIMITERS = true;
+
+ private IOpenable fOwner;
+
+ private IFile fFile;
+
+ private ITextFileBuffer fTextFileBuffer;
+
+ private IDocument fDocument;
+
+ private DocumentSetCommand fSetCmd = new DocumentSetCommand();
+
+ private DocumentReplaceCommand fReplaceCmd = new DocumentReplaceCommand();
+
+ private Set fLegalLineDelimiters;
+
+ private List fBufferListeners = new ArrayList(3);
+
+ private IStatus fStatus;
+
+ /**
+ * This method is public
for test purposes only.
+ */
+ public DocumentAdapter(IOpenable owner, IFile file) {
+
+ fOwner = owner;
+ fFile = file;
+
+ initialize();
+ }
+
+ private void initialize() {
+ ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
+ IPath location = fFile.getFullPath();
+ try {
+ manager.connect(location, new NullProgressMonitor());
+ fTextFileBuffer = manager.getTextFileBuffer(location);
+ fDocument = fTextFileBuffer.getDocument();
+ } catch (CoreException x) {
+ fStatus = x.getStatus();
+ fDocument = manager.createEmptyDocument(location);
+ }
+ fDocument.addPrenotifiedDocumentListener(this);
+ }
+
+ /**
+ * Returns the status of this document adapter.
+ */
+ public IStatus getStatus() {
+ if (fStatus != null)
+ return fStatus;
+ if (fTextFileBuffer != null)
+ return fTextFileBuffer.getStatus();
+ return null;
+ }
+
+ /**
+ * Returns the adapted document.
+ *
+ * @return the adapted document
+ */
+ public IDocument getDocument() {
+ return fDocument;
+ }
+
+ /*
+ * @see IBuffer#addBufferChangedListener(IBufferChangedListener)
+ */
+ public void addBufferChangedListener(IBufferChangedListener listener) {
+ Assert.isNotNull(listener);
+ if (!fBufferListeners.contains(listener))
+ fBufferListeners.add(listener);
+ }
+
+ /*
+ * @see IBuffer#removeBufferChangedListener(IBufferChangedListener)
+ */
+ public void removeBufferChangedListener(IBufferChangedListener listener) {
+ Assert.isNotNull(listener);
+ fBufferListeners.remove(listener);
+ }
+
+ /*
+ * @see IBuffer#append(char[])
+ */
+ public void append(char[] text) {
+ append(new String(text));
+ }
+
+ /*
+ * @see IBuffer#append(String)
+ */
+ public void append(String text) {
+ if (DEBUG_LINE_DELIMITERS) {
+ validateLineDelimiters(text);
+ }
+ fReplaceCmd.replace(fDocument.getLength(), 0, text);
+ }
+
+ /*
+ * @see IBuffer#close()
+ */
+ public void close() {
+
+ if (isClosed())
+ return;
+
+ IDocument d = fDocument;
+ fDocument = null;
+ d.removePrenotifiedDocumentListener(this);
+
+ if (fTextFileBuffer != null) {
+ ITextFileBufferManager manager = FileBuffers
+ .getTextFileBufferManager();
+ try {
+ manager.disconnect(fTextFileBuffer.getLocation(),
+ new NullProgressMonitor());
+ } catch (CoreException x) {
+ // ignore
+ }
+ fTextFileBuffer = null;
+ }
+
+ fireBufferChanged(new BufferChangedEvent(this, 0, 0, null));
+ fBufferListeners.clear();
+ }
+
+ /*
+ * @see IBuffer#getChar(int)
+ */
+ public char getChar(int position) {
+ try {
+ return fDocument.getChar(position);
+ } catch (BadLocationException x) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ }
+
+ /*
+ * @see IBuffer#getCharacters()
+ */
+ public char[] getCharacters() {
+ String content = getContents();
+ return content == null ? null : content.toCharArray();
+ }
+
+ /*
+ * @see IBuffer#getContents()
+ */
+ public String getContents() {
+ return fDocument.get();
+ }
+
+ /*
+ * @see IBuffer#getLength()
+ */
+ public int getLength() {
+ return fDocument.getLength();
+ }
+
+ /*
+ * @see IBuffer#getOwner()
+ */
+ public IOpenable getOwner() {
+ return fOwner;
+ }
+
+ /*
+ * @see IBuffer#getText(int, int)
+ */
+ public String getText(int offset, int length) {
+ try {
+ return fDocument.get(offset, length);
+ } catch (BadLocationException x) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ }
+
+ /*
+ * @see IBuffer#getUnderlyingResource()
+ */
+ public IResource getUnderlyingResource() {
+ return fFile;
+ }
+
+ /*
+ * @see IBuffer#hasUnsavedChanges()
+ */
+ public boolean hasUnsavedChanges() {
+ return fTextFileBuffer != null ? fTextFileBuffer.isDirty() : false;
+ }
+
+ /*
+ * @see IBuffer#isClosed()
+ */
+ public boolean isClosed() {
+ return fDocument == null;
+ }
+
+ /*
+ * @see IBuffer#isReadOnly()
+ */
+ public boolean isReadOnly() {
+ IResource resource = getUnderlyingResource();
+ return resource == null ? true : resource.getResourceAttributes()
+ .isReadOnly();
+ }
+
+ /*
+ * @see IBuffer#replace(int, int, char[])
+ */
+ public void replace(int position, int length, char[] text) {
+ replace(position, length, new String(text));
+ }
+
+ /*
+ * @see IBuffer#replace(int, int, String)
+ */
+ public void replace(int position, int length, String text) {
+ if (DEBUG_LINE_DELIMITERS) {
+ validateLineDelimiters(text);
+ }
+ fReplaceCmd.replace(position, length, text);
+ }
+
+ /*
+ * @see IBuffer#save(IProgressMonitor, boolean)
+ */
+ public void save(IProgressMonitor progress, boolean force)
+ throws JavaModelException {
+ try {
+ if (fTextFileBuffer != null)
+ fTextFileBuffer.commit(progress, force);
+ } catch (CoreException e) {
+ throw new JavaModelException(e);
+ }
+ }
+
+ /*
+ * @see IBuffer#setContents(char[])
+ */
+ public void setContents(char[] contents) {
+ setContents(new String(contents));
+ }
+
+ /*
+ * @see IBuffer#setContents(String)
+ */
+ public void setContents(String contents) {
+ int oldLength = fDocument.getLength();
+
+ if (contents == null) {
+
+ if (oldLength != 0)
+ fSetCmd.set(""); //$NON-NLS-1$
+
+ } else {
+
+ // set only if different
+ if (DEBUG_LINE_DELIMITERS) {
+ validateLineDelimiters(contents);
+ }
+
+ if (!contents.equals(fDocument.get()))
+ fSetCmd.set(contents);
+ }
+ }
+
+ private void validateLineDelimiters(String contents) {
+
+ if (fLegalLineDelimiters == null) {
+ // collect all line delimiters in the document
+ HashSet existingDelimiters = new HashSet();
+
+ for (int i = fDocument.getNumberOfLines() - 1; i >= 0; i--) {
+ try {
+ String curr = fDocument.getLineDelimiter(i);
+ if (curr != null) {
+ existingDelimiters.add(curr);
+ }
+ } catch (BadLocationException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ if (existingDelimiters.isEmpty()) {
+ return; // first insertion of a line delimiter: no test
+ }
+ fLegalLineDelimiters = existingDelimiters;
+
+ }
+
+ DefaultLineTracker tracker = new DefaultLineTracker();
+ tracker.set(contents);
+
+ int lines = tracker.getNumberOfLines();
+ if (lines <= 1)
+ return;
+
+ for (int i = 0; i < lines; i++) {
+ try {
+ String curr = tracker.getLineDelimiter(i);
+ if (curr != null && !fLegalLineDelimiters.contains(curr)) {
+ StringBuffer buf = new StringBuffer(
+ "New line delimiter added to new code: "); //$NON-NLS-1$
+ for (int k = 0; k < curr.length(); k++) {
+ buf.append(String.valueOf((int) curr.charAt(k)));
+ }
+ PHPeclipsePlugin.log(new Exception(buf.toString()));
+ }
+ } catch (BadLocationException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ }
+
+ /*
+ * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ // there is nothing to do here
+ }
+
+ /*
+ * @see IDocumentListener#documentChanged(DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ fireBufferChanged(new BufferChangedEvent(this, event.getOffset(), event
+ .getLength(), event.getText()));
+ }
+
+ private void fireBufferChanged(BufferChangedEvent event) {
+ if (fBufferListeners != null && fBufferListeners.size() > 0) {
+ Iterator e = new ArrayList(fBufferListeners).iterator();
+ while (e.hasNext())
+ ((IBufferChangedListener) e.next()).bufferChanged(event);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/EditorHighlightingSynchronizer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/EditorHighlightingSynchronizer.java
new file mode 100644
index 0000000..4125a28
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/EditorHighlightingSynchronizer.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.link.ILinkedModeListener;
+import org.eclipse.jface.text.link.LinkedModeModel;
+
+/**
+ * Turns off occurrences highlighting on a java editor until linked mode is
+ * left.
+ *
+ * @since 3.0
+ */
+public class EditorHighlightingSynchronizer implements ILinkedModeListener {
+
+ private final PHPEditor fEditor;
+
+ // private final boolean fWasOccurrencesOn;
+
+ /**
+ * Creates a new synchronizer.
+ *
+ * @param editor
+ * the java editor the occurrences markers of which will be
+ * synchonized with the linked mode
+ *
+ */
+ public EditorHighlightingSynchronizer(PHPEditor editor) {
+ Assert.isLegal(editor != null);
+ fEditor = editor;
+ // fWasOccurrencesOn= fEditor.isMarkingOccurrences();
+ //
+ // if (fWasOccurrencesOn)
+ // fEditor.uninstallOccurrencesFinder();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.link.ILinkedModeListener#left(org.eclipse.jface.text.link.LinkedModeModel,
+ * int)
+ */
+ public void left(LinkedModeModel environment, int flags) {
+ // if (fWasOccurrencesOn)
+ // fEditor.installOccurrencesFinder();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.link.ILinkedModeListener#suspend(org.eclipse.jface.text.link.LinkedModeModel)
+ */
+ public void suspend(LinkedModeModel environment) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.link.ILinkedModeListener#resume(org.eclipse.jface.text.link.LinkedModeModel,
+ * int)
+ */
+ public void resume(LinkedModeModel environment, int flags) {
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/EditorUtility.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/EditorUtility.java
new file mode 100644
index 0000000..5952b81
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/EditorUtility.java
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.IWorkingCopy;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.ui.JavaUI;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.action.Action;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * A number of routines for working with JavaElements in editors
+ *
+ * Use 'isOpenInEditor' to test if an element is already open in a editor Use
+ * 'openInEditor' to force opening an element in a editor With 'getWorkingCopy'
+ * you get the working copy (element in the editor) of an element
+ */
+public class EditorUtility {
+
+ public static boolean isEditorInput(Object element, IEditorPart editor) {
+ if (editor != null) {
+ try {
+ return editor.getEditorInput().equals(getEditorInput(element));
+ } catch (JavaModelException x) {
+ PHPeclipsePlugin.log(x.getStatus());
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests if a cu is currently shown in an editor
+ *
+ * @return the IEditorPart if shown, null if element is not open in an
+ * editor
+ */
+ public static IEditorPart isOpenInEditor(Object inputElement) {
+ IEditorInput input = null;
+
+ try {
+ input = getEditorInput(inputElement);
+ } catch (JavaModelException x) {
+ PHPeclipsePlugin.log(x.getStatus());
+ }
+
+ if (input != null) {
+ IWorkbenchPage p = WebUI.getActivePage();
+ if (p != null) {
+ return p.findEditor(input);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Opens a Java editor for an element such as IJavaElement
,
+ * IFile
, or IStorage
. The editor is
+ * activated by default.
+ *
+ * @return the IEditorPart or null if wrong element type or opening failed
+ */
+ public static IEditorPart openInEditor(Object inputElement)
+ throws JavaModelException, PartInitException {
+ return openInEditor(inputElement, true);
+ }
+
+ /**
+ * Opens a Java editor for an element (IJavaElement, IFile, IStorage...)
+ *
+ * @return the IEditorPart or null if wrong element type or opening failed
+ */
+ public static IEditorPart openInEditor(Object inputElement, boolean activate)
+ throws JavaModelException, PartInitException {
+
+ if (inputElement instanceof IFile)
+ return openInEditor((IFile) inputElement, activate);
+
+ IEditorInput input = getEditorInput(inputElement);
+ if (input instanceof IFileEditorInput) {
+ IFileEditorInput fileInput = (IFileEditorInput) input;
+ return openInEditor(fileInput.getFile(), activate);
+ }
+
+ if (input != null)
+ return openInEditor(input, getEditorID(input, inputElement),
+ activate);
+
+ return null;
+ }
+
+ /**
+ * Selects a Java Element in an editor
+ */
+ public static void revealInEditor(IEditorPart part, IJavaElement element) {
+ if (element != null && part instanceof PHPEditor) {
+ ((PHPEditor) part).setSelection(element);
+ }
+ }
+
+ private static IEditorPart openInEditor(IFile file, boolean activate)
+ throws PartInitException {
+ if (file != null) {
+ IWorkbenchPage p = WebUI.getActivePage();
+ if (p != null) {
+ IEditorPart editorPart = IDE.openEditor(p, file, activate);
+ initializeHighlightRange(editorPart);
+ return editorPart;
+ }
+ }
+ return null;
+ }
+
+ private static IEditorPart openInEditor(IEditorInput input,
+ String editorID, boolean activate) throws PartInitException {
+ if (input != null) {
+ IWorkbenchPage p = WebUI.getActivePage();
+ if (p != null) {
+ IEditorPart editorPart = p
+ .openEditor(input, editorID, activate);
+ initializeHighlightRange(editorPart);
+ return editorPart;
+ }
+ }
+ return null;
+ }
+
+ private static void initializeHighlightRange(IEditorPart editorPart) {
+ if (editorPart instanceof ITextEditor) {
+ TogglePresentationAction toggleAction = new TogglePresentationAction();
+ // Initialize editor
+ toggleAction.setEditor((ITextEditor) editorPart);
+ // Reset action
+ toggleAction.setEditor(null);
+ }
+ }
+
+ /**
+ * @deprecated Made it public again for java debugger UI.
+ */
+ public static String getEditorID(IEditorInput input, Object inputObject) {
+ IEditorRegistry registry = PlatformUI.getWorkbench()
+ .getEditorRegistry();
+ IEditorDescriptor descriptor = registry.getDefaultEditor(input
+ .getName());
+ if (descriptor != null)
+ return descriptor.getId();
+ return null;
+ }
+
+ private static IEditorInput getEditorInput(IJavaElement element)
+ throws JavaModelException {
+ while (element != null) {
+ if (element instanceof IWorkingCopy
+ && ((IWorkingCopy) element).isWorkingCopy())
+ element = ((IWorkingCopy) element).getOriginalElement();
+
+ if (element instanceof ICompilationUnit) {
+ ICompilationUnit unit = (ICompilationUnit) element;
+ IResource resource = unit.getResource();
+ if (resource instanceof IFile)
+ return new FileEditorInput((IFile) resource);
+ }
+
+ // if (element instanceof IClassFile)
+ // return new InternalClassFileEditorInput((IClassFile) element);
+ //
+ element = element.getParent();
+ }
+
+ return null;
+ }
+
+ public static IEditorInput getEditorInput(Object input)
+ throws JavaModelException {
+
+ if (input instanceof IJavaElement)
+ return getEditorInput((IJavaElement) input);
+
+ if (input instanceof IFile)
+ return new FileEditorInput((IFile) input);
+
+ // if (input instanceof IStorage)
+ // return new JarEntryEditorInput((IStorage)input);
+
+ return null;
+ }
+
+ /**
+ * If the current active editor edits a java element return it, else return
+ * null
+ */
+ public static IJavaElement getActiveEditorJavaInput() {
+ IWorkbenchPage page = WebUI.getActivePage();
+ if (page != null) {
+ IEditorPart part = page.getActiveEditor();
+ if (part != null) {
+ IEditorInput editorInput = part.getEditorInput();
+ if (editorInput != null) {
+ return (IJavaElement) editorInput
+ .getAdapter(IJavaElement.class);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the working copy of an compilation unit opened in an editor
+ *
+ * @param part
+ * the editor part
+ * @param cu
+ * the original compilation unit (or another working copy)
+ * @return the working copy of the compilation unit, or null if not found
+ */
+ public static ICompilationUnit getWorkingCopy(ICompilationUnit cu) {
+ if (cu == null)
+ return null;
+ if (cu.isWorkingCopy())
+ return cu;
+
+ return (ICompilationUnit) cu.findSharedWorkingCopy(JavaUI
+ .getBufferFactory());
+ }
+
+ /**
+ * Gets the working copy of an member opened in an editor
+ *
+ * @param member
+ * the original member or a member in a working copy
+ * @return the corresponding member in the shared working copy or
+ * null
if not found
+ */
+ public static IMember getWorkingCopy(IMember member)
+ throws JavaModelException {
+ ICompilationUnit cu = member.getCompilationUnit();
+ if (cu != null) {
+ ICompilationUnit workingCopy = getWorkingCopy(cu);
+ if (workingCopy != null) {
+ return JavaModelUtil.findMemberInCompilationUnit(workingCopy,
+ member);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the compilation unit for the given java element.
+ *
+ * @param element
+ * the java element whose compilation unit is searched for
+ * @return the compilation unit of the given java element
+ */
+ private static ICompilationUnit getCompilationUnit(IJavaElement element) {
+
+ if (element == null)
+ return null;
+
+ if (element instanceof IMember)
+ return ((IMember) element).getCompilationUnit();
+
+ int type = element.getElementType();
+ if (IJavaElement.COMPILATION_UNIT == type)
+ return (ICompilationUnit) element;
+ if (IJavaElement.CLASS_FILE == type)
+ return null;
+
+ return getCompilationUnit(element.getParent());
+ }
+
+ /**
+ * Returns the working copy of the given java element.
+ *
+ * @param javaElement
+ * the javaElement for which the working copyshould be found
+ * @param reconcile
+ * indicates whether the working copy must be reconcile prior to
+ * searching it
+ * @return the working copy of the given element or null
if
+ * none
+ */
+ public static IJavaElement getWorkingCopy(IJavaElement element,
+ boolean reconcile) throws JavaModelException {
+ ICompilationUnit unit = getCompilationUnit(element);
+ if (unit == null)
+ return null;
+
+ if (unit.isWorkingCopy())
+ return element;
+
+ ICompilationUnit workingCopy = getWorkingCopy(unit);
+ if (workingCopy != null) {
+ if (reconcile) {
+ synchronized (workingCopy) {
+ workingCopy.reconcile();
+ return JavaModelUtil.findInCompilationUnit(workingCopy,
+ element);
+ }
+ } else {
+ return JavaModelUtil
+ .findInCompilationUnit(workingCopy, element);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Maps the localized modifier name to a code in the same manner as
+ * #findModifier.
+ *
+ * @return the SWT modifier bit, or 0
if no match was found
+ * @see findModifier
+ * @since 2.1.1
+ */
+ public static int findLocalizedModifier(String token) {
+ if (token == null)
+ return 0;
+
+ if (token.equalsIgnoreCase(Action.findModifierString(SWT.CTRL)))
+ return SWT.CTRL;
+ if (token.equalsIgnoreCase(Action.findModifierString(SWT.SHIFT)))
+ return SWT.SHIFT;
+ if (token.equalsIgnoreCase(Action.findModifierString(SWT.ALT)))
+ return SWT.ALT;
+ if (token.equalsIgnoreCase(Action.findModifierString(SWT.COMMAND)))
+ return SWT.COMMAND;
+
+ return 0;
+ }
+
+ /**
+ * Returns the modifier string for the given SWT modifier modifier bits.
+ *
+ * @param stateMask
+ * the SWT modifier bits
+ * @return the modifier string
+ * @since 2.1.1
+ */
+ public static String getModifierString(int stateMask) {
+ String modifierString = ""; //$NON-NLS-1$
+ if ((stateMask & SWT.CTRL) == SWT.CTRL)
+ modifierString = appendModifierString(modifierString, SWT.CTRL);
+ if ((stateMask & SWT.ALT) == SWT.ALT)
+ modifierString = appendModifierString(modifierString, SWT.ALT);
+ if ((stateMask & SWT.SHIFT) == SWT.SHIFT)
+ modifierString = appendModifierString(modifierString, SWT.SHIFT);
+ if ((stateMask & SWT.COMMAND) == SWT.COMMAND)
+ modifierString = appendModifierString(modifierString, SWT.COMMAND);
+
+ return modifierString;
+ }
+
+ /**
+ * Appends to modifier string of the given SWT modifier bit to the given
+ * modifierString.
+ *
+ * @param modifierString
+ * the modifier string
+ * @param modifier
+ * an int with SWT modifier bit
+ * @return the concatenated modifier string
+ * @since 2.1.1
+ */
+ private static String appendModifierString(String modifierString,
+ int modifier) {
+ if (modifierString == null)
+ modifierString = ""; //$NON-NLS-1$
+ String newModifierString = Action.findModifierString(modifier);
+ if (modifierString.length() == 0)
+ return newModifierString;
+ return PHPEditorMessages
+ .getFormattedString(
+ "EditorUtility.concatModifierStrings", new String[] { modifierString, newModifierString }); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the Java project for a given editor input or null
+ * if no corresponding Java project exists.
+ *
+ * @param input
+ * the editor input
+ * @return the corresponding Java project
+ *
+ * @since 3.0
+ */
+ public static IJavaProject getJavaProject(IEditorInput input) {
+ IJavaProject jProject = null;
+ if (input instanceof IFileEditorInput) {
+ IProject project = ((IFileEditorInput) input).getFile()
+ .getProject();
+ if (project != null) {
+ jProject = JavaCore.create(project);
+ if (!jProject.exists())
+ jProject = null;
+ }
+ }
+ // else if (input instanceof IClassFileEditorInput) {
+ // jProject=
+ // ((IClassFileEditorInput)input).getClassFile().getJavaProject();
+ // }
+ return jProject;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/GotoAnnotationAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/GotoAnnotationAction.java
new file mode 100644
index 0000000..781cff9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/GotoAnnotationAction.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+public class GotoAnnotationAction extends TextEditorAction {
+
+ private boolean fForward;
+
+ public GotoAnnotationAction(String prefix, boolean forward) {
+ super(PHPEditorMessages.getResourceBundle(), prefix, null);
+ fForward = forward;
+ if (forward)
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.GOTO_NEXT_ERROR_ACTION);
+ else
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.GOTO_PREVIOUS_ERROR_ACTION);
+ }
+
+ public void run() {
+ PHPEditor e = (PHPEditor) getTextEditor();
+ e.gotoAnnotation(fForward);
+ }
+
+ public void setEditor(ITextEditor editor) {
+ if (editor instanceof PHPEditor)
+ super.setEditor(editor);
+ update();
+ }
+
+ public void update() {
+ setEnabled(getTextEditor() instanceof PHPEditor);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/GotoErrorAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/GotoErrorAction.java
new file mode 100644
index 0000000..8a835e2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/GotoErrorAction.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+public class GotoErrorAction extends TextEditorAction {
+
+ private boolean fForward;
+
+ public GotoErrorAction(String prefix, boolean forward) {
+ super(PHPEditorMessages.getResourceBundle(), prefix, null);
+ fForward = forward;
+ if (forward)
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.GOTO_NEXT_ERROR_ACTION);
+ else
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.GOTO_PREVIOUS_ERROR_ACTION);
+ }
+
+ public void run() {
+ PHPEditor e = (PHPEditor) getTextEditor();
+ e.gotoError(fForward);
+ }
+
+ public void setEditor(ITextEditor editor) {
+ if (editor instanceof PHPEditor)
+ super.setEditor(editor);
+ update();
+ }
+
+ public void update() {
+ setEnabled(getTextEditor() instanceof PHPEditor);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/HTMLDocumentSetupParticipant.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/HTMLDocumentSetupParticipant.java
new file mode 100644
index 0000000..9946258
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/HTMLDocumentSetupParticipant.java
@@ -0,0 +1,38 @@
+/**********************************************************************
+ Copyright (c) 2000, 2003 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * The document setup participant for PHPDT.
+ */
+public class HTMLDocumentSetupParticipant implements IDocumentSetupParticipant {
+
+ public HTMLDocumentSetupParticipant() {
+ }
+
+ /*
+ * @see org.eclipse.core.filebuffers.IDocumentSetupParticipant#setup(org.eclipse.jface.text.IDocument)
+ */
+ public void setup(IDocument document) {
+ JavaTextTools tools = WebUI.getDefault().getJavaTextTools();
+ tools.setupHTMLDocumentPartitioner(document,
+ IPHPPartitions.PHP_PARTITIONING, null); // IPHPPartitions.PHP_PARTITIONING,
+ // null);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ICompilationUnitDocumentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ICompilationUnitDocumentProvider.java
new file mode 100644
index 0000000..115130c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ICompilationUnitDocumentProvider.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.source.IAnnotationModelListener;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.IDocumentProviderExtension2;
+import org.eclipse.ui.texteditor.IDocumentProviderExtension3;
+
+/**
+ * @since 3.0
+ */
+public interface ICompilationUnitDocumentProvider extends IDocumentProvider,
+ IDocumentProviderExtension2, IDocumentProviderExtension3 {
+
+ /**
+ * Shuts down this provider.
+ */
+ void shutdown();
+
+ /**
+ * Returns the working copy for the given element.
+ *
+ * @param element
+ * the element
+ * @return the working copy for the given element
+ */
+ ICompilationUnit getWorkingCopy(Object element);
+
+ /**
+ * Saves the content of the given document to the given element. This method
+ * has only an effect if it is called when directly or indirectly inside
+ * saveDocument
.
+ *
+ * @param monitor
+ * the progress monitor
+ * @param element
+ * the element to which to save
+ * @param document
+ * the document to save
+ * @param overwrite
+ * true
if the save should be enforced
+ */
+ void saveDocumentContent(IProgressMonitor monitor, Object element,
+ IDocument document, boolean overwrite) throws CoreException;
+
+ /**
+ * Creates a line tracker for the given element. It is of the same kind as
+ * the one that would be used for a newly created document for the given
+ * element.
+ *
+ * @param element
+ * the element
+ * @return a line tracker for the given element
+ */
+ ILineTracker createLineTracker(Object element);
+
+ /**
+ * Sets the document provider's save policy.
+ *
+ * @param savePolicy
+ * the save policy
+ */
+ void setSavePolicy(ISavePolicy savePolicy);
+
+ /**
+ * Adds a listener that reports changes from all compilation unit annotation
+ * models.
+ *
+ * @param listener
+ * the listener
+ */
+ void addGlobalAnnotationModelListener(IAnnotationModelListener listener);
+
+ /**
+ * Removes the listener.
+ *
+ * @param listener
+ * the listener
+ */
+ void removeGlobalAnnotationModelListener(IAnnotationModelListener listener);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IJavaAnnotation.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IJavaAnnotation.java
new file mode 100644
index 0000000..2e109ad
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IJavaAnnotation.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Interface of annotations representing markers and problems.
+ *
+ * @see org.eclipse.core.resources.IMarker
+ * @see net.sourceforge.phpdt.core.compiler.IProblem
+ */
+public interface IJavaAnnotation {
+
+ /**
+ * @see org.eclipse.jface.text.source.Annotation#getType()
+ */
+ String getType();
+
+ /**
+ * @see org.eclipse.jface.text.source.Annotation#isPersistent()
+ */
+ boolean isPersistent();
+
+ /**
+ * @see org.eclipse.jface.text.source.Annotation#isMarkedDeleted()
+ */
+ boolean isMarkedDeleted();
+
+ /**
+ * @see org.eclipse.jface.text.source.Annotation#getText()
+ */
+ String getText();
+
+ /**
+ * Returns whether this annotation is overlaid.
+ *
+ * @return true
if overlaid
+ */
+ boolean hasOverlay();
+
+ /**
+ * Returns the overlay of this annotation.
+ *
+ * @return the annotation's overlay
+ * @since 3.0
+ */
+ IJavaAnnotation getOverlay();
+
+ /**
+ * Returns an iterator for iterating over the annotation which are overlaid
+ * by this annotation.
+ *
+ * @return an iterator over the overlaid annotaions
+ */
+ Iterator getOverlaidIterator();
+
+ /**
+ * Adds the given annotation to the list of annotations which are overlaid
+ * by this annotations.
+ *
+ * @param annotation
+ * the problem annoation
+ */
+ void addOverlaid(IJavaAnnotation annotation);
+
+ /**
+ * Removes the given annotation from the list of annotations which are
+ * overlaid by this annotation.
+ *
+ * @param annotation
+ * the problem annoation
+ */
+ void removeOverlaid(IJavaAnnotation annotation);
+
+ /**
+ * Tells whether this annotation is a problem annotation.
+ *
+ * @return true
if it is a problem annotation
+ */
+ boolean isProblem();
+
+ /**
+ * Returns the compilation unit corresponding to the document on which the
+ * annotation is set or null
if no corresponding
+ * co0mpilationunit exists.
+ */
+ ICompilationUnit getCompilationUnit();
+
+ String[] getArguments();
+
+ int getId();
+
+ Image getImage(Display display);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IJavaEditorActionConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IJavaEditorActionConstants.java
new file mode 100644
index 0000000..fd91df3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IJavaEditorActionConstants.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+/**
+ * Defines action IDs for private JavaEditor actions.
+ */
+public interface IJavaEditorActionConstants {
+
+ /**
+ * ID of the action to toggle the style of the presentation.
+ */
+ public static final String TOGGLE_PRESENTATION = "togglePresentation"; //$NON-NLS-1$
+
+ /**
+ * ID of the toolbar action to go to the previous error.
+ */
+ public static final String PREVIOUS_ERROR = "gotoPreviousError"; //$NON-NLS-1$
+
+ /**
+ * ID of the toolbar action to go to the next error.
+ */
+ public static final String NEXT_ERROR = "gotoNextError"; //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IPainter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IPainter.java
new file mode 100644
index 0000000..80d2594
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IPainter.java
@@ -0,0 +1,42 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+public interface IPainter {
+
+ /** Paint reasons */
+ int SELECTION = 0;
+
+ int TEXT_CHANGE = 1;
+
+ int KEY_STROKE = 2;
+
+ int MOUSE_BUTTON = 4;
+
+ int INTERNAL = 8;
+
+ int CONFIGURATION = 16;
+
+ /**
+ * Disposes this painter.
+ *
+ * XXX: The relationship with deactivate is not yet defined.
+ *
+ */
+ void dispose();
+
+ void paint(int reason);
+
+ /**
+ * Deactivates the painter.
+ *
+ * XXX: The relationship with dispose is not yet defined.
+ *
+ */
+ void deactivate(boolean redraw);
+
+ void setPositionManager(IPositionManager manager);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IPositionManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IPositionManager.java
new file mode 100644
index 0000000..8b4965c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IPositionManager.java
@@ -0,0 +1,15 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import org.eclipse.jface.text.Position;
+
+public interface IPositionManager {
+
+ void addManagedPosition(Position position);
+
+ void removeManagedPosition(Position position);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IProblemAnnotation.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IProblemAnnotation.java
new file mode 100644
index 0000000..bd6a3ee
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/IProblemAnnotation.java
@@ -0,0 +1,59 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.util.Iterator;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Interface of annotations representing problems.
+ */
+public interface IProblemAnnotation {
+
+ AnnotationType getAnnotationType();
+
+ boolean isTemporary();
+
+ String getMessage();
+
+ String[] getArguments();
+
+ int getId();
+
+ Image getImage(Display display);
+
+ boolean isRelevant();
+
+ boolean hasOverlay();
+
+ Iterator getOverlaidIterator();
+
+ void addOverlaid(IProblemAnnotation annotation);
+
+ void removeOverlaid(IProblemAnnotation annotation);
+
+ /**
+ * @deprecated
+ */
+ boolean isProblem();
+
+ /**
+ * @deprecated
+ */
+ boolean isTask();
+
+ /**
+ * @deprecated
+ */
+ boolean isWarning();
+
+ /**
+ * @deprecated
+ */
+ boolean isError();
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ISavePolicy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ISavePolicy.java
new file mode 100644
index 0000000..4b26a0c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ISavePolicy.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+public interface ISavePolicy {
+
+ /**
+ *
+ */
+ void preSave(ICompilationUnit unit);
+
+ /**
+ * Returns the compilation unit in which the argument has been changed. If
+ * the argument is not changed, the returned result is null
.
+ */
+ ICompilationUnit postSave(ICompilationUnit unit);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaAnnotationImageProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaAnnotationImageProvider.java
new file mode 100644
index 0000000..ae92cf6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaAnnotationImageProvider.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.IAnnotationImageProvider;
+
+/**
+ * Image provider for annotations based on Java problem markers.
+ *
+ * @since 3.0
+ */
+public class JavaAnnotationImageProvider implements IAnnotationImageProvider {
+
+ private final static int NO_IMAGE = 0;
+
+ private final static int GRAY_IMAGE = 1;
+
+ private final static int OVERLAY_IMAGE = 2;
+
+ private final static int QUICKFIX_IMAGE = 3;
+
+ private final static int QUICKFIX_ERROR_IMAGE = 4;
+
+ private static Image fgQuickFixImage;
+
+ private static Image fgQuickFixErrorImage;
+
+ private static ImageRegistry fgImageRegistry;
+
+ private boolean fShowQuickFixIcon;
+
+ private int fCachedImageType;
+
+ private Image fCachedImage;
+
+ public JavaAnnotationImageProvider() {
+ fShowQuickFixIcon = PreferenceConstants.getPreferenceStore()
+ .getBoolean(PreferenceConstants.EDITOR_CORRECTION_INDICATION);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationImageProvider#getManagedImage(org.eclipse.jface.text.source.Annotation)
+ */
+ public Image getManagedImage(Annotation annotation) {
+ if (annotation instanceof IJavaAnnotation) {
+ IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
+ int imageType = getImageType(javaAnnotation);
+ return getImage(javaAnnotation, imageType, Display.getCurrent());
+ }
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationImageProvider#getImageDescriptorId(org.eclipse.jface.text.source.Annotation)
+ */
+ public String getImageDescriptorId(Annotation annotation) {
+ // unmanaged images are not supported
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationImageProvider#getImageDescriptor(java.lang.String)
+ */
+ public ImageDescriptor getImageDescriptor(String symbolicName) {
+ // unmanaged images are not supported
+ return null;
+ }
+
+ private boolean showQuickFix(IJavaAnnotation annotation) {
+ // return fShowQuickFixIcon && annotation.isProblem() &&
+ // JavaCorrectionProcessor.hasCorrections(annotation);
+ return false;
+ }
+
+ private Image getQuickFixImage() {
+ if (fgQuickFixImage == null)
+ fgQuickFixImage = PHPUiImages
+ .get(PHPUiImages.IMG_OBJS_FIXABLE_PROBLEM);
+ return fgQuickFixImage;
+ }
+
+ private Image getQuickFixErrorImage() {
+ if (fgQuickFixErrorImage == null)
+ fgQuickFixErrorImage = PHPUiImages
+ .get(PHPUiImages.IMG_OBJS_FIXABLE_ERROR);
+ return fgQuickFixErrorImage;
+ }
+
+ private ImageRegistry getImageRegistry(Display display) {
+ if (fgImageRegistry == null)
+ fgImageRegistry = new ImageRegistry(display);
+ return fgImageRegistry;
+ }
+
+ private int getImageType(IJavaAnnotation annotation) {
+ int imageType = NO_IMAGE;
+ if (annotation.hasOverlay())
+ imageType = OVERLAY_IMAGE;
+ else if (!annotation.isMarkedDeleted()) {
+ if (showQuickFix(annotation))
+ imageType = JavaMarkerAnnotation.ERROR_ANNOTATION_TYPE
+ .equals(annotation.getType()) ? QUICKFIX_ERROR_IMAGE
+ : QUICKFIX_IMAGE;
+ } else {
+ imageType = GRAY_IMAGE;
+ }
+ return imageType;
+ }
+
+ private Image getImage(IJavaAnnotation annotation, int imageType,
+ Display display) {
+ if (fCachedImageType == imageType)
+ return fCachedImage;
+
+ Image image = null;
+ switch (imageType) {
+ case OVERLAY_IMAGE:
+ IJavaAnnotation overlay = annotation.getOverlay();
+ image = overlay.getImage(display);
+ break;
+ case QUICKFIX_IMAGE:
+ image = getQuickFixImage();
+ break;
+ case QUICKFIX_ERROR_IMAGE:
+ image = getQuickFixErrorImage();
+ break;
+ case GRAY_IMAGE: {
+ ISharedImages sharedImages = PlatformUI.getWorkbench()
+ .getSharedImages();
+ String annotationType = annotation.getType();
+ if (JavaMarkerAnnotation.ERROR_ANNOTATION_TYPE
+ .equals(annotationType)) {
+ image = sharedImages.getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
+ } else if (JavaMarkerAnnotation.WARNING_ANNOTATION_TYPE
+ .equals(annotationType)) {
+ image = sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK);
+ } else if (JavaMarkerAnnotation.INFO_ANNOTATION_TYPE
+ .equals(annotationType)) {
+ image = sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK);
+ }
+ if (image != null) {
+ ImageRegistry registry = getImageRegistry(display);
+ String key = Integer.toString(image.hashCode());
+ Image grayImage = registry.get(key);
+ if (grayImage == null) {
+ grayImage = new Image(display, image, SWT.IMAGE_GRAY);
+ registry.put(key, grayImage);
+ }
+ image = grayImage;
+ }
+ break;
+ }
+ }
+
+ fCachedImageType = imageType;
+ fCachedImage = image;
+ return fCachedImage;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaAnnotationIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaAnnotationIterator.java
new file mode 100644
index 0000000..40ef7c2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaAnnotationIterator.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+
+/**
+ * Filters problems based on their types.
+ */
+public class JavaAnnotationIterator implements Iterator {
+
+ private Iterator fIterator;
+
+ private Annotation fNext;
+
+ private boolean fSkipIrrelevants;
+
+ private boolean fReturnAllAnnotations;
+
+ /**
+ * Equivalent to
+ * JavaAnnotationIterator(model, skipIrrelevants, false)
.
+ */
+ public JavaAnnotationIterator(IAnnotationModel model,
+ boolean skipIrrelevants) {
+ this(model, skipIrrelevants, false);
+ }
+
+ /**
+ * Returns a new JavaAnnotationIterator.
+ *
+ * @param model
+ * the annotation model
+ * @param skipIrrelevants
+ * whether to skip irrelevant annotations
+ * @param returnAllAnnotations
+ * Whether to return non IJavaAnnotations as well
+ */
+ public JavaAnnotationIterator(IAnnotationModel model,
+ boolean skipIrrelevants, boolean returnAllAnnotations) {
+ fReturnAllAnnotations = returnAllAnnotations;
+ if (model != null)
+ fIterator = model.getAnnotationIterator();
+ else
+ fIterator = Collections.EMPTY_LIST.iterator();
+ fSkipIrrelevants = skipIrrelevants;
+ skip();
+ }
+
+ private void skip() {
+ while (fIterator.hasNext()) {
+ Annotation next = (Annotation) fIterator.next();
+ if (next instanceof IJavaAnnotation) {
+ if (fSkipIrrelevants) {
+ if (!next.isMarkedDeleted()) {
+ fNext = next;
+ return;
+ }
+ } else {
+ fNext = next;
+ return;
+ }
+ } else if (fReturnAllAnnotations) {
+ fNext = next;
+ return;
+ }
+ }
+ fNext = null;
+ }
+
+ /*
+ * @see Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return fNext != null;
+ }
+
+ /*
+ * @see Iterator#next()
+ */
+ public Object next() {
+ try {
+ return fNext;
+ } finally {
+ skip();
+ }
+ }
+
+ /*
+ * @see Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaDocumentFactory.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaDocumentFactory.java
new file mode 100644
index 0000000..1166d26
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaDocumentFactory.java
@@ -0,0 +1,30 @@
+/**********************************************************************
+ Copyright (c) 2000, 2003 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.core.filebuffers.IDocumentFactory;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * The document factory for JDT UI,
+ */
+public class JavaDocumentFactory implements IDocumentFactory {
+
+ public JavaDocumentFactory() {
+ }
+
+ /*
+ * @see org.eclipse.core.filebuffers.IDocumentFactory#createDocument()
+ */
+ public IDocument createDocument() {
+ return new PartiallySynchronizedDocument();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaDocumentSetupParticipant.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaDocumentSetupParticipant.java
new file mode 100644
index 0000000..c4cd4a9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaDocumentSetupParticipant.java
@@ -0,0 +1,41 @@
+/**********************************************************************
+ Copyright (c) 2000, 2003 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * The document setup participant for PHPDT.
+ */
+public class JavaDocumentSetupParticipant implements IDocumentSetupParticipant {
+
+ public JavaDocumentSetupParticipant() {
+ }
+
+ /*
+ * @see org.eclipse.core.filebuffers.IDocumentSetupParticipant#setup(org.eclipse.jface.text.IDocument)
+ */
+ public void setup(IDocument document) {
+ JavaTextTools tools = WebUI.getDefault().getJavaTextTools();
+ tools.setupJavaDocumentPartitioner(document,
+ IPHPPartitions.PHP_PARTITIONING);
+
+ // tools.setupJavaDocumentPartitioner(document,
+ // IPHPPartitions.PHP_PARTITIONING, null);
+ // //IPHPPartitions.PHP_PARTITIONING, null);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaEditorErrorTickUpdater.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaEditorErrorTickUpdater.java
new file mode 100644
index 0000000..e1ecf5f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaEditorErrorTickUpdater.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.ui.viewsupport.IProblemChangedListener;
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementImageProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaUILabelProvider;
+import net.sourceforge.phpdt.ui.ProblemsLabelDecorator;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+
+/**
+ * The JavaEditorErrorTickUpdater
will register as a
+ * IProblemChangedListener to listen on problem changes of the editor's input.
+ * It updates the title images when the annotation model changed.
+ */
+public class JavaEditorErrorTickUpdater implements IProblemChangedListener {
+
+ private PHPEditor fJavaEditor;
+
+ private JavaUILabelProvider fLabelProvider;
+
+ public JavaEditorErrorTickUpdater(PHPEditor editor) {
+ Assert.isNotNull(editor);
+ fJavaEditor = editor;
+ fLabelProvider = new JavaUILabelProvider(0,
+ JavaElementImageProvider.SMALL_ICONS);
+ fLabelProvider.addLabelDecorator(new ProblemsLabelDecorator(null));
+ WebUI.getDefault().getProblemMarkerManager().addListener(
+ this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see IProblemChangedListener#problemsChanged(IResource[], boolean)
+ */
+ public void problemsChanged(IResource[] changedResources,
+ boolean isMarkerChange) {
+ if (isMarkerChange) {
+ return;
+ }
+ IEditorInput input = fJavaEditor.getEditorInput();
+ if (input != null) { // might run async, tests needed
+ IJavaElement jelement = (IJavaElement) input
+ .getAdapter(IJavaElement.class);
+ if (jelement != null) {
+ IResource resource = jelement.getResource();
+ for (int i = 0; i < changedResources.length; i++) {
+ if (changedResources[i].equals(resource)) {
+ updateEditorImage(jelement);
+ }
+ }
+ }
+ }
+ }
+
+ public void updateEditorImage(IJavaElement jelement) {
+ Image titleImage = fJavaEditor.getTitleImage();
+ if (titleImage == null) {
+ return;
+ }
+ Image newImage = fLabelProvider.getImage(jelement);
+ if (titleImage != newImage) {
+ postImageChange(newImage);
+ }
+ }
+
+ private void postImageChange(final Image newImage) {
+ Shell shell = fJavaEditor.getEditorSite().getShell();
+ if (shell != null && !shell.isDisposed()) {
+ shell.getDisplay().syncExec(new Runnable() {
+ public void run() {
+ fJavaEditor.updatedTitleImage(newImage);
+ }
+ });
+ }
+ }
+
+ public void dispose() {
+ fLabelProvider.dispose();
+ WebUI.getDefault().getProblemMarkerManager().removeListener(
+ this);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaMarkerAnnotation.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaMarkerAnnotation.java
new file mode 100644
index 0000000..e72f265
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaMarkerAnnotation.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaModelMarker;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+
+public class JavaMarkerAnnotation extends MarkerAnnotation implements
+ IJavaAnnotation {
+
+ public static final String JAVA_MARKER_TYPE_PREFIX = "net.sourceforge.phpdt"; //$NON-NLS-1$
+
+ public static final String ERROR_ANNOTATION_TYPE = "net.sourceforge.phpdt.ui.error"; //$NON-NLS-1$
+
+ public static final String WARNING_ANNOTATION_TYPE = "net.sourceforge.phpdt.ui.warning"; //$NON-NLS-1$
+
+ public static final String INFO_ANNOTATION_TYPE = "net.sourceforge.phpdt.ui.info"; //$NON-NLS-1$
+
+ public static final String TASK_ANNOTATION_TYPE = "org.eclipse.ui.workbench.texteditor.task"; //$NON-NLS-1$
+
+ private IJavaAnnotation fOverlay;
+
+ public JavaMarkerAnnotation(IMarker marker) {
+ super(marker);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.IJavaAnnotation#getImage(org.eclipse.swt.widgets.Display)
+ */
+ public Image getImage(Display display) {
+ return super.getImage(display);
+ }
+
+ /*
+ * @see IJavaAnnotation#getArguments()
+ */
+ public String[] getArguments() {
+ IMarker marker = getMarker();
+ if (marker != null && marker.exists() && isProblem())
+ return JavaModelUtil.getProblemArgumentsFromMarker(marker
+ .getAttribute(IJavaModelMarker.ARGUMENTS, "")); //$NON-NLS-1$
+ return null;
+ }
+
+ /*
+ * @see IJavaAnnotation#getId()
+ */
+ public int getId() {
+ IMarker marker = getMarker();
+ if (marker == null || !marker.exists())
+ return -1;
+
+ if (isProblem())
+ return marker.getAttribute(IJavaModelMarker.ID, -1);
+
+ // if (TASK_ANNOTATION_TYPE.equals(getAnnotationType())) {
+ // try {
+ // if (marker.isSubtypeOf(IJavaModelMarker.TASK_MARKER)) {
+ // return IProblem.Task;
+ // }
+ // } catch (CoreException e) {
+ // JavaPlugin.log(e); // should no happen, we test for marker.exists
+ // }
+ // }
+
+ return -1;
+ }
+
+ /*
+ * @see IJavaAnnotation#isProblem()
+ */
+ public boolean isProblem() {
+ String type = getType();
+ return WARNING_ANNOTATION_TYPE.equals(type)
+ || ERROR_ANNOTATION_TYPE.equals(type);
+ }
+
+ /**
+ * Overlays this annotation with the given javaAnnotation.
+ *
+ * @param javaAnnotation
+ * annotation that is overlaid by this annotation
+ */
+ public void setOverlay(IJavaAnnotation javaAnnotation) {
+ if (fOverlay != null)
+ fOverlay.removeOverlaid(this);
+
+ fOverlay = javaAnnotation;
+ if (!isMarkedDeleted())
+ markDeleted(fOverlay != null);
+
+ if (fOverlay != null)
+ fOverlay.addOverlaid(this);
+ }
+
+ /*
+ * @see IJavaAnnotation#hasOverlay()
+ */
+ public boolean hasOverlay() {
+ return fOverlay != null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.IJavaAnnotation#getOverlay()
+ */
+ public IJavaAnnotation getOverlay() {
+ return fOverlay;
+ }
+
+ /*
+ * @see IJavaAnnotation#addOverlaid(IJavaAnnotation)
+ */
+ public void addOverlaid(IJavaAnnotation annotation) {
+ // not supported
+ }
+
+ /*
+ * @see IJavaAnnotation#removeOverlaid(IJavaAnnotation)
+ */
+ public void removeOverlaid(IJavaAnnotation annotation) {
+ // not supported
+ }
+
+ /*
+ * @see IJavaAnnotation#getOverlaidIterator()
+ */
+ public Iterator getOverlaidIterator() {
+ // not supported
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.IJavaAnnotation#getCompilationUnit()
+ */
+ public ICompilationUnit getCompilationUnit() {
+ IJavaElement element = JavaCore.create(getMarker().getResource());
+ if (element instanceof ICompilationUnit) {
+ ICompilationUnit cu = (ICompilationUnit) element;
+ ICompilationUnit workingCopy = EditorUtility.getWorkingCopy(cu);
+ if (workingCopy != null) {
+ return workingCopy;
+ }
+ return cu;
+ }
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java
new file mode 100644
index 0000000..9dac4f3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java
@@ -0,0 +1,1428 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.Vector;
+
+import net.sourceforge.phpdt.core.ElementChangedEvent;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IElementChangedListener;
+import net.sourceforge.phpdt.core.IField;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaElementDelta;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.actions.AbstractToggleLinkingAction;
+import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
+import net.sourceforge.phpdt.internal.ui.preferences.MembersOrderPreferenceCache;
+import net.sourceforge.phpdt.internal.ui.viewsupport.AppearanceAwareLabelProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.DecoratingJavaLabelProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels;
+import net.sourceforge.phpdt.internal.ui.viewsupport.StatusBarUpdater;
+import net.sourceforge.phpdt.ui.JavaElementSorter;
+import net.sourceforge.phpdt.ui.JavaUI;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.ProblemsLabelDecorator.ProblemsLabelChangedEvent;
+import net.sourceforge.phpdt.ui.actions.CustomFiltersActionGroup;
+import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
+import net.sourceforge.phpdt.ui.actions.MemberFilterActionGroup;
+import net.sourceforge.phpdt.ui.actions.PHPdtActionConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+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.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionContext;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+import org.eclipse.ui.model.WorkbenchAdapter;
+import org.eclipse.ui.part.IPageSite;
+import org.eclipse.ui.part.IShowInSource;
+import org.eclipse.ui.part.IShowInTarget;
+import org.eclipse.ui.part.IShowInTargetList;
+import org.eclipse.ui.part.Page;
+import org.eclipse.ui.part.ShowInContext;
+import org.eclipse.ui.texteditor.GotoAnnotationAction;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.ui.texteditor.TextEditorAction;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
+
+/**
+ * The content outline page of the Java editor. The viewer implements a
+ * proprietary update mechanism based on Java model deltas. It does not react on
+ * domain changes. It is specified to show the content of ICompilationUnits and
+ * IClassFiles. Publishes its context menu under
+ * PHPeclipsePlugin.getDefault().getPluginId() + ".outline"
.
+ */
+public class JavaOutlinePage extends Page implements IContentOutlinePage,
+ IAdaptable, IPostSelectionProvider {
+
+ static Object[] NO_CHILDREN = new Object[0];
+
+ /**
+ * The element change listener of the java outline viewer.
+ *
+ * @see IElementChangedListener
+ */
+ class ElementChangedListener implements IElementChangedListener {
+
+ public void elementChanged(final ElementChangedEvent e) {
+
+ if (getControl() == null)
+ return;
+
+ Display d = getControl().getDisplay();
+ if (d != null) {
+ d.asyncExec(new Runnable() {
+ public void run() {
+ ICompilationUnit cu = (ICompilationUnit) fInput;
+ IJavaElement base = cu;
+ // if (fTopLevelTypeOnly) {
+ // base= getMainType(cu);
+ // if (base == null) {
+ if (fOutlineViewer != null)
+ fOutlineViewer.refresh(true);
+ return;
+ // }
+ // }
+ // IJavaElementDelta delta= findElement(base,
+ // e.getDelta());
+ // if (delta != null && fOutlineViewer != null) {
+ // fOutlineViewer.reconcile(delta);
+ // }
+ }
+ });
+ }
+ }
+
+ private boolean isPossibleStructuralChange(IJavaElementDelta cuDelta) {
+ if (cuDelta.getKind() != IJavaElementDelta.CHANGED) {
+ return true; // add or remove
+ }
+ int flags = cuDelta.getFlags();
+ if ((flags & IJavaElementDelta.F_CHILDREN) != 0) {
+ return true;
+ }
+ return (flags & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_FINE_GRAINED)) == IJavaElementDelta.F_CONTENT;
+ }
+
+ protected IJavaElementDelta findElement(IJavaElement unit,
+ IJavaElementDelta delta) {
+
+ if (delta == null || unit == null)
+ return null;
+
+ IJavaElement element = delta.getElement();
+
+ if (unit.equals(element)) {
+ if (isPossibleStructuralChange(delta)) {
+ return delta;
+ }
+ return null;
+ }
+
+ if (element.getElementType() > IJavaElement.CLASS_FILE)
+ return null;
+
+ IJavaElementDelta[] children = delta.getAffectedChildren();
+ if (children == null || children.length == 0)
+ return null;
+
+ for (int i = 0; i < children.length; i++) {
+ IJavaElementDelta d = findElement(unit, children[i]);
+ if (d != null)
+ return d;
+ }
+
+ return null;
+ }
+ }
+
+ static class NoClassElement extends WorkbenchAdapter implements IAdaptable {
+ /*
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return PHPEditorMessages
+ .getString("JavaOutlinePage.error.NoTopLevelType"); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class)
+ */
+ public Object getAdapter(Class clas) {
+ if (clas == IWorkbenchAdapter.class)
+ return this;
+ return null;
+ }
+ }
+
+ /**
+ * Content provider for the children of an ICompilationUnit or an IClassFile
+ *
+ * @see ITreeContentProvider
+ */
+ class ChildrenProvider implements ITreeContentProvider {
+
+ private Object[] NO_CLASS = new Object[] { new NoClassElement() };
+
+ private ElementChangedListener fListener;
+
+ protected boolean matches(IJavaElement element) {
+ if (element.getElementType() == IJavaElement.METHOD) {
+ String name = element.getElementName();
+ return (name != null && name.indexOf('<') >= 0);
+ }
+ return false;
+ }
+
+ protected IJavaElement[] filter(IJavaElement[] children) {
+ boolean initializers = false;
+ for (int i = 0; i < children.length; i++) {
+ if (matches(children[i])) {
+ initializers = true;
+ break;
+ }
+ }
+
+ if (!initializers)
+ return children;
+
+ Vector v = new Vector();
+ for (int i = 0; i < children.length; i++) {
+ if (matches(children[i]))
+ continue;
+ v.addElement(children[i]);
+ }
+
+ IJavaElement[] result = new IJavaElement[v.size()];
+ v.copyInto(result);
+ return result;
+ }
+
+ public Object[] getChildren(Object parent) {
+ if (parent instanceof IParent) {
+ IParent c = (IParent) parent;
+ try {
+ return filter(c.getChildren());
+ } catch (JavaModelException x) {
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=38341
+ // don't log NotExist exceptions as this is a valid case
+ // since we might have been posted and the element
+ // removed in the meantime.
+ if (PHPeclipsePlugin.isDebug() || !x.isDoesNotExist())
+ PHPeclipsePlugin.log(x);
+ }
+ }
+ return NO_CHILDREN;
+ }
+
+ public Object[] getElements(Object parent) {
+ if (fTopLevelTypeOnly) {
+ if (parent instanceof ICompilationUnit) {
+ try {
+ IType type = getMainType((ICompilationUnit) parent);
+ return type != null ? type.getChildren() : NO_CLASS;
+ } catch (JavaModelException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ // else if (parent instanceof IClassFile) {
+ // try {
+ // IType type= getMainType((IClassFile) parent);
+ // return type != null ? type.getChildren() : NO_CLASS;
+ // } catch (JavaModelException e) {
+ // PHPeclipsePlugin.log(e);
+ // }
+ // }
+ }
+ return getChildren(parent);
+ }
+
+ public Object getParent(Object child) {
+ if (child instanceof IJavaElement) {
+ IJavaElement e = (IJavaElement) child;
+ return e.getParent();
+ }
+ return null;
+ }
+
+ public boolean hasChildren(Object parent) {
+ if (parent instanceof IParent) {
+ IParent c = (IParent) parent;
+ try {
+ IJavaElement[] children = filter(c.getChildren());
+ return (children != null && children.length > 0);
+ } catch (JavaModelException x) {
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=38341
+ // don't log NotExist exceptions as this is a valid case
+ // since we might have been posted and the element
+ // removed in the meantime.
+ if (PHPeclipsePlugin.isDebug() || !x.isDoesNotExist())
+ PHPeclipsePlugin.log(x);
+ }
+ }
+ return false;
+ }
+
+ public boolean isDeleted(Object o) {
+ return false;
+ }
+
+ public void dispose() {
+ if (fListener != null) {
+ JavaCore.removeElementChangedListener(fListener);
+ fListener = null;
+ }
+ }
+
+ /*
+ * @see IContentProvider#inputChanged(Viewer, Object, Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ boolean isCU = (newInput instanceof ICompilationUnit);
+
+ if (isCU && fListener == null) {
+ fListener = new ElementChangedListener();
+ JavaCore.addElementChangedListener(fListener);
+ } else if (!isCU && fListener != null) {
+ JavaCore.removeElementChangedListener(fListener);
+ fListener = null;
+ }
+ }
+ }
+
+ class JavaOutlineViewer extends TreeViewer {
+
+ /**
+ * Indicates an item which has been reused. At the point of its reuse it
+ * has been expanded. This field is used to communicate between
+ * internalExpandToLevel
and reuseTreeItem
.
+ */
+ private Item fReusedExpandedItem;
+
+ private boolean fReorderedMembers;
+
+ private boolean fForceFireSelectionChanged;
+
+ public JavaOutlineViewer(Tree tree) {
+ super(tree);
+ setAutoExpandLevel(ALL_LEVELS);
+ setUseHashlookup(true);
+ }
+
+ /**
+ * Investigates the given element change event and if affected
+ * incrementally updates the Java outline.
+ *
+ * @param delta
+ * the Java element delta used to reconcile the Java outline
+ */
+ public void reconcile(IJavaElementDelta delta) {
+ fReorderedMembers = false;
+ fForceFireSelectionChanged = false;
+ if (getSorter() == null) {
+ if (fTopLevelTypeOnly && delta.getElement() instanceof IType
+ && (delta.getKind() & IJavaElementDelta.ADDED) != 0) {
+ refresh(true);
+
+ } else {
+ Widget w = findItem(fInput);
+ if (w != null && !w.isDisposed())
+ update(w, delta);
+ if (fForceFireSelectionChanged)
+ fireSelectionChanged(new SelectionChangedEvent(
+ getSite().getSelectionProvider(), this
+ .getSelection()));
+ if (fReorderedMembers) {
+ refresh(false);
+ fReorderedMembers = false;
+ }
+ }
+ } else {
+ // just for now
+ refresh(true);
+ }
+ }
+
+ /*
+ * @see TreeViewer#internalExpandToLevel
+ */
+ protected void internalExpandToLevel(Widget node, int level) {
+ if (node instanceof Item) {
+ Item i = (Item) node;
+ if (i.getData() instanceof IJavaElement) {
+ IJavaElement je = (IJavaElement) i.getData();
+ if (je.getElementType() == IJavaElement.IMPORT_CONTAINER
+ || isInnerType(je)) {
+ if (i != fReusedExpandedItem) {
+ setExpanded(i, false);
+ return;
+ }
+ }
+ }
+ }
+ super.internalExpandToLevel(node, level);
+ }
+
+ protected void reuseTreeItem(Item item, Object element) {
+
+ // remove children
+ Item[] c = getChildren(item);
+ if (c != null && c.length > 0) {
+
+ if (getExpanded(item))
+ fReusedExpandedItem = item;
+
+ for (int k = 0; k < c.length; k++) {
+ if (c[k].getData() != null)
+ disassociate(c[k]);
+ c[k].dispose();
+ }
+ }
+
+ updateItem(item, element);
+ updatePlus(item, element);
+ internalExpandToLevel(item, ALL_LEVELS);
+
+ fReusedExpandedItem = null;
+ fForceFireSelectionChanged = true;
+ }
+
+ protected boolean mustUpdateParent(IJavaElementDelta delta,
+ IJavaElement element) {
+ if (element instanceof IMethod) {
+ if ((delta.getKind() & IJavaElementDelta.ADDED) != 0) {
+ try {
+ return ((IMethod) element).isMainMethod();
+ } catch (JavaModelException e) {
+ PHPeclipsePlugin.log(e.getStatus());
+ }
+ }
+ return "main".equals(element.getElementName()); //$NON-NLS-1$
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.AbstractTreeViewer#isExpandable(java.lang.Object)
+ */
+ public boolean isExpandable(Object element) {
+ if (hasFilters()) {
+ return getFilteredChildren(element).length > 0;
+ }
+ return super.isExpandable(element);
+ }
+
+ protected ISourceRange getSourceRange(IJavaElement element)
+ throws JavaModelException {
+ if (element instanceof ISourceReference)
+ return ((ISourceReference) element).getSourceRange();
+ if (element instanceof IMember)// && !(element instanceof
+ // IInitializer))
+ return ((IMember) element).getNameRange();
+ return null;
+ }
+
+ protected boolean overlaps(ISourceRange range, int start, int end) {
+ return start <= (range.getOffset() + range.getLength() - 1)
+ && range.getOffset() <= end;
+ }
+
+ protected boolean filtered(IJavaElement parent, IJavaElement child) {
+
+ Object[] result = new Object[] { child };
+ ViewerFilter[] filters = getFilters();
+ for (int i = 0; i < filters.length; i++) {
+ result = filters[i].filter(this, parent, result);
+ if (result.length == 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ protected void update(Widget w, IJavaElementDelta delta) {
+
+ Item item;
+
+ IJavaElement parent = delta.getElement();
+ IJavaElementDelta[] affected = delta.getAffectedChildren();
+ Item[] children = getChildren(w);
+
+ boolean doUpdateParent = false;
+ boolean doUpdateParentsPlus = false;
+
+ Vector deletions = new Vector();
+ Vector additions = new Vector();
+
+ for (int i = 0; i < affected.length; i++) {
+ IJavaElementDelta affectedDelta = affected[i];
+ IJavaElement affectedElement = affectedDelta.getElement();
+ int status = affected[i].getKind();
+
+ // find tree item with affected element
+ int j;
+ for (j = 0; j < children.length; j++)
+ if (affectedElement.equals(children[j].getData()))
+ break;
+
+ if (j == children.length) {
+ // remove from collapsed parent
+ if ((status & IJavaElementDelta.REMOVED) != 0) {
+ doUpdateParentsPlus = true;
+ continue;
+ }
+ // addition
+ if ((status & IJavaElementDelta.CHANGED) != 0
+ && (affectedDelta.getFlags() & IJavaElementDelta.F_MODIFIERS) != 0
+ && !filtered(parent, affectedElement)) {
+ additions.addElement(affectedDelta);
+ }
+ continue;
+ }
+
+ item = children[j];
+
+ // removed
+ if ((status & IJavaElementDelta.REMOVED) != 0) {
+ deletions.addElement(item);
+ doUpdateParent = doUpdateParent
+ || mustUpdateParent(affectedDelta, affectedElement);
+
+ // changed
+ } else if ((status & IJavaElementDelta.CHANGED) != 0) {
+ int change = affectedDelta.getFlags();
+ doUpdateParent = doUpdateParent
+ || mustUpdateParent(affectedDelta, affectedElement);
+
+ if ((change & IJavaElementDelta.F_MODIFIERS) != 0) {
+ if (filtered(parent, affectedElement))
+ deletions.addElement(item);
+ else
+ updateItem(item, affectedElement);
+ }
+
+ if ((change & IJavaElementDelta.F_CONTENT) != 0)
+ updateItem(item, affectedElement);
+
+ if ((change & IJavaElementDelta.F_CHILDREN) != 0)
+ update(item, affectedDelta);
+
+ if ((change & IJavaElementDelta.F_REORDER) != 0)
+ fReorderedMembers = true;
+ }
+ }
+
+ // find all elements to add
+ IJavaElementDelta[] add = delta.getAddedChildren();
+ if (additions.size() > 0) {
+ IJavaElementDelta[] tmp = new IJavaElementDelta[add.length
+ + additions.size()];
+ System.arraycopy(add, 0, tmp, 0, add.length);
+ for (int i = 0; i < additions.size(); i++)
+ tmp[i + add.length] = (IJavaElementDelta) additions
+ .elementAt(i);
+ add = tmp;
+ }
+
+ // add at the right position
+ go2: for (int i = 0; i < add.length; i++) {
+
+ try {
+
+ IJavaElement e = add[i].getElement();
+ if (filtered(parent, e))
+ continue go2;
+
+ doUpdateParent = doUpdateParent
+ || mustUpdateParent(add[i], e);
+ ISourceRange rng = getSourceRange(e);
+ int start = rng.getOffset();
+ int end = start + rng.getLength() - 1;
+ int nameOffset = Integer.MAX_VALUE;
+ if (e instanceof IField) {
+ ISourceRange nameRange = ((IField) e).getNameRange();
+ if (nameRange != null)
+ nameOffset = nameRange.getOffset();
+ }
+
+ Item last = null;
+ item = null;
+ children = getChildren(w);
+
+ for (int j = 0; j < children.length; j++) {
+ item = children[j];
+ IJavaElement r = (IJavaElement) item.getData();
+
+ if (r == null) {
+ // parent node collapsed and not be opened before ->
+ // do nothing
+ continue go2;
+ }
+
+ try {
+ rng = getSourceRange(r);
+
+ // multi-field declarations always start at
+ // the same offset. They also have the same
+ // end offset if the field sequence is terminated
+ // with a semicolon. If not, the source range
+ // ends behind the identifier / initializer
+ // see
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=51851
+ boolean multiFieldDeclaration = r.getElementType() == IJavaElement.FIELD
+ && e.getElementType() == IJavaElement.FIELD
+ && rng.getOffset() == start;
+
+ // elements are inserted by occurrence
+ // however, multi-field declarations have
+ // equal source ranges offsets, therefore we
+ // compare name-range offsets.
+ boolean multiFieldOrderBefore = false;
+ if (multiFieldDeclaration) {
+ if (r instanceof IField) {
+ ISourceRange nameRange = ((IField) r)
+ .getNameRange();
+ if (nameRange != null) {
+ if (nameRange.getOffset() > nameOffset)
+ multiFieldOrderBefore = true;
+ }
+ }
+ }
+
+ if (!multiFieldDeclaration
+ && overlaps(rng, start, end)) {
+
+ // be tolerant if the delta is not correct, or
+ // if
+ // the tree has been updated other than by a
+ // delta
+ reuseTreeItem(item, e);
+ continue go2;
+
+ } else if (multiFieldOrderBefore
+ || rng.getOffset() > start) {
+
+ if (last != null && deletions.contains(last)) {
+ // reuse item
+ deletions.removeElement(last);
+ reuseTreeItem(last, e);
+ } else {
+ // nothing to reuse
+ createTreeItem(w, e, j);
+ }
+ continue go2;
+ }
+
+ } catch (JavaModelException x) {
+ // stumbled over deleted element
+ }
+
+ last = item;
+ }
+
+ // add at the end of the list
+ if (last != null && deletions.contains(last)) {
+ // reuse item
+ deletions.removeElement(last);
+ reuseTreeItem(last, e);
+ } else {
+ // nothing to reuse
+ createTreeItem(w, e, -1);
+ }
+
+ } catch (JavaModelException x) {
+ // the element to be added is not present -> don't add it
+ }
+ }
+
+ // remove items which haven't been reused
+ Enumeration e = deletions.elements();
+ while (e.hasMoreElements()) {
+ item = (Item) e.nextElement();
+ disassociate(item);
+ item.dispose();
+ }
+
+ if (doUpdateParent)
+ updateItem(w, delta.getElement());
+ if (!doUpdateParent && doUpdateParentsPlus && w instanceof Item)
+ updatePlus((Item) w, delta.getElement());
+ }
+
+ /*
+ * @see ContentViewer#handleLabelProviderChanged(LabelProviderChangedEvent)
+ */
+ protected void handleLabelProviderChanged(
+ LabelProviderChangedEvent event) {
+ Object input = getInput();
+ if (event instanceof ProblemsLabelChangedEvent) {
+ ProblemsLabelChangedEvent e = (ProblemsLabelChangedEvent) event;
+ if (e.isMarkerChange() && input instanceof ICompilationUnit) {
+ return; // marker changes can be ignored
+ }
+ }
+ // look if the underlying resource changed
+ Object[] changed = event.getElements();
+ if (changed != null) {
+ IResource resource = getUnderlyingResource();
+ if (resource != null) {
+ for (int i = 0; i < changed.length; i++) {
+ if (changed[i] != null && changed[i].equals(resource)) {
+ // change event to a full refresh
+ event = new LabelProviderChangedEvent(
+ (IBaseLabelProvider) event.getSource());
+ break;
+ }
+ }
+ }
+ }
+ super.handleLabelProviderChanged(event);
+ }
+
+ private IResource getUnderlyingResource() {
+ Object input = getInput();
+ if (input instanceof ICompilationUnit) {
+ ICompilationUnit cu = (ICompilationUnit) input;
+ cu = JavaModelUtil.toOriginal(cu);
+ return cu.getResource();
+ }
+ // else if (input instanceof IClassFile) {
+ // return ((IClassFile) input).getResource();
+ // }
+ return null;
+ }
+
+ }
+
+ class LexicalSortingAction extends Action {
+
+ private JavaElementSorter fSorter = new JavaElementSorter();
+
+ public LexicalSortingAction() {
+ super();
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.LEXICAL_SORTING_OUTLINE_ACTION);
+ setText(PHPEditorMessages.getString("JavaOutlinePage.Sort.label")); //$NON-NLS-1$
+ PHPUiImages.setLocalImageDescriptors(this, "alphab_sort_co.gif"); //$NON-NLS-1$
+ setToolTipText(PHPEditorMessages
+ .getString("JavaOutlinePage.Sort.tooltip")); //$NON-NLS-1$
+ setDescription(PHPEditorMessages
+ .getString("JavaOutlinePage.Sort.description")); //$NON-NLS-1$
+
+ boolean checked = WebUI.getDefault()
+ .getPreferenceStore().getBoolean(
+ "LexicalSortingAction.isChecked"); //$NON-NLS-1$
+ valueChanged(checked, false);
+ }
+
+ public void run() {
+ valueChanged(isChecked(), true);
+ }
+
+ private void valueChanged(final boolean on, boolean store) {
+ setChecked(on);
+ BusyIndicator.showWhile(fOutlineViewer.getControl().getDisplay(),
+ new Runnable() {
+ public void run() {
+ fOutlineViewer.setSorter(on ? fSorter : null);
+ }
+ });
+
+ if (store)
+ WebUI.getDefault().getPreferenceStore().setValue(
+ "LexicalSortingAction.isChecked", on); //$NON-NLS-1$
+ }
+ }
+
+ class ClassOnlyAction extends Action {
+
+ public ClassOnlyAction() {
+ super();
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.GO_INTO_TOP_LEVEL_TYPE_ACTION);
+ setText(PHPEditorMessages
+ .getString("JavaOutlinePage.GoIntoTopLevelType.label")); //$NON-NLS-1$
+ setToolTipText(PHPEditorMessages
+ .getString("JavaOutlinePage.GoIntoTopLevelType.tooltip")); //$NON-NLS-1$
+ setDescription(PHPEditorMessages
+ .getString("JavaOutlinePage.GoIntoTopLevelType.description")); //$NON-NLS-1$
+ PHPUiImages.setLocalImageDescriptors(this,
+ "gointo_toplevel_type.gif"); //$NON-NLS-1$
+
+ IPreferenceStore preferenceStore = WebUI.getDefault()
+ .getPreferenceStore();
+ boolean showclass = preferenceStore
+ .getBoolean("GoIntoTopLevelTypeAction.isChecked"); //$NON-NLS-1$
+ setTopLevelTypeOnly(showclass);
+ }
+
+ /*
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ setTopLevelTypeOnly(!fTopLevelTypeOnly);
+ }
+
+ private void setTopLevelTypeOnly(boolean show) {
+ fTopLevelTypeOnly = show;
+ setChecked(show);
+ fOutlineViewer.refresh(false);
+
+ IPreferenceStore preferenceStore = WebUI.getDefault()
+ .getPreferenceStore();
+ preferenceStore
+ .setValue("GoIntoTopLevelTypeAction.isChecked", show); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * This action toggles whether this Java Outline page links its selection to
+ * the active editor.
+ *
+ * @since 3.0
+ */
+ public class ToggleLinkingAction extends AbstractToggleLinkingAction {
+
+ JavaOutlinePage fJavaOutlinePage;
+
+ /**
+ * Constructs a new action.
+ *
+ * @param outlinePage
+ * the Java outline page
+ */
+ public ToggleLinkingAction(JavaOutlinePage outlinePage) {
+ boolean isLinkingEnabled = PreferenceConstants
+ .getPreferenceStore()
+ .getBoolean(
+ PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE);
+ setChecked(isLinkingEnabled);
+ fJavaOutlinePage = outlinePage;
+ }
+
+ /**
+ * Runs the action.
+ */
+ public void run() {
+ PreferenceConstants.getPreferenceStore().setValue(
+ PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE,
+ isChecked());
+ if (isChecked() && fEditor != null)
+ fEditor.synchronizeOutlinePage(fEditor
+ .computeHighlightRangeSourceReference(), false);
+ }
+
+ }
+
+ /** A flag to show contents of top level type only */
+ private boolean fTopLevelTypeOnly;
+
+ private IJavaElement fInput;
+
+ private String fContextMenuID;
+
+ private Menu fMenu;
+
+ private JavaOutlineViewer fOutlineViewer;
+
+ private PHPEditor fEditor;
+
+ private MemberFilterActionGroup fMemberFilterActionGroup;
+
+ private ListenerList fSelectionChangedListeners = new ListenerList();
+
+ private ListenerList fPostSelectionChangedListeners = new ListenerList();
+
+ private Hashtable fActions = new Hashtable();
+
+ private TogglePresentationAction fTogglePresentation;
+
+ private GotoAnnotationAction fPreviousAnnotation;
+
+ private GotoAnnotationAction fNextAnnotation;
+
+ private TextEditorAction fShowJavadoc;
+
+ private IAction fUndo;
+
+ private IAction fRedo;
+
+ private ToggleLinkingAction fToggleLinkingAction;
+
+ private CompositeActionGroup fActionGroups;
+
+ private IPropertyChangeListener fPropertyChangeListener;
+
+ /**
+ * Custom filter action group.
+ *
+ * @since 3.0
+ */
+ private CustomFiltersActionGroup fCustomFiltersActionGroup;
+
+ public JavaOutlinePage(String contextMenuID, PHPEditor editor) {
+ super();
+
+ Assert.isNotNull(editor);
+
+ fContextMenuID = contextMenuID;
+ fEditor = editor;
+ fTogglePresentation = new TogglePresentationAction();
+ ResourceBundle bundle = PHPEditorMessages.getResourceBundle();
+ fPreviousAnnotation = new GotoAnnotationAction(bundle,
+ "PreviousAnnotation.", null, false); //$NON-NLS-1$
+ fNextAnnotation = new GotoAnnotationAction(bundle,
+ "NextAnnotation.", null, true); //$NON-NLS-1$
+ fShowJavadoc = (TextEditorAction) fEditor.getAction("ShowJavaDoc"); //$NON-NLS-1$
+ fUndo = fEditor.getAction(ITextEditorActionConstants.UNDO);
+ fRedo = fEditor.getAction(ITextEditorActionConstants.REDO);
+
+ fTogglePresentation.setEditor(editor);
+ fPreviousAnnotation.setEditor(editor);
+ fNextAnnotation.setEditor(editor);
+
+ fPropertyChangeListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ doPropertyChange(event);
+ }
+ };
+ WebUI.getDefault().getPreferenceStore()
+ .addPropertyChangeListener(fPropertyChangeListener);
+ }
+
+ /**
+ * Returns the primary type of a compilation unit (has the same name as the
+ * compilation unit).
+ *
+ * @param compilationUnit
+ * the compilation unit
+ * @return returns the primary type of the compilation unit, or
+ * null
if is does not have one
+ */
+ protected IType getMainType(ICompilationUnit compilationUnit) {
+
+ if (compilationUnit == null)
+ return null;
+
+ String name = compilationUnit.getElementName();
+ int index = name.indexOf('.');
+ if (index != -1)
+ name = name.substring(0, index);
+ IType type = compilationUnit.getType(name);
+ return type.exists() ? type : null;
+ }
+
+ /**
+ * Returns the primary type of a class file.
+ *
+ * @param classFile
+ * the class file
+ * @return returns the primary type of the class file, or null
+ * if is does not have one
+ */
+ // protected IType getMainType(IClassFile classFile) {
+ // try {
+ // IType type= classFile.getType();
+ // return type != null && type.exists() ? type : null;
+ // } catch (JavaModelException e) {
+ // return null;
+ // }
+ // }
+ /*
+ * (non-Javadoc) Method declared on Page
+ */
+ public void init(IPageSite pageSite) {
+ super.init(pageSite);
+ }
+
+ private void doPropertyChange(PropertyChangeEvent event) {
+ if (fOutlineViewer != null) {
+ if (MembersOrderPreferenceCache.isMemberOrderProperty(event
+ .getProperty())) {
+ fOutlineViewer.refresh(false);
+ }
+ }
+ }
+
+ /*
+ * @see ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener)
+ */
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ if (fOutlineViewer != null)
+ fOutlineViewer.addSelectionChangedListener(listener);
+ else
+ fSelectionChangedListeners.add(listener);
+ }
+
+ /*
+ * @see ISelectionProvider#removeSelectionChangedListener(ISelectionChangedListener)
+ */
+ public void removeSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ if (fOutlineViewer != null)
+ fOutlineViewer.removeSelectionChangedListener(listener);
+ else
+ fSelectionChangedListeners.remove(listener);
+ }
+
+ /*
+ * @see ISelectionProvider#setSelection(ISelection)
+ */
+ public void setSelection(ISelection selection) {
+ if (fOutlineViewer != null)
+ fOutlineViewer.setSelection(selection);
+ }
+
+ /*
+ * @see ISelectionProvider#getSelection()
+ */
+ public ISelection getSelection() {
+ if (fOutlineViewer == null)
+ return StructuredSelection.EMPTY;
+ return fOutlineViewer.getSelection();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IPostSelectionProvider#addPostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+ */
+ public void addPostSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ if (fOutlineViewer != null)
+ fOutlineViewer.addPostSelectionChangedListener(listener);
+ else
+ fPostSelectionChangedListeners.add(listener);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IPostSelectionProvider#removePostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+ */
+ public void removePostSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ if (fOutlineViewer != null)
+ fOutlineViewer.removePostSelectionChangedListener(listener);
+ else
+ fPostSelectionChangedListeners.remove(listener);
+ }
+
+ private void registerToolbarActions(IActionBars actionBars) {
+
+ IToolBarManager toolBarManager = actionBars.getToolBarManager();
+ if (toolBarManager != null) {
+ toolBarManager.add(new LexicalSortingAction());
+
+ fMemberFilterActionGroup = new MemberFilterActionGroup(
+ fOutlineViewer,
+ "net.sourceforge.phpeclipse.JavaOutlinePage"); //$NON-NLS-1$
+ fMemberFilterActionGroup.contributeToToolBar(toolBarManager);
+
+ fCustomFiltersActionGroup.fillActionBars(actionBars);
+
+ IMenuManager menu = actionBars.getMenuManager();
+ menu.add(new Separator("EndFilterGroup")); //$NON-NLS-1$
+
+ fToggleLinkingAction = new ToggleLinkingAction(this);
+ menu.add(new ClassOnlyAction());
+ menu.add(fToggleLinkingAction);
+ }
+ }
+
+ /*
+ * @see IPage#createControl
+ */
+ public void createControl(Composite parent) {
+
+ Tree tree = new Tree(parent, SWT.MULTI);
+
+ AppearanceAwareLabelProvider lprovider = new AppearanceAwareLabelProvider(
+ AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS
+ | JavaElementLabels.F_APP_TYPE_SIGNATURE,
+ AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS);
+
+ fOutlineViewer = new JavaOutlineViewer(tree);
+ initDragAndDrop();
+ fOutlineViewer.setContentProvider(new ChildrenProvider());
+ fOutlineViewer.setLabelProvider(new DecoratingJavaLabelProvider(
+ lprovider));
+
+ Object[] listeners = fSelectionChangedListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ fSelectionChangedListeners.remove(listeners[i]);
+ fOutlineViewer
+ .addSelectionChangedListener((ISelectionChangedListener) listeners[i]);
+ }
+
+ listeners = fPostSelectionChangedListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ fPostSelectionChangedListeners.remove(listeners[i]);
+ fOutlineViewer
+ .addPostSelectionChangedListener((ISelectionChangedListener) listeners[i]);
+ }
+
+ MenuManager manager = new MenuManager(fContextMenuID, fContextMenuID);
+ manager.setRemoveAllWhenShown(true);
+ manager.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager m) {
+ contextMenuAboutToShow(m);
+ }
+ });
+ fMenu = manager.createContextMenu(tree);
+ tree.setMenu(fMenu);
+
+ IPageSite site = getSite();
+ site
+ .registerContextMenu(PHPeclipsePlugin.getPluginId()
+ + ".outline", manager, fOutlineViewer); //$NON-NLS-1$
+ site.setSelectionProvider(fOutlineViewer);
+
+ // we must create the groups after we have set the selection provider to
+ // the site
+ fActionGroups = new CompositeActionGroup(new ActionGroup[] {
+ // new OpenViewActionGroup(this),
+ // new CCPActionGroup(this),
+ new GenerateActionGroup(this) });
+ // new RefactorActionGroup(this),
+ // new JavaSearchActionGroup(this)});
+
+ // register global actions
+ IActionBars bars = site.getActionBars();
+
+ bars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, fUndo);
+ bars.setGlobalActionHandler(ITextEditorActionConstants.REDO, fRedo);
+ bars.setGlobalActionHandler(ActionFactory.PREVIOUS.getId(),
+ fPreviousAnnotation);
+ bars
+ .setGlobalActionHandler(ActionFactory.NEXT.getId(),
+ fNextAnnotation);
+ bars.setGlobalActionHandler(PHPdtActionConstants.SHOW_JAVA_DOC,
+ fShowJavadoc);
+ bars
+ .setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.TOGGLE_SHOW_SELECTED_ELEMENT_ONLY,
+ fTogglePresentation);
+ bars.setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.GOTO_NEXT_ANNOTATION,
+ fNextAnnotation);
+ bars.setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.GOTO_PREVIOUS_ANNOTATION,
+ fPreviousAnnotation);
+
+ fActionGroups.fillActionBars(bars);
+
+ IStatusLineManager statusLineManager = bars.getStatusLineManager();
+ if (statusLineManager != null) {
+ StatusBarUpdater updater = new StatusBarUpdater(statusLineManager);
+ fOutlineViewer.addPostSelectionChangedListener(updater);
+ }
+ // Custom filter group
+ fCustomFiltersActionGroup = new CustomFiltersActionGroup(
+ "net.sourceforge.phpdt.ui.JavaOutlinePage", fOutlineViewer); //$NON-NLS-1$
+
+ registerToolbarActions(bars);
+
+ fOutlineViewer.setInput(fInput);
+ }
+
+ public void dispose() {
+
+ if (fEditor == null)
+ return;
+
+ if (fMemberFilterActionGroup != null) {
+ fMemberFilterActionGroup.dispose();
+ fMemberFilterActionGroup = null;
+ }
+
+ if (fCustomFiltersActionGroup != null) {
+ fCustomFiltersActionGroup.dispose();
+ fCustomFiltersActionGroup = null;
+ }
+
+ fEditor.outlinePageClosed();
+ fEditor = null;
+
+ fSelectionChangedListeners.clear();
+ fSelectionChangedListeners = null;
+
+ fPostSelectionChangedListeners.clear();
+ fPostSelectionChangedListeners = null;
+
+ if (fPropertyChangeListener != null) {
+ WebUI.getDefault().getPreferenceStore()
+ .removePropertyChangeListener(fPropertyChangeListener);
+ fPropertyChangeListener = null;
+ }
+
+ if (fMenu != null && !fMenu.isDisposed()) {
+ fMenu.dispose();
+ fMenu = null;
+ }
+
+ if (fActionGroups != null)
+ fActionGroups.dispose();
+
+ fTogglePresentation.setEditor(null);
+ fPreviousAnnotation.setEditor(null);
+ fNextAnnotation.setEditor(null);
+
+ fOutlineViewer = null;
+
+ super.dispose();
+ }
+
+ public Control getControl() {
+ if (fOutlineViewer != null)
+ return fOutlineViewer.getControl();
+ return null;
+ }
+
+ public void setInput(IJavaElement inputElement) {
+ fInput = inputElement;
+ if (fOutlineViewer != null)
+ fOutlineViewer.setInput(fInput);
+ }
+
+ public void select(ISourceReference reference) {
+ if (fOutlineViewer != null) {
+
+ ISelection s = fOutlineViewer.getSelection();
+ if (s instanceof IStructuredSelection) {
+ IStructuredSelection ss = (IStructuredSelection) s;
+ List elements = ss.toList();
+ if (!elements.contains(reference)) {
+ s = (reference == null ? StructuredSelection.EMPTY
+ : new StructuredSelection(reference));
+ fOutlineViewer.setSelection(s, true);
+ }
+ }
+ }
+ }
+
+ public void setAction(String actionID, IAction action) {
+ Assert.isNotNull(actionID);
+ if (action == null)
+ fActions.remove(actionID);
+ else
+ fActions.put(actionID, action);
+ }
+
+ public IAction getAction(String actionID) {
+ Assert.isNotNull(actionID);
+ return (IAction) fActions.get(actionID);
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class key) {
+ if (key == IShowInSource.class) {
+ return getShowInSource();
+ }
+ if (key == IShowInTargetList.class) {
+ return new IShowInTargetList() {
+ public String[] getShowInTargetIds() {
+ return new String[] { JavaUI.ID_PACKAGES };
+ }
+
+ };
+ }
+ if (key == IShowInTarget.class) {
+ return getShowInTarget();
+ }
+
+ return null;
+ }
+
+ /**
+ * Convenience method to add the action installed under the given actionID
+ * to the specified group of the menu.
+ *
+ * @param menu
+ * the menu manager
+ * @param group
+ * the group to which to add the action
+ * @param actionID
+ * the ID of the new action
+ */
+ protected void addAction(IMenuManager menu, String group, String actionID) {
+ IAction action = getAction(actionID);
+ if (action != null) {
+ if (action instanceof IUpdate)
+ ((IUpdate) action).update();
+
+ if (action.isEnabled()) {
+ IMenuManager subMenu = menu.findMenuUsingPath(group);
+ if (subMenu != null)
+ subMenu.add(action);
+ else
+ menu.appendToGroup(group, action);
+ }
+ }
+ }
+
+ protected void contextMenuAboutToShow(IMenuManager menu) {
+
+ WebUI.createStandardGroups(menu);
+
+ IStructuredSelection selection = (IStructuredSelection) getSelection();
+ fActionGroups.setContext(new ActionContext(selection));
+ fActionGroups.fillContextMenu(menu);
+ }
+
+ /*
+ * @see Page#setFocus()
+ */
+ public void setFocus() {
+ if (fOutlineViewer != null)
+ fOutlineViewer.getControl().setFocus();
+ }
+
+ /**
+ * Checks whether a given Java element is an inner type.
+ *
+ * @param element
+ * the java element
+ * @return true
iff the given element is an inner type
+ */
+ private boolean isInnerType(IJavaElement element) {
+
+ if (element != null && element.getElementType() == IJavaElement.TYPE) {
+ IType type = (IType) element;
+ try {
+ return type.isMember();
+ } catch (JavaModelException e) {
+ IJavaElement parent = type.getParent();
+ if (parent != null) {
+ int parentElementType = parent.getElementType();
+ return (parentElementType != IJavaElement.COMPILATION_UNIT && parentElementType != IJavaElement.CLASS_FILE);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the IShowInSource
for this view.
+ *
+ * @return the {@link IShowInSource}
+ */
+ protected IShowInSource getShowInSource() {
+ return new IShowInSource() {
+ public ShowInContext getShowInContext() {
+ return new ShowInContext(null, getSite().getSelectionProvider()
+ .getSelection());
+ }
+ };
+ }
+
+ /**
+ * Returns the IShowInTarget
for this view.
+ *
+ * @return the {@link IShowInTarget}
+ */
+ protected IShowInTarget getShowInTarget() {
+ return new IShowInTarget() {
+ public boolean show(ShowInContext context) {
+ ISelection sel = context.getSelection();
+ if (sel instanceof ITextSelection) {
+ ITextSelection tsel = (ITextSelection) sel;
+ int offset = tsel.getOffset();
+ IJavaElement element = fEditor.getElementAt(offset);
+ if (element != null) {
+ setSelection(new StructuredSelection(element));
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ }
+
+ private void initDragAndDrop() {
+ int ops = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
+ Transfer[] transfers = new Transfer[] { LocalSelectionTransfer
+ .getInstance() };
+
+ // Drop Adapter
+ // TransferDropTargetListener[] dropListeners= new
+ // TransferDropTargetListener[] {
+ // new SelectionTransferDropAdapter(fOutlineViewer)
+ // };
+ // fOutlineViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new
+ // DelegatingDropAdapter(dropListeners));
+
+ // Drag Adapter
+ // TransferDragSourceListener[] dragListeners= new
+ // TransferDragSourceListener[] {
+ // new SelectionTransferDragAdapter(fOutlineViewer)
+ // };
+ // fOutlineViewer.addDragSupport(ops, transfers, new
+ // JdtViewerDragAdapter(fOutlineViewer, dragListeners));
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectMarkerRulerAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectMarkerRulerAction.java
new file mode 100644
index 0000000..e265b54
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectMarkerRulerAction.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.Iterator;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension;
+import org.eclipse.ui.texteditor.SelectMarkerRulerAction;
+
+/**
+ * A special select marker ruler action which activates quick fix if clicked on
+ * a quick fixable problem.
+ */
+public class JavaSelectMarkerRulerAction extends SelectMarkerRulerAction {
+
+ private ITextEditor fTextEditor;
+
+ private Position fPosition;
+
+ public JavaSelectMarkerRulerAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor, IVerticalRulerInfo ruler) {
+ super(bundle, prefix, editor, ruler);
+ fTextEditor = editor;
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.JAVA_SELECT_MARKER_RULER_ACTION);
+ }
+
+ public void run() {
+ // if
+ // (PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
+ // return;
+
+ if (fPosition != null) {
+ ITextOperationTarget operation = (ITextOperationTarget) fTextEditor
+ .getAdapter(ITextOperationTarget.class);
+ // final int opCode= PHPUnitEditor.CORRECTIONASSIST_PROPOSALS;
+ // if (operation != null && operation.canDoOperation(opCode)) {
+ // fTextEditor.selectAndReveal(fPosition.getOffset(),
+ // fPosition.getLength());
+ // operation.doOperation(opCode);
+ // return;
+ // }
+ return;
+ }
+ super.run();
+ }
+
+ public void update() {
+ // Begin Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20114
+ if (!(fTextEditor instanceof ITextEditorExtension)
+ || ((ITextEditorExtension) fTextEditor).isEditorInputReadOnly()) {
+ fPosition = null;
+ super.update();
+ return;
+ }
+ // End Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20114
+ fPosition = getJavaAnnotationPosition();
+ if (fPosition != null)
+ setEnabled(true);
+ else
+ super.update();
+ }
+
+ private Position getJavaAnnotationPosition() {
+ AbstractMarkerAnnotationModel model = getAnnotationModel();
+ IDocument document = getDocument();
+ if (model == null)
+ return null;
+ ICompilationUnit cu = getCompilationUnit();
+ if (cu == null) {
+ return null;
+ }
+
+ // boolean hasAssistLightbulb=
+ // PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.APPEARANCE_QUICKASSIST_LIGHTBULB);
+ Annotation assistAnnotation = null;
+
+ Iterator iter = model.getAnnotationIterator();
+ while (iter.hasNext()) {
+ Annotation annotation = (Annotation) iter.next();
+ if (annotation instanceof IJavaAnnotation) {
+ IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
+ if (!javaAnnotation.isMarkedDeleted()) {
+ Position position = model.getPosition(annotation);
+ // if (includesRulerLine(position, document) &&
+ // JavaCorrectionProcessor.hasCorrections(javaAnnotation))
+ // return position;
+ }
+ }
+ // else if (hasAssistLightbulb && annotation instanceof
+ // AssistAnnotation) {
+ // // there is only one AssistAnnotation at a time
+ // assistAnnotation= annotation;
+ // }
+ }
+ if (assistAnnotation != null) {
+ Position position = model.getPosition(assistAnnotation);
+ // no need to check 'JavaCorrectionProcessor.hasAssists': annotation
+ // only created when
+ // there are assists
+ if (includesRulerLine(position, document))
+ return position;
+ }
+ return null;
+ }
+
+ private ICompilationUnit getCompilationUnit() {
+ IEditorInput input = fTextEditor.getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput) input).getFile();
+ IJavaElement element = JavaCore.create(file);
+ if (element instanceof ICompilationUnit)
+ return (ICompilationUnit) element;
+ }
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectMarkerRulerAction2.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectMarkerRulerAction2.java
new file mode 100644
index 0000000..5b3abd8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectMarkerRulerAction2.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.VerticalRulerEvent;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.ui.texteditor.SelectAnnotationRulerAction;
+
+// import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
+// import
+// net.sourceforge.phpdt.internal.ui.text.correction.JavaCorrectionProcessor;
+// import
+// net.sourceforge.phpdt.internal.ui.text.correction.QuickAssistLightBulbUpdater.AssistAnnotation;
+// import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaExpandHover;
+
+/**
+ * A special select marker ruler action which activates quick fix if clicked on
+ * a quick fixable problem.
+ */
+public class JavaSelectMarkerRulerAction2 extends SelectAnnotationRulerAction {
+
+ public JavaSelectMarkerRulerAction2(ResourceBundle bundle, String prefix,
+ ITextEditor editor) {
+ super(bundle, prefix, editor);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
+ IJavaHelpContextIds.JAVA_SELECT_MARKER_RULER_ACTION);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IVerticalRulerListener#annotationDefaultSelected(org.eclipse.ui.texteditor.VerticalRulerEvent)
+ */
+ public void annotationDefaultSelected(VerticalRulerEvent event) {
+ Annotation annotation = event.getSelectedAnnotation();
+ IAnnotationModel model = getAnnotationModel();
+
+ // if (isOverrideIndicator(annotation)) {
+ // ((OverrideIndicatorManager.OverrideIndicator)annotation).open();
+ // return;
+ // }
+
+ if (isBreakpoint(annotation))
+ triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
+
+ Position position = model.getPosition(annotation);
+ if (position == null)
+ return;
+
+ // if (isQuickFixTarget(annotation)) {
+ // ITextOperationTarget operation= (ITextOperationTarget)
+ // getTextEditor().getAdapter(ITextOperationTarget.class);
+ // final int opCode= PHPUnitEditor.CORRECTIONASSIST_PROPOSALS;
+ // if (operation != null && operation.canDoOperation(opCode)) {
+ // getTextEditor().selectAndReveal(position.getOffset(),
+ // position.getLength());
+ // operation.doOperation(opCode);
+ // return;
+ // }
+ // }
+
+ // default:
+ super.annotationDefaultSelected(event);
+ }
+
+ /**
+ * Tells whether the given annotation is an override annotation.
+ *
+ * @param annotation
+ * the annotation
+ * @return true
iff the annotation is an override annotation
+ */
+ private boolean isOverrideIndicator(Annotation annotation) {
+ return false; // annotation instanceof
+ // OverrideIndicatorManager.OverrideIndicator;
+ }
+
+ /**
+ * @param annotation
+ * @return
+ */
+ private boolean isBreakpoint(Annotation annotation) {
+ return annotation.getType().equals("org.eclipse.debug.core.breakpoint");
+ // ||
+ // annotation.getType().equals(JavaExpandHover.NO_BREAKPOINT_ANNOTATION);
+ // //$NON-NLS-1$
+
+ }
+
+ private boolean isQuickFixTarget(Annotation a) {
+ return false; // JavaCorrectionProcessor.hasCorrections(a) || a
+ // instanceof AssistAnnotation;
+ }
+
+ private void triggerAction(String actionID) {
+ IAction action = getTextEditor().getAction(actionID);
+ if (action != null) {
+ if (action instanceof IUpdate)
+ ((IUpdate) action).update();
+ // hack to propagate line change
+ if (action instanceof ISelectionListener) {
+ ((ISelectionListener) action).selectionChanged(null, null);
+ }
+ if (action.isEnabled())
+ action.run();
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectRulerAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectRulerAction.java
new file mode 100644
index 0000000..586ff2e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSelectRulerAction.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+public class JavaSelectRulerAction extends AbstractRulerActionDelegate {
+
+ /*
+ * @see AbstractRulerActionDelegate#createAction(ITextEditor,
+ * IVerticalRulerInfo)
+ */
+ protected IAction createAction(ITextEditor editor,
+ IVerticalRulerInfo rulerInfo) {
+ return new JavaSelectMarkerRulerAction(PHPEditorMessages
+ .getResourceBundle(),
+ "JavaSelectMarkerRulerAction.", editor, rulerInfo); //$NON-NLS-1$
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSourceViewer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSourceViewer.java
new file mode 100644
index 0000000..124ee59
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaSourceViewer.java
@@ -0,0 +1,471 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.internal.ui.text.SmartBackspaceManager;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.ITextPresentationListener;
+import org.eclipse.jface.text.information.IInformationPresenter;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.source.IOverviewRuler;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+
+public class JavaSourceViewer extends ProjectionViewer implements
+ IPropertyChangeListener {
+
+ /**
+ * Text operation code for requesting the outline for the current input.
+ */
+ public static final int SHOW_OUTLINE = 51;
+
+ /**
+ * Text operation code for requesting the outline for the element at the
+ * current position.
+ */
+ public static final int OPEN_STRUCTURE = 52;
+
+ /**
+ * Text operation code for requesting the hierarchy for the current input.
+ */
+ public static final int SHOW_HIERARCHY = 53;
+
+ private IInformationPresenter fOutlinePresenter;
+
+ private IInformationPresenter fStructurePresenter;
+
+ // private IInformationPresenter fHierarchyPresenter;
+
+ /**
+ * This viewer's foreground color.
+ *
+ * @since 3.0
+ */
+ private Color fForegroundColor;
+
+ /**
+ * The viewer's background color.
+ *
+ * @since 3.0
+ */
+ private Color fBackgroundColor;
+
+ /**
+ * This viewer's selection foreground color.
+ *
+ * @since 3.0
+ */
+ private Color fSelectionForegroundColor;
+
+ /**
+ * The viewer's selection background color.
+ *
+ * @since 3.0
+ */
+ private Color fSelectionBackgroundColor;
+
+ /**
+ * The preference store.
+ *
+ * @since 3.0
+ */
+ private IPreferenceStore fPreferenceStore;
+
+ /**
+ * Is this source viewer configured?
+ *
+ * @since 3.0
+ */
+ private boolean fIsConfigured;
+
+ /**
+ * The backspace manager of this viewer.
+ *
+ * @since 3.0
+ */
+ private SmartBackspaceManager fBackspaceManager;
+
+ public JavaSourceViewer(Composite parent, IVerticalRuler verticalRuler,
+ IOverviewRuler overviewRuler, boolean showAnnotationsOverview,
+ int styles, IPreferenceStore store) {
+ super(parent, verticalRuler, overviewRuler, showAnnotationsOverview,
+ styles);
+ setPreferenceStore(store);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewer#createFormattingContext()
+ * @since 3.0
+ */
+ // public IFormattingContext createFormattingContext() {
+ //
+ // IFormattingContext context= new CommentFormattingContext();
+ // Map map= new Hashtable(JavaCore.getOptions());
+ //
+ // context.storeToMap(PreferenceConstants.getPreferenceStore(), map, false);
+ // context.setProperty(FormattingContextProperties.CONTEXT_PREFERENCES,
+ // map);
+ //
+ // return context;
+ // }
+ /*
+ * @see ITextOperationTarget#doOperation(int)
+ */
+ public void doOperation(int operation) {
+ if (getTextWidget() == null)
+ return;
+
+ switch (operation) {
+ case SHOW_OUTLINE:
+ fOutlinePresenter.showInformation();
+ return;
+ case OPEN_STRUCTURE:
+ fStructurePresenter.showInformation();
+ return;
+ case SHOW_HIERARCHY:
+ // fHierarchyPresenter.showInformation();
+ return;
+ case FORMAT:
+ Point point = getSelectedRange();
+ if (point.y == 0) {
+ // setSelectedRange(0, getDocument().getLength());
+ revealRange(0, getDocument().getLength());
+ }
+ break;
+ }
+
+ super.doOperation(operation);
+ }
+
+ /*
+ * @see ITextOperationTarget#canDoOperation(int)
+ */
+ public boolean canDoOperation(int operation) {
+ if (operation == SHOW_OUTLINE)
+ return fOutlinePresenter != null;
+ if (operation == OPEN_STRUCTURE)
+ return fStructurePresenter != null;
+ if (operation == SHOW_HIERARCHY)
+ // return fHierarchyPresenter != null;
+ return false;
+
+ return super.canDoOperation(operation);
+ }
+
+ /*
+ * @see ISourceViewer#configure(SourceViewerConfiguration)
+ */
+ public void configure(SourceViewerConfiguration configuration) {
+ super.configure(configuration);
+ if (configuration instanceof PHPSourceViewerConfiguration) {
+ fOutlinePresenter = ((PHPSourceViewerConfiguration) configuration)
+ .getOutlinePresenter(this, false);
+ fOutlinePresenter.install(this);
+ }
+ if (configuration instanceof PHPSourceViewerConfiguration) {
+ fStructurePresenter = ((PHPSourceViewerConfiguration) configuration)
+ .getOutlinePresenter(this, true);
+ fStructurePresenter.install(this);
+ }
+ if (configuration instanceof PHPSourceViewerConfiguration) {
+ // fHierarchyPresenter=
+ // ((PHPSourceViewerConfiguration)configuration).getHierarchyPresenter(this,
+ // true);
+ // fHierarchyPresenter.install(this);
+
+ if (fPreferenceStore != null) {
+ fPreferenceStore.addPropertyChangeListener(this);
+ initializeViewerColors();
+ }
+ }
+ fIsConfigured = true;
+ }
+
+ protected void initializeViewerColors() {
+ if (fPreferenceStore != null) {
+
+ StyledText styledText = getTextWidget();
+
+ // ----------- foreground color --------------------
+ Color color = fPreferenceStore
+ .getBoolean(PreferenceConstants.EDITOR_FOREGROUND_DEFAULT_COLOR) ? null
+ : createColor(fPreferenceStore,
+ PreferenceConstants.EDITOR_FOREGROUND_COLOR,
+ styledText.getDisplay());
+ styledText.setForeground(color);
+
+ if (fForegroundColor != null)
+ fForegroundColor.dispose();
+
+ fForegroundColor = color;
+
+ // ---------- background color ----------------------
+ color = fPreferenceStore
+ .getBoolean(PreferenceConstants.EDITOR_BACKGROUND_DEFAULT_COLOR) ? null
+ : createColor(fPreferenceStore,
+ PreferenceConstants.EDITOR_BACKGROUND_COLOR,
+ styledText.getDisplay());
+ styledText.setBackground(color);
+
+ if (fBackgroundColor != null)
+ fBackgroundColor.dispose();
+
+ fBackgroundColor = color;
+
+ // ----------- selection foreground color --------------------
+ color = fPreferenceStore
+ .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_FOREGROUND_DEFAULT_COLOR) ? null
+ : createColor(
+ fPreferenceStore,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_FOREGROUND_COLOR,
+ styledText.getDisplay());
+ styledText.setSelectionForeground(color);
+
+ if (fSelectionForegroundColor != null)
+ fSelectionForegroundColor.dispose();
+
+ fSelectionForegroundColor = color;
+
+ // ---------- selection background color ----------------------
+ color = fPreferenceStore
+ .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_BACKGROUND_DEFAULT_COLOR) ? null
+ : createColor(
+ fPreferenceStore,
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_BACKGROUND_COLOR,
+ styledText.getDisplay());
+ styledText.setSelectionBackground(color);
+
+ if (fSelectionBackgroundColor != null)
+ fSelectionBackgroundColor.dispose();
+
+ fSelectionBackgroundColor = color;
+ }
+ }
+
+ /**
+ * Creates a color from the information stored in the given preference
+ * store. Returns null
if there is no such information
+ * available.
+ *
+ * @param store
+ * the store to read from
+ * @param key
+ * the key used for the lookup in the preference store
+ * @param display
+ * the display used create the color
+ * @return the created color according to the specification in the
+ * preference store
+ * @since 3.0
+ */
+ private Color createColor(IPreferenceStore store, String key,
+ Display display) {
+
+ RGB rgb = null;
+
+ if (store.contains(key)) {
+
+ if (store.isDefault(key))
+ rgb = PreferenceConverter.getDefaultColor(store, key);
+ else
+ rgb = PreferenceConverter.getColor(store, key);
+
+ if (rgb != null)
+ return new Color(display, rgb);
+ }
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.ISourceViewerExtension2#unconfigure()
+ * @since 3.0
+ */
+ public void unconfigure() {
+ if (fOutlinePresenter != null) {
+ fOutlinePresenter.uninstall();
+ fOutlinePresenter = null;
+ }
+ if (fStructurePresenter != null) {
+ fStructurePresenter.uninstall();
+ fStructurePresenter = null;
+ }
+ // if (fHierarchyPresenter != null) {
+ // fHierarchyPresenter.uninstall();
+ // fHierarchyPresenter= null;
+ // }
+ if (fForegroundColor != null) {
+ fForegroundColor.dispose();
+ fForegroundColor = null;
+ }
+ if (fBackgroundColor != null) {
+ fBackgroundColor.dispose();
+ fBackgroundColor = null;
+ }
+ if (fPreferenceStore != null)
+ fPreferenceStore.removePropertyChangeListener(this);
+
+ super.unconfigure();
+
+ fIsConfigured = false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewer#rememberSelection()
+ */
+ public Point rememberSelection() {
+ return super.rememberSelection();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewer#restoreSelection()
+ */
+ public void restoreSelection() {
+ super.restoreSelection();
+ }
+
+ /*
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (PreferenceConstants.EDITOR_FOREGROUND_COLOR.equals(property)
+ || PreferenceConstants.EDITOR_FOREGROUND_DEFAULT_COLOR
+ .equals(property)
+ || PreferenceConstants.EDITOR_BACKGROUND_COLOR.equals(property)
+ || PreferenceConstants.EDITOR_BACKGROUND_DEFAULT_COLOR
+ .equals(property)
+ || AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_FOREGROUND_COLOR
+ .equals(property)
+ || AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_FOREGROUND_DEFAULT_COLOR
+ .equals(property)
+ || AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_BACKGROUND_COLOR
+ .equals(property)
+ || AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_BACKGROUND_DEFAULT_COLOR
+ .equals(property)) {
+ initializeViewerColors();
+ }
+ }
+
+ /**
+ * Sets the preference store on this viewer.
+ *
+ * @param store
+ * the preference store
+ *
+ * @since 3.0
+ */
+ public void setPreferenceStore(IPreferenceStore store) {
+ if (fIsConfigured && fPreferenceStore != null)
+ fPreferenceStore.removePropertyChangeListener(this);
+
+ fPreferenceStore = store;
+
+ if (fIsConfigured && fPreferenceStore != null) {
+ fPreferenceStore.addPropertyChangeListener(this);
+ initializeViewerColors();
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewer#createControl(org.eclipse.swt.widgets.Composite,
+ * int)
+ */
+ protected void createControl(Composite parent, int styles) {
+ super.createControl(parent, styles);
+
+ fBackspaceManager = new SmartBackspaceManager();
+ fBackspaceManager.install(this);
+ }
+
+ /**
+ * Returns the backspace manager for this viewer.
+ *
+ * @return the backspace manager for this viewer, or null
if
+ * there is none
+ * @since 3.0
+ */
+ public SmartBackspaceManager getBackspaceManager() {
+ return fBackspaceManager;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewer#handleDispose()
+ */
+ protected void handleDispose() {
+ if (fBackspaceManager != null) {
+ fBackspaceManager.uninstall();
+ fBackspaceManager = null;
+ }
+
+ super.handleDispose();
+ }
+
+ /**
+ * Prepends the text presentation listener at the beginning of the viewer's
+ * list of text presentation listeners. If the listener is already
+ * registered with the viewer this call moves the listener to the beginning
+ * of the list.
+ *
+ * @param listener
+ * the text presentation listener
+ * @since 3.0
+ */
+ public void prependTextPresentationListener(
+ ITextPresentationListener listener) {
+
+ Assert.isNotNull(listener);
+
+ if (fTextPresentationListeners == null)
+ fTextPresentationListeners = new ArrayList();
+
+ fTextPresentationListeners.remove(listener);
+ fTextPresentationListeners.add(0, listener);
+ }
+
+ /**
+ * Sets the given reconciler.
+ *
+ * @param reconciler
+ * the reconciler
+ * @since 3.0
+ */
+ void setReconciler(IReconciler reconciler) {
+ fReconciler = reconciler;
+ }
+
+ /**
+ * Returns the reconciler.
+ *
+ * @return the reconciler or null
if not set
+ * @since 3.0
+ */
+ Object getReconciler() {
+ return fReconciler;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaStorageDocumentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaStorageDocumentProvider.java
new file mode 100644
index 0000000..350afb8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/JavaStorageDocumentProvider.java
@@ -0,0 +1,47 @@
+/**********************************************************************
+ Copyright (c) 2000, 2003 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.editors.text.StorageDocumentProvider;
+
+/**
+ * @since 3.0
+ */
+public class JavaStorageDocumentProvider extends StorageDocumentProvider {
+
+ public JavaStorageDocumentProvider() {
+ super();
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.StorageDocumentProvider#setupDocument(java.lang.Object,
+ * org.eclipse.jface.text.IDocument)
+ */
+ protected void setupDocument(Object element, IDocument document) {
+
+ if (document != null) {
+ JavaTextTools tools = WebUI.getDefault()
+ .getJavaTextTools();
+ tools.setupJavaDocumentPartitioner(document,
+ IPHPPartitions.PHP_PARTITIONING);
+
+ // tools.setupJavaDocumentPartitioner(document,
+ // IDocument.DEFAULT_CONTENT_TYPE, element); //IPHPPartitions.HTML,
+ // element);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/LinePainter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/LinePainter.java
new file mode 100644
index 0000000..b0f7533
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/LinePainter.java
@@ -0,0 +1,187 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.custom.LineBackgroundEvent;
+import org.eclipse.swt.custom.LineBackgroundListener;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+
+public class LinePainter implements IPainter, LineBackgroundListener {
+
+ private final ISourceViewer fViewer;
+
+ private Color fHighlightColor;
+
+ private IPositionManager fPositionManager;
+
+ // positions to keep track of beginning and end of line to be painted or
+ // cleared
+ private Position fCurrentLine = new Position(0, 0);
+
+ private Position fLastLine = new Position(0, 0);
+
+ // used to keep track of the last line painted
+ private int fLastLineNumber = -1;
+
+ private boolean fIsActive;
+
+ public LinePainter(ISourceViewer sourceViewer) {
+ fViewer = sourceViewer;
+ }
+
+ public void setHighlightColor(Color highlightColor) {
+ fHighlightColor = highlightColor;
+ }
+
+ /*
+ * @see LineBackgroundListener#lineGetBackground(LineBackgroundEvent)
+ */
+ public void lineGetBackground(LineBackgroundEvent event) {
+ // don't use cached line information because of asynch painting
+
+ StyledText textWidget = fViewer.getTextWidget();
+ if (textWidget != null) {
+
+ int caret = textWidget.getCaretOffset();
+ int length = event.lineText.length();
+
+ if (event.lineOffset <= caret && caret <= event.lineOffset + length)
+ event.lineBackground = fHighlightColor;
+ else
+ event.lineBackground = textWidget.getBackground();
+ }
+ }
+
+ private boolean updateHighlightLine() {
+ try {
+
+ IDocument document = fViewer.getDocument();
+
+ int offset = fViewer.getTextWidget().getCaretOffset()
+ + fViewer.getVisibleRegion().getOffset();
+ int lineNumber = document.getLineOfOffset(offset);
+
+ // redraw if the current line number is different from the last line
+ // number we painted
+ // initially fLastLineNumber is -1
+ if (lineNumber != fLastLineNumber) {
+
+ fLastLine.offset = fCurrentLine.offset;
+ fLastLine.length = fCurrentLine.length;
+ fLastLine.isDeleted = fCurrentLine.isDeleted;
+
+ fCurrentLine.isDeleted = false;
+ fCurrentLine.offset = document.getLineOffset(lineNumber);
+ if (lineNumber == document.getNumberOfLines() - 1)
+ fCurrentLine.length = document.getLength()
+ - fCurrentLine.offset;
+ else
+ fCurrentLine.length = document
+ .getLineOffset(lineNumber + 1)
+ - fCurrentLine.offset;
+
+ fLastLineNumber = lineNumber;
+ return true;
+
+ }
+
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+
+ private void drawHighlightLine(Position position, int visibleOffset) {
+ StyledText textWidget = fViewer.getTextWidget();
+
+ // if the position that is about to be drawn was deleted then we can't
+ if (position.isDeleted())
+ return;
+
+ int delta = position.offset - visibleOffset;
+ if (0 <= delta && delta <= fViewer.getVisibleRegion().getLength()) {
+ Point upperLeft = textWidget.getLocationAtOffset(delta);
+ int width = textWidget.getClientArea().width
+ + textWidget.getHorizontalPixel();
+ int height = textWidget.getLineHeight();
+ textWidget.redraw(upperLeft.x, upperLeft.y, width, height, false);
+ }
+ }
+
+ /*
+ * @see IPainter#deactivate(boolean)
+ */
+ public void deactivate(boolean redraw) {
+ if (fIsActive) {
+ fIsActive = false;
+
+ /*
+ * on turning off the feature one has to paint the currently
+ * highlighted line with the standard background color
+ */
+ if (redraw)
+ drawHighlightLine(fCurrentLine, fViewer.getVisibleRegion()
+ .getOffset());
+
+ fViewer.getTextWidget().removeLineBackgroundListener(this);
+
+ if (fPositionManager != null)
+ fPositionManager.removeManagedPosition(fCurrentLine);
+
+ fLastLineNumber = -1;
+ }
+ }
+
+ /*
+ * @see IPainter#dispose()
+ */
+ public void dispose() {
+ }
+
+ /*
+ * @see IPainter#paint(int)
+ */
+ public void paint(int reason) {
+
+ // check selection
+ Point selection = fViewer.getTextWidget().getSelectionRange();
+ if (selection.y > 0) {
+ deactivate(true);
+ return;
+ }
+
+ // initialization
+ if (!fIsActive) {
+ fViewer.getTextWidget().addLineBackgroundListener(this);
+ fPositionManager.addManagedPosition(fCurrentLine);
+ fIsActive = true;
+ }
+
+ // redraw line highlight only if it hasn't been drawn yet on the
+ // respective line
+ if (updateHighlightLine()) {
+ // used to handle segmented view of source files
+ int visibleRegionOffset = fViewer.getVisibleRegion().getOffset();
+ // clear last line
+ drawHighlightLine(fLastLine, visibleRegionOffset);
+ // draw new line
+ drawHighlightLine(fCurrentLine, visibleRegionOffset);
+ }
+ }
+
+ /*
+ * @see IPainter#setPositionManager(IPositionManager)
+ */
+ public void setPositionManager(IPositionManager manager) {
+ fPositionManager = manager;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPAnnotationHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPAnnotationHover.java
new file mode 100644
index 0000000..7972adf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPAnnotationHover.java
@@ -0,0 +1,177 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+
+/**
+ * The PHPAnnotationHover provides the hover support for PHP editors.
+ */
+
+public class PHPAnnotationHover implements IAnnotationHover {
+
+ /*
+ * (non-Javadoc) Method declared on IAnnotationHover
+ */
+ // public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
+ // IDocument document= sourceViewer.getDocument();
+ //
+ // try {
+ // IRegion info= document.getLineInformation(lineNumber);
+ // return document.get(info.getOffset(), info.getLength());
+ // } catch (BadLocationException x) {
+ // }
+ //
+ // return null;
+ // }
+ //
+ static final int MAX_INFO_LENGTH = 80;
+
+ /**
+ * @see org.eclipse.jface.text.source.IAnnotationHover#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer,
+ * int)
+ */
+
+ public String getHoverInfo(ISourceViewer viewer, int line) {
+ String info = null;
+ List markers = getMarkersForLine(viewer, line);
+ if (markers != null) {
+ info = "";
+ for (int i = 0; i < markers.size(); i++) {
+ IMarker marker = (IMarker) markers.get(i);
+ String message = marker.getAttribute(IMarker.MESSAGE,
+ (String) null);
+ if (message != null && message.trim().length() > 0) {
+
+ if (message.length() > MAX_INFO_LENGTH) {
+ message = splitMessage(message);
+ }
+ info += message;
+
+ if (i != markers.size() - 1) {
+ info += "\n";
+ }
+ }
+ }
+ }
+ return info;
+ }
+
+ private String splitMessage(String message) {
+ String result = "";
+
+ if (message.length() <= MAX_INFO_LENGTH) {
+ return message;
+ }
+
+ String tmpStr = new String(message);
+
+ while (tmpStr.length() > MAX_INFO_LENGTH) {
+
+ int spacepos = tmpStr.indexOf(" ", MAX_INFO_LENGTH);
+
+ if (spacepos != -1) {
+ result += tmpStr.substring(0, spacepos) + "\n";
+ tmpStr = tmpStr.substring(spacepos);
+ } else {
+ result += tmpStr.substring(0, MAX_INFO_LENGTH) + "\n";
+ tmpStr = tmpStr.substring(MAX_INFO_LENGTH);
+ }
+
+ }
+
+ result += tmpStr;
+
+ return result;
+ }
+
+ /**
+ * Returns all markers which includes the ruler's line of activity.
+ */
+ protected List getMarkersForLine(ISourceViewer aViewer, int aLine) {
+ List markers = new ArrayList();
+ IAnnotationModel model = aViewer.getAnnotationModel();
+ if (model != null) {
+ Iterator e = model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Object o = e.next();
+ if (o instanceof MarkerAnnotation) {
+ MarkerAnnotation a = (MarkerAnnotation) o;
+ if (compareRulerLine(model.getPosition(a), aViewer
+ .getDocument(), aLine) != 0) {
+ markers.add(a.getMarker());
+ }
+ }
+ }
+ }
+ return markers;
+ }
+
+ /**
+ * Returns one marker which includes the ruler's line of activity.
+ */
+ protected IMarker getMarkerForLine(ISourceViewer aViewer, int aLine) {
+ IMarker marker = null;
+ IAnnotationModel model = aViewer.getAnnotationModel();
+ if (model != null) {
+ Iterator e = model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Object o = e.next();
+ if (o instanceof MarkerAnnotation) {
+ MarkerAnnotation a = (MarkerAnnotation) o;
+ if (compareRulerLine(model.getPosition(a), aViewer
+ .getDocument(), aLine) != 0) {
+ marker = a.getMarker();
+ }
+ }
+ }
+ }
+ return marker;
+ }
+
+ /**
+ * Returns distance of given line to specified position (1 = same line, 2 =
+ * included in given position, 0 = not related).
+ */
+ protected int compareRulerLine(Position aPosition, IDocument aDocument,
+ int aLine) {
+ int distance = 0;
+ if (aPosition.getOffset() > -1 && aPosition.getLength() > -1) {
+ try {
+ int markerLine = aDocument.getLineOfOffset(aPosition
+ .getOffset());
+ if (aLine == markerLine) {
+ distance = 1;
+ } else if (markerLine <= aLine
+ && aLine <= aDocument.getLineOfOffset(aPosition
+ .getOffset()
+ + aPosition.getLength())) {
+ distance = 2;
+ }
+ } catch (BadLocationException e) {
+ }
+ }
+ return distance;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPDocumentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPDocumentProvider.java
new file mode 100644
index 0000000..4bd3c76
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPDocumentProvider.java
@@ -0,0 +1,1730 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IProblemRequestor;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.java.IProblemRequestorExtension;
+import net.sourceforge.phpdt.internal.ui.text.spelling.SpellReconcileStrategy.SpellProblem;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceRuleFactory;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.ISynchronizable;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationModelEvent;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelListener;
+import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
+import org.eclipse.jface.text.source.IAnnotationPresentation;
+import org.eclipse.jface.text.source.ImageUtilities;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.ForwardingDocumentProvider;
+import org.eclipse.ui.editors.text.TextFileDocumentProvider;
+import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.AnnotationPreferenceLookup;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+import org.eclipse.ui.texteditor.MarkerUtilities;
+import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
+
+/**
+ * The PHPDocumentProvider provides the IDocuments used by java editors.
+ */
+
+public class PHPDocumentProvider extends TextFileDocumentProvider implements
+ ICompilationUnitDocumentProvider {
+ /**
+ * Here for visibility issues only.
+ */
+
+ /**
+ * Bundle of all required informations to allow working copy management.
+ */
+ /**
+ * Bundle of all required informations to allow working copy management.
+ */
+ static protected class CompilationUnitInfo extends FileInfo {
+ public ICompilationUnit fCopy;
+ }
+
+ /**
+ * Annotation model dealing with java marker annotations and temporary
+ * problems. Also acts as problem requestor for its compilation unit.
+ * Initialiy inactive. Must explicitly be activated.
+ */
+ protected static class CompilationUnitAnnotationModel extends
+ ResourceMarkerAnnotationModel implements IProblemRequestor,
+ IProblemRequestorExtension {
+
+ private static class ProblemRequestorState {
+ boolean fInsideReportingSequence = false;
+
+ List fReportedProblems;
+ }
+
+ private ThreadLocal fProblemRequestorState = new ThreadLocal();
+
+ private int fStateCount = 0;
+
+ private ICompilationUnit fCompilationUnit;
+
+ private List fGeneratedAnnotations;
+
+ private IProgressMonitor fProgressMonitor;
+
+ private boolean fIsActive = false;
+
+ private ReverseMap fReverseMap = new ReverseMap();
+
+ private List fPreviouslyOverlaid = null;
+
+ private List fCurrentlyOverlaid = new ArrayList();
+
+ public CompilationUnitAnnotationModel(IResource resource) {
+ super(resource);
+ }
+
+ public void setCompilationUnit(ICompilationUnit unit) {
+ fCompilationUnit = unit;
+ }
+
+ protected MarkerAnnotation createMarkerAnnotation(IMarker marker) {
+ String markerType = MarkerUtilities.getMarkerType(marker);
+ if (markerType != null
+ && markerType
+ .startsWith(JavaMarkerAnnotation.JAVA_MARKER_TYPE_PREFIX))
+ return new JavaMarkerAnnotation(marker);
+ return super.createMarkerAnnotation(marker);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.AnnotationModel#createAnnotationModelEvent()
+ */
+ protected AnnotationModelEvent createAnnotationModelEvent() {
+ return new CompilationUnitAnnotationModelEvent(this, getResource());
+ }
+
+ protected Position createPositionFromProblem(IProblem problem) {
+ int start = problem.getSourceStart();
+ if (start < 0)
+ return null;
+
+ int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
+ if (length < 0)
+ return null;
+
+ return new Position(start, length);
+ }
+
+ /*
+ * @see IProblemRequestor#beginReporting()
+ */
+ public void beginReporting() {
+ ProblemRequestorState state = (ProblemRequestorState) fProblemRequestorState
+ .get();
+ if (state == null)
+ internalBeginReporting(false);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.java.IProblemRequestorExtension#beginReportingSequence()
+ */
+ public void beginReportingSequence() {
+ ProblemRequestorState state = (ProblemRequestorState) fProblemRequestorState
+ .get();
+ if (state == null)
+ internalBeginReporting(true);
+ }
+
+ /**
+ * Sets up the infrastructure necessary for problem reporting.
+ *
+ * @param insideReportingSequence
+ * true
if this method call is issued from
+ * inside a reporting sequence
+ */
+ private void internalBeginReporting(boolean insideReportingSequence) {
+ if (fCompilationUnit != null) {
+ // &&
+ // fCompilationUnit.getJavaProject().isOnClasspath(fCompilationUnit))
+ // {
+ ProblemRequestorState state = new ProblemRequestorState();
+ state.fInsideReportingSequence = insideReportingSequence;
+ state.fReportedProblems = new ArrayList();
+ synchronized (getLockObject()) {
+ fProblemRequestorState.set(state);
+ ++fStateCount;
+ }
+ }
+ }
+
+ /*
+ * @see IProblemRequestor#acceptProblem(IProblem)
+ */
+ public void acceptProblem(IProblem problem) {
+ if (isActive()) {
+ ProblemRequestorState state = (ProblemRequestorState) fProblemRequestorState
+ .get();
+ if (state != null)
+ state.fReportedProblems.add(problem);
+ }
+ }
+
+ /*
+ * @see IProblemRequestor#endReporting()
+ */
+ public void endReporting() {
+ ProblemRequestorState state = (ProblemRequestorState) fProblemRequestorState
+ .get();
+ if (state != null && !state.fInsideReportingSequence)
+ internalEndReporting(state);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.java.IProblemRequestorExtension#endReportingSequence()
+ */
+ public void endReportingSequence() {
+ ProblemRequestorState state = (ProblemRequestorState) fProblemRequestorState
+ .get();
+ if (state != null && state.fInsideReportingSequence)
+ internalEndReporting(state);
+ }
+
+ private void internalEndReporting(ProblemRequestorState state) {
+ int stateCount = 0;
+ synchronized (getLockObject()) {
+ --fStateCount;
+ stateCount = fStateCount;
+ fProblemRequestorState.set(null);
+ }
+
+ if (stateCount == 0 && isActive())
+ reportProblems(state.fReportedProblems);
+ }
+
+ /**
+ * Signals the end of problem reporting.
+ */
+ private void reportProblems(List reportedProblems) {
+ if (fProgressMonitor != null && fProgressMonitor.isCanceled())
+ return;
+
+ boolean temporaryProblemsChanged = false;
+
+ synchronized (getLockObject()) {
+
+ boolean isCanceled = false;
+
+ fPreviouslyOverlaid = fCurrentlyOverlaid;
+ fCurrentlyOverlaid = new ArrayList();
+
+ if (fGeneratedAnnotations.size() > 0) {
+ temporaryProblemsChanged = true;
+ removeAnnotations(fGeneratedAnnotations, false, true);
+ fGeneratedAnnotations.clear();
+ }
+
+ if (reportedProblems != null && reportedProblems.size() > 0) {
+
+ Iterator e = reportedProblems.iterator();
+ while (e.hasNext()) {
+
+ if (fProgressMonitor != null
+ && fProgressMonitor.isCanceled()) {
+ isCanceled = true;
+ break;
+ }
+
+ IProblem problem = (IProblem) e.next();
+ Position position = createPositionFromProblem(problem);
+ if (position != null) {
+
+ try {
+ ProblemAnnotation annotation = new ProblemAnnotation(
+ problem, fCompilationUnit);
+ overlayMarkers(position, annotation);
+ addAnnotation(annotation, position, false);
+ fGeneratedAnnotations.add(annotation);
+
+ temporaryProblemsChanged = true;
+ } catch (BadLocationException x) {
+ // ignore invalid position
+ }
+ }
+ }
+ }
+
+ removeMarkerOverlays(isCanceled);
+ fPreviouslyOverlaid = null;
+ }
+
+ if (temporaryProblemsChanged)
+ fireModelChanged();
+ }
+
+ private void removeMarkerOverlays(boolean isCanceled) {
+ if (isCanceled) {
+ fCurrentlyOverlaid.addAll(fPreviouslyOverlaid);
+ } else if (fPreviouslyOverlaid != null) {
+ Iterator e = fPreviouslyOverlaid.iterator();
+ while (e.hasNext()) {
+ JavaMarkerAnnotation annotation = (JavaMarkerAnnotation) e
+ .next();
+ annotation.setOverlay(null);
+ }
+ }
+ }
+
+ /**
+ * Overlays value with problem annotation.
+ *
+ * @param problemAnnotation
+ */
+ private void setOverlay(Object value,
+ ProblemAnnotation problemAnnotation) {
+ if (value instanceof JavaMarkerAnnotation) {
+ JavaMarkerAnnotation annotation = (JavaMarkerAnnotation) value;
+ if (annotation.isProblem()) {
+ annotation.setOverlay(problemAnnotation);
+ fPreviouslyOverlaid.remove(annotation);
+ fCurrentlyOverlaid.add(annotation);
+ }
+ } else {
+ }
+ }
+
+ private void overlayMarkers(Position position,
+ ProblemAnnotation problemAnnotation) {
+ Object value = getAnnotations(position);
+ if (value instanceof List) {
+ List list = (List) value;
+ for (Iterator e = list.iterator(); e.hasNext();)
+ setOverlay(e.next(), problemAnnotation);
+ } else {
+ setOverlay(value, problemAnnotation);
+ }
+ }
+
+ /**
+ * Tells this annotation model to collect temporary problems from now
+ * on.
+ */
+ private void startCollectingProblems() {
+ fGeneratedAnnotations = new ArrayList();
+ }
+
+ /**
+ * Tells this annotation model to no longer collect temporary problems.
+ */
+ private void stopCollectingProblems() {
+ if (fGeneratedAnnotations != null)
+ removeAnnotations(fGeneratedAnnotations, true, true);
+ fGeneratedAnnotations = null;
+ }
+
+ /*
+ * @see IProblemRequestor#isActive()
+ */
+ public boolean isActive() {
+ return fIsActive;
+ }
+
+ /*
+ * @see IProblemRequestorExtension#setProgressMonitor(IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ fProgressMonitor = monitor;
+ }
+
+ /*
+ * @see IProblemRequestorExtension#setIsActive(boolean)
+ */
+ public void setIsActive(boolean isActive) {
+ if (fIsActive != isActive) {
+ fIsActive = isActive;
+ if (fIsActive)
+ startCollectingProblems();
+ else
+ stopCollectingProblems();
+ }
+ }
+
+ private Object getAnnotations(Position position) {
+ return fReverseMap.get(position);
+ }
+
+ /*
+ * @see AnnotationModel#addAnnotation(Annotation, Position, boolean)
+ */
+ protected void addAnnotation(Annotation annotation, Position position,
+ boolean fireModelChanged) throws BadLocationException {
+ super.addAnnotation(annotation, position, fireModelChanged);
+
+ Object cached = fReverseMap.get(position);
+ if (cached == null)
+ fReverseMap.put(position, annotation);
+ else if (cached instanceof List) {
+ List list = (List) cached;
+ list.add(annotation);
+ } else if (cached instanceof Annotation) {
+ List list = new ArrayList(2);
+ list.add(cached);
+ list.add(annotation);
+ fReverseMap.put(position, list);
+ }
+ }
+
+ /*
+ * @see AnnotationModel#removeAllAnnotations(boolean)
+ */
+ protected void removeAllAnnotations(boolean fireModelChanged) {
+ super.removeAllAnnotations(fireModelChanged);
+ fReverseMap.clear();
+ }
+
+ /*
+ * @see AnnotationModel#removeAnnotation(Annotation, boolean)
+ */
+ protected void removeAnnotation(Annotation annotation,
+ boolean fireModelChanged) {
+ Position position = getPosition(annotation);
+ Object cached = fReverseMap.get(position);
+ if (cached instanceof List) {
+ List list = (List) cached;
+ list.remove(annotation);
+ if (list.size() == 1) {
+ fReverseMap.put(position, list.get(0));
+ list.clear();
+ }
+ } else if (cached instanceof Annotation) {
+ fReverseMap.remove(position);
+ }
+ super.removeAnnotation(annotation, fireModelChanged);
+ }
+ }
+
+ protected static class GlobalAnnotationModelListener implements
+ IAnnotationModelListener, IAnnotationModelListenerExtension {
+
+ private ListenerList fListenerList;
+
+ public GlobalAnnotationModelListener() {
+ fListenerList = new ListenerList();
+ }
+
+ public void addListener(IAnnotationModelListener listener) {
+ fListenerList.add(listener);
+ }
+
+ /**
+ * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
+ */
+ public void modelChanged(AnnotationModelEvent event) {
+ Object[] listeners = fListenerList.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ Object curr = listeners[i];
+ if (curr instanceof IAnnotationModelListenerExtension) {
+ ((IAnnotationModelListenerExtension) curr)
+ .modelChanged(event);
+ }
+ }
+ }
+
+ /**
+ * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
+ */
+ public void modelChanged(IAnnotationModel model) {
+ Object[] listeners = fListenerList.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ ((IAnnotationModelListener) listeners[i]).modelChanged(model);
+ }
+ }
+
+ public void removeListener(IAnnotationModelListener listener) {
+ fListenerList.remove(listener);
+ }
+ }
+
+ /**
+ * Annotation representating an IProblem
.
+ */
+ static public class ProblemAnnotation extends Annotation implements
+ IJavaAnnotation, IAnnotationPresentation {
+
+ private static final String SPELLING_ANNOTATION_TYPE = "org.eclipse.ui.workbench.texteditor.spelling";
+
+ // XXX: To be fully correct these constants should be non-static
+ /**
+ * The layer in which task problem annotations are located.
+ */
+ private static final int TASK_LAYER;
+
+ /**
+ * The layer in which info problem annotations are located.
+ */
+ private static final int INFO_LAYER;
+
+ /**
+ * The layer in which warning problem annotations representing are
+ * located.
+ */
+ private static final int WARNING_LAYER;
+
+ /**
+ * The layer in which error problem annotations representing are
+ * located.
+ */
+ private static final int ERROR_LAYER;
+
+ static {
+ AnnotationPreferenceLookup lookup = EditorsUI
+ .getAnnotationPreferenceLookup();
+ TASK_LAYER = computeLayer(
+ "org.eclipse.ui.workbench.texteditor.task", lookup); //$NON-NLS-1$
+ INFO_LAYER = computeLayer("net.sourceforge.phpdt.ui.info", lookup); //$NON-NLS-1$
+ WARNING_LAYER = computeLayer(
+ "net.sourceforge.phpdt.ui.warning", lookup); //$NON-NLS-1$
+ ERROR_LAYER = computeLayer("net.sourceforge.phpdt.ui.error", lookup); //$NON-NLS-1$
+ }
+
+ private static int computeLayer(String annotationType,
+ AnnotationPreferenceLookup lookup) {
+ Annotation annotation = new Annotation(annotationType, false, null);
+ AnnotationPreference preference = lookup
+ .getAnnotationPreference(annotation);
+ if (preference != null)
+ return preference.getPresentationLayer() + 1;
+ else
+ return IAnnotationAccessExtension.DEFAULT_LAYER + 1;
+ }
+
+ // private static Image fgQuickFixImage;
+ // private static Image fgQuickFixErrorImage;
+ // private static boolean fgQuickFixImagesInitialized= false;
+
+ private ICompilationUnit fCompilationUnit;
+
+ private List fOverlaids;
+
+ private IProblem fProblem;
+
+ private Image fImage;
+
+ private boolean fQuickFixImagesInitialized = false;
+
+ private int fLayer = IAnnotationAccessExtension.DEFAULT_LAYER;
+
+ public ProblemAnnotation(IProblem problem, ICompilationUnit cu) {
+
+ fProblem = problem;
+ fCompilationUnit = cu;
+
+ if (SpellProblem.Spelling == fProblem.getID()) {
+ setType(SPELLING_ANNOTATION_TYPE);
+ fLayer = WARNING_LAYER;
+ } else if (IProblem.Task == fProblem.getID()) {
+ setType(JavaMarkerAnnotation.TASK_ANNOTATION_TYPE);
+ fLayer = TASK_LAYER;
+ } else if (fProblem.isWarning()) {
+ setType(JavaMarkerAnnotation.WARNING_ANNOTATION_TYPE);
+ fLayer = WARNING_LAYER;
+ } else if (fProblem.isError()) {
+ setType(JavaMarkerAnnotation.ERROR_ANNOTATION_TYPE);
+ fLayer = ERROR_LAYER;
+ } else {
+ setType(JavaMarkerAnnotation.INFO_ANNOTATION_TYPE);
+ fLayer = INFO_LAYER;
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationPresentation#getLayer()
+ */
+ public int getLayer() {
+ return fLayer;
+ }
+
+ private void initializeImages() {
+ // http://bugs.eclipse.org/bugs/show_bug.cgi?id=18936
+ // if (!fQuickFixImagesInitialized) {
+ // if (isProblem() && indicateQuixFixableProblems() &&
+ // JavaCorrectionProcessor.hasCorrections(this)) { // no light bulb
+ // for tasks
+ // if (!fgQuickFixImagesInitialized) {
+ // fgQuickFixImage=
+ // JavaPluginImages.get(JavaPluginImages.IMG_OBJS_FIXABLE_PROBLEM);
+ // fgQuickFixErrorImage=
+ // JavaPluginImages.get(JavaPluginImages.IMG_OBJS_FIXABLE_ERROR);
+ // fgQuickFixImagesInitialized= true;
+ // }
+ // if (JavaMarkerAnnotation.ERROR_ANNOTATION_TYPE.equals(getType()))
+ // fImage= fgQuickFixErrorImage;
+ // else
+ // fImage= fgQuickFixImage;
+ // }
+ // fQuickFixImagesInitialized= true;
+ // }
+ }
+
+ private boolean indicateQuixFixableProblems() {
+ return PreferenceConstants.getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_CORRECTION_INDICATION);
+ }
+
+ /*
+ * @see Annotation#paint
+ */
+ public void paint(GC gc, Canvas canvas, Rectangle r) {
+ initializeImages();
+ if (fImage != null)
+ ImageUtilities.drawImage(fImage, gc, canvas, r, SWT.CENTER,
+ SWT.TOP);
+ }
+
+ /*
+ * @see IJavaAnnotation#getImage(Display)
+ */
+ public Image getImage(Display display) {
+ initializeImages();
+ return fImage;
+ }
+
+ /*
+ * @see IJavaAnnotation#getMessage()
+ */
+ public String getText() {
+ return fProblem.getMessage();
+ }
+
+ /*
+ * @see IJavaAnnotation#getArguments()
+ */
+ public String[] getArguments() {
+ return isProblem() ? fProblem.getArguments() : null;
+ }
+
+ /*
+ * @see IJavaAnnotation#getId()
+ */
+ public int getId() {
+ return fProblem.getID();
+ }
+
+ /*
+ * @see IJavaAnnotation#isProblem()
+ */
+ public boolean isProblem() {
+ String type = getType();
+ return JavaMarkerAnnotation.WARNING_ANNOTATION_TYPE.equals(type)
+ || JavaMarkerAnnotation.ERROR_ANNOTATION_TYPE.equals(type)
+ || SPELLING_ANNOTATION_TYPE.equals(type);
+ }
+
+ /*
+ * @see IJavaAnnotation#hasOverlay()
+ */
+ public boolean hasOverlay() {
+ return false;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.IJavaAnnotation#getOverlay()
+ */
+ public IJavaAnnotation getOverlay() {
+ return null;
+ }
+
+ /*
+ * @see IJavaAnnotation#addOverlaid(IJavaAnnotation)
+ */
+ public void addOverlaid(IJavaAnnotation annotation) {
+ if (fOverlaids == null)
+ fOverlaids = new ArrayList(1);
+ fOverlaids.add(annotation);
+ }
+
+ /*
+ * @see IJavaAnnotation#removeOverlaid(IJavaAnnotation)
+ */
+ public void removeOverlaid(IJavaAnnotation annotation) {
+ if (fOverlaids != null) {
+ fOverlaids.remove(annotation);
+ if (fOverlaids.size() == 0)
+ fOverlaids = null;
+ }
+ }
+
+ /*
+ * @see IJavaAnnotation#getOverlaidIterator()
+ */
+ public Iterator getOverlaidIterator() {
+ if (fOverlaids != null)
+ return fOverlaids.iterator();
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.IJavaAnnotation#getCompilationUnit()
+ */
+ public ICompilationUnit getCompilationUnit() {
+ return fCompilationUnit;
+ }
+ }
+
+ /**
+ * Internal structure for mapping positions to some value. The reason for
+ * this specific structure is that positions can change over time. Thus a
+ * lookup is based on value and not on hash value.
+ */
+ protected static class ReverseMap {
+
+ static class Entry {
+ Position fPosition;
+
+ Object fValue;
+ }
+
+ private int fAnchor = 0;
+
+ private List fList = new ArrayList(2);
+
+ public ReverseMap() {
+ }
+
+ public void clear() {
+ fList.clear();
+ }
+
+ public Object get(Position position) {
+
+ Entry entry;
+
+ // behind anchor
+ int length = fList.size();
+ for (int i = fAnchor; i < length; i++) {
+ entry = (Entry) fList.get(i);
+ if (entry.fPosition.equals(position)) {
+ fAnchor = i;
+ return entry.fValue;
+ }
+ }
+
+ // before anchor
+ for (int i = 0; i < fAnchor; i++) {
+ entry = (Entry) fList.get(i);
+ if (entry.fPosition.equals(position)) {
+ fAnchor = i;
+ return entry.fValue;
+ }
+ }
+
+ return null;
+ }
+
+ private int getIndex(Position position) {
+ Entry entry;
+ int length = fList.size();
+ for (int i = 0; i < length; i++) {
+ entry = (Entry) fList.get(i);
+ if (entry.fPosition.equals(position))
+ return i;
+ }
+ return -1;
+ }
+
+ public void put(Position position, Object value) {
+ int index = getIndex(position);
+ if (index == -1) {
+ Entry entry = new Entry();
+ entry.fPosition = position;
+ entry.fValue = value;
+ fList.add(entry);
+ } else {
+ Entry entry = (Entry) fList.get(index);
+ entry.fValue = value;
+ }
+ }
+
+ public void remove(Position position) {
+ int index = getIndex(position);
+ if (index > -1)
+ fList.remove(index);
+ }
+ }
+
+ /**
+ * Document that can also be used by a background reconciler.
+ */
+ protected static class PartiallySynchronizedDocument extends Document {
+
+ /*
+ * @see IDocumentExtension#startSequentialRewrite(boolean)
+ */
+ synchronized public void startSequentialRewrite(boolean normalized) {
+ super.startSequentialRewrite(normalized);
+ }
+
+ /*
+ * @see IDocumentExtension#stopSequentialRewrite()
+ */
+ synchronized public void stopSequentialRewrite() {
+ super.stopSequentialRewrite();
+ }
+
+ /*
+ * @see IDocument#get()
+ */
+ synchronized public String get() {
+ return super.get();
+ }
+
+ /*
+ * @see IDocument#get(int, int)
+ */
+ synchronized public String get(int offset, int length)
+ throws BadLocationException {
+ return super.get(offset, length);
+ }
+
+ /*
+ * @see IDocument#getChar(int)
+ */
+ synchronized public char getChar(int offset)
+ throws BadLocationException {
+ return super.getChar(offset);
+ }
+
+ /*
+ * @see IDocument#replace(int, int, String)
+ */
+ synchronized public void replace(int offset, int length, String text)
+ throws BadLocationException {
+ super.replace(offset, length, text);
+ }
+
+ /*
+ * @see IDocument#set(String)
+ */
+ synchronized public void set(String text) {
+ super.set(text);
+ }
+ };
+
+ //
+ // private static PHPPartitionScanner HTML_PARTITION_SCANNER = null;
+ //
+ // private static PHPPartitionScanner PHP_PARTITION_SCANNER = null;
+ // private static PHPPartitionScanner SMARTY_PARTITION_SCANNER = null;
+ //
+ // // private final static String[] TYPES= new String[] {
+ // PHPPartitionScanner.PHP, PHPPartitionScanner.JAVA_DOC,
+ // PHPPartitionScanner.JAVA_MULTILINE_COMMENT };
+ // private final static String[] TYPES =
+ // new String[] {
+ // IPHPPartitionScannerConstants.PHP,
+ // IPHPPartitionScannerConstants.PHP_MULTILINE_COMMENT,
+ // IPHPPartitionScannerConstants.HTML,
+ // IPHPPartitionScannerConstants.HTML_MULTILINE_COMMENT,
+ // IPHPPartitionScannerConstants.JAVASCRIPT,
+ // IPHPPartitionScannerConstants.CSS,
+ // IPHPPartitionScannerConstants.SMARTY,
+ // IPHPPartitionScannerConstants.SMARTY_MULTILINE_COMMENT };
+ // private static PHPPartitionScanner XML_PARTITION_SCANNER = null;
+
+ /* Preference key for temporary problems */
+ private final static String HANDLE_TEMPORARY_PROBLEMS = PreferenceConstants.EDITOR_EVALUTE_TEMPORARY_PROBLEMS;
+
+ /** Indicates whether the save has been initialized by this provider */
+ private boolean fIsAboutToSave = false;
+
+ /** The save policy used by this provider */
+ private ISavePolicy fSavePolicy;
+
+ /** Internal property changed listener */
+ private IPropertyChangeListener fPropertyListener;
+
+ /** annotation model listener added to all created CU annotation models */
+ private GlobalAnnotationModelListener fGlobalAnnotationModelListener;
+
+ public PHPDocumentProvider() {
+ // IDocumentProvider provider= new TextFileDocumentProvider(new
+ // JavaStorageDocumentProvider());
+ IDocumentProvider provider = new TextFileDocumentProvider();
+ provider = new ForwardingDocumentProvider(
+ IPHPPartitions.PHP_PARTITIONING,
+ new JavaDocumentSetupParticipant(), provider);
+ setParentDocumentProvider(provider);
+
+ fGlobalAnnotationModelListener = new GlobalAnnotationModelListener();
+ fPropertyListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ if (HANDLE_TEMPORARY_PROBLEMS.equals(event.getProperty()))
+ enableHandlingTemporaryProblems();
+ }
+ };
+ WebUI.getDefault().getPreferenceStore()
+ .addPropertyChangeListener(fPropertyListener);
+
+ }
+
+ /**
+ * Sets the document provider's save policy.
+ */
+ public void setSavePolicy(ISavePolicy savePolicy) {
+ fSavePolicy = savePolicy;
+ }
+
+ /**
+ * Creates a compilation unit from the given file.
+ *
+ * @param file
+ * the file from which to create the compilation unit
+ */
+ protected ICompilationUnit createCompilationUnit(IFile file) {
+ Object element = JavaCore.create(file);
+ if (element instanceof ICompilationUnit)
+ return (ICompilationUnit) element;
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createEmptyFileInfo()
+ */
+ protected FileInfo createEmptyFileInfo() {
+ return new CompilationUnitInfo();
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createAnnotationModel(org.eclipse.core.resources.IFile)
+ */
+ protected IAnnotationModel createAnnotationModel(IFile file) {
+ return new CompilationUnitAnnotationModel(file);
+ }
+
+ /*
+ * @see AbstractDocumentProvider#createElementInfo(Object)
+ */
+ // protected ElementInfo createElementInfo(Object element) throws
+ // CoreException {
+ //
+ // if (!(element instanceof IFileEditorInput))
+ // return super.createElementInfo(element);
+ //
+ // IFileEditorInput input = (IFileEditorInput) element;
+ // ICompilationUnit original = createCompilationUnit(input.getFile());
+ // if (original != null) {
+ //
+ // try {
+ //
+ // try {
+ // refreshFile(input.getFile());
+ // } catch (CoreException x) {
+ // handleCoreException(x,
+ // PHPEditorMessages.getString("PHPDocumentProvider.error.createElementInfo"));
+ // //$NON-NLS-1$
+ // }
+ //
+ // IAnnotationModel m = createCompilationUnitAnnotationModel(input);
+ // IProblemRequestor r = m instanceof IProblemRequestor ?
+ // (IProblemRequestor) m : null;
+ // ICompilationUnit c = (ICompilationUnit)
+ // original.getSharedWorkingCopy(getProgressMonitor(), fBufferFactory, r);
+ //
+ // DocumentAdapter a = null;
+ // try {
+ // a = (DocumentAdapter) c.getBuffer();
+ // } catch (ClassCastException x) {
+ // IStatus status = new Status(IStatus.ERROR, PHPeclipsePlugin.PLUGIN_ID,
+ // PHPStatusConstants.TEMPLATE_IO_EXCEPTION, "Shared working copy has wrong
+ // buffer", x); //$NON-NLS-1$
+ // throw new CoreException(status);
+ // }
+ //
+ // _FileSynchronizer f = new _FileSynchronizer(input);
+ // f.install();
+ //
+ // CompilationUnitInfo info = new CompilationUnitInfo(a.getDocument(), m, f,
+ // c);
+ // info.setModificationStamp(computeModificationStamp(input.getFile()));
+ // info.fStatus = a.getStatus();
+ // info.fEncoding = getPersistedEncoding(input);
+ //
+ // if (r instanceof IProblemRequestorExtension) {
+ // IProblemRequestorExtension extension = (IProblemRequestorExtension) r;
+ // extension.setIsActive(isHandlingTemporaryProblems());
+ // }
+ // m.addAnnotationModelListener(fGlobalAnnotationModelListener);
+ //
+ // return info;
+ //
+ // } catch (JavaModelException x) {
+ // throw new CoreException(x.getStatus());
+ // }
+ // } else {
+ // return super.createElementInfo(element);
+ // }
+ // }
+ /*
+ * @see AbstractDocumentProvider#disposeElementInfo(Object, ElementInfo)
+ */
+ // protected void disposeElementInfo(Object element, ElementInfo info) {
+ //
+ // if (info instanceof CompilationUnitInfo) {
+ // CompilationUnitInfo cuInfo = (CompilationUnitInfo) info;
+ // cuInfo.fCopy.destroy();
+ // cuInfo.fModel.removeAnnotationModelListener(fGlobalAnnotationModelListener);
+ // }
+ //
+ // super.disposeElementInfo(element, info);
+ // }
+ /*
+ * @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object,
+ * IDocument, boolean)
+ */
+ // protected void doSaveDocument(IProgressMonitor monitor, Object element,
+ // IDocument document, boolean overwrite)
+ // throws CoreException {
+ //
+ // ElementInfo elementInfo = getElementInfo(element);
+ // if (elementInfo instanceof CompilationUnitInfo) {
+ // CompilationUnitInfo info = (CompilationUnitInfo) elementInfo;
+ //
+ // // update structure, assumes lock on info.fCopy
+ // info.fCopy.reconcile();
+ //
+ // ICompilationUnit original = (ICompilationUnit)
+ // info.fCopy.getOriginalElement();
+ // IResource resource = original.getResource();
+ //
+ // if (resource == null) {
+ // // underlying resource has been deleted, just recreate file, ignore the
+ // rest
+ // super.doSaveDocument(monitor, element, document, overwrite);
+ // return;
+ // }
+ //
+ // if (resource != null && !overwrite)
+ // checkSynchronizationState(info.fModificationStamp, resource);
+ //
+ // if (fSavePolicy != null)
+ // fSavePolicy.preSave(info.fCopy);
+ //
+ // // inform about the upcoming content change
+ // fireElementStateChanging(element);
+ // try {
+ // fIsAboutToSave = true;
+ // // commit working copy
+ // info.fCopy.commit(overwrite, monitor);
+ // } catch (CoreException x) {
+ // // inform about the failure
+ // fireElementStateChangeFailed(element);
+ // throw x;
+ // } catch (RuntimeException x) {
+ // // inform about the failure
+ // fireElementStateChangeFailed(element);
+ // throw x;
+ // } finally {
+ // fIsAboutToSave = false;
+ // }
+ //
+ // // If here, the dirty state of the editor will change to "not dirty".
+ // // Thus, the state changing flag will be reset.
+ //
+ // AbstractMarkerAnnotationModel model = (AbstractMarkerAnnotationModel)
+ // info.fModel;
+ // model.updateMarkers(info.fDocument);
+ //
+ // if (resource != null)
+ // info.setModificationStamp(computeModificationStamp(resource));
+ //
+ // if (fSavePolicy != null) {
+ // ICompilationUnit unit = fSavePolicy.postSave(original);
+ // if (unit != null) {
+ // IResource r = unit.getResource();
+ // IMarker[] markers = r.findMarkers(IMarker.MARKER, true,
+ // IResource.DEPTH_ZERO);
+ // if (markers != null && markers.length > 0) {
+ // for (int i = 0; i < markers.length; i++)
+ // model.updateMarker(markers[i], info.fDocument, null);
+ // }
+ // }
+ // }
+ //
+ // } else {
+ // super.doSaveDocument(monitor, element, document, overwrite);
+ // }
+ // }
+ /*
+ * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createFileInfo(java.lang.Object)
+ */
+ protected FileInfo createFileInfo(Object element) throws CoreException {
+ if (!(element instanceof IFileEditorInput))
+ return null;
+
+ IFileEditorInput input = (IFileEditorInput) element;
+ ICompilationUnit original = createCompilationUnit(input.getFile());
+ if (original == null)
+ return null;
+
+ FileInfo info = super.createFileInfo(element);
+ if (!(info instanceof CompilationUnitInfo))
+ return null;
+
+ CompilationUnitInfo cuInfo = (CompilationUnitInfo) info;
+ setUpSynchronization(cuInfo);
+
+ IProblemRequestor requestor = cuInfo.fModel instanceof IProblemRequestor ? (IProblemRequestor) cuInfo.fModel
+ : null;
+
+ original.becomeWorkingCopy(requestor, getProgressMonitor());
+ cuInfo.fCopy = original;
+
+ if (cuInfo.fModel instanceof CompilationUnitAnnotationModel) {
+ CompilationUnitAnnotationModel model = (CompilationUnitAnnotationModel) cuInfo.fModel;
+ model.setCompilationUnit(cuInfo.fCopy);
+ }
+
+ if (cuInfo.fModel != null)
+ cuInfo.fModel
+ .addAnnotationModelListener(fGlobalAnnotationModelListener);
+
+ if (requestor instanceof IProblemRequestorExtension) {
+ IProblemRequestorExtension extension = (IProblemRequestorExtension) requestor;
+ extension.setIsActive(isHandlingTemporaryProblems());
+ }
+
+ return cuInfo;
+ }
+
+ private void setUpSynchronization(CompilationUnitInfo cuInfo) {
+ IDocument document = cuInfo.fTextFileBuffer.getDocument();
+ IAnnotationModel model = cuInfo.fModel;
+
+ if (document instanceof ISynchronizable
+ && model instanceof ISynchronizable) {
+ Object lock = ((ISynchronizable) document).getLockObject();
+ ((ISynchronizable) model).setLockObject(lock);
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#disposeFileInfo(java.lang.Object,
+ * org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo)
+ */
+ protected void disposeFileInfo(Object element, FileInfo info) {
+ if (info instanceof CompilationUnitInfo) {
+ CompilationUnitInfo cuInfo = (CompilationUnitInfo) info;
+
+ try {
+ cuInfo.fCopy.discardWorkingCopy();
+ } catch (JavaModelException x) {
+ handleCoreException(x, x.getMessage());
+ }
+
+ if (cuInfo.fModel != null)
+ cuInfo.fModel
+ .removeAnnotationModelListener(fGlobalAnnotationModelListener);
+ }
+ super.disposeFileInfo(element, info);
+ }
+
+ protected void commitWorkingCopy(IProgressMonitor monitor, Object element,
+ CompilationUnitInfo info, boolean overwrite) throws CoreException {
+ synchronized (info.fCopy) {
+ info.fCopy.reconcile();
+ }
+
+ IDocument document = info.fTextFileBuffer.getDocument();
+ IResource resource = info.fCopy.getResource();
+
+ Assert.isTrue(resource instanceof IFile);
+ if (!resource.exists()) {
+ // underlying resource has been deleted, just recreate file, ignore
+ // the rest
+ createFileFromDocument(monitor, (IFile) resource, document);
+ return;
+ }
+
+ if (fSavePolicy != null)
+ fSavePolicy.preSave(info.fCopy);
+
+ try {
+
+ fIsAboutToSave = true;
+ info.fCopy.commitWorkingCopy(overwrite, monitor);
+
+ } catch (CoreException x) {
+ // inform about the failure
+ fireElementStateChangeFailed(element);
+ throw x;
+ } catch (RuntimeException x) {
+ // inform about the failure
+ fireElementStateChangeFailed(element);
+ throw x;
+ } finally {
+ fIsAboutToSave = false;
+ }
+
+ // If here, the dirty state of the editor will change to "not dirty".
+ // Thus, the state changing flag will be reset.
+ if (info.fModel instanceof AbstractMarkerAnnotationModel) {
+ AbstractMarkerAnnotationModel model = (AbstractMarkerAnnotationModel) info.fModel;
+ model.updateMarkers(document);
+ }
+
+ if (fSavePolicy != null) {
+ ICompilationUnit unit = fSavePolicy.postSave(info.fCopy);
+ if (unit != null
+ && info.fModel instanceof AbstractMarkerAnnotationModel) {
+ IResource r = unit.getResource();
+ IMarker[] markers = r.findMarkers(IMarker.MARKER, true,
+ IResource.DEPTH_ZERO);
+ if (markers != null && markers.length > 0) {
+ AbstractMarkerAnnotationModel model = (AbstractMarkerAnnotationModel) info.fModel;
+ for (int i = 0; i < markers.length; i++)
+ model.updateMarker(document, markers[i], null);
+ }
+ }
+ }
+
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createSaveOperation(java.lang.Object,
+ * org.eclipse.jface.text.IDocument, boolean)
+ */
+ protected DocumentProviderOperation createSaveOperation(
+ final Object element, final IDocument document,
+ final boolean overwrite) throws CoreException {
+ // final FileInfo info= getFileInfo(element);
+ // if (info instanceof CompilationUnitInfo) {
+ // return new DocumentProviderOperation() {
+ // /*
+ // * @see
+ // org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
+ // */
+ // protected void execute(IProgressMonitor monitor) throws CoreException
+ // {
+ // commitWorkingCopy(monitor, element, (CompilationUnitInfo) info,
+ // overwrite);
+ // }
+ // /*
+ // * @see
+ // org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
+ // */
+ // public ISchedulingRule getSchedulingRule() {
+ // if (info.fElement instanceof IFileEditorInput) {
+ // IFile file= ((IFileEditorInput) info.fElement).getFile();
+ // IResourceRuleFactory ruleFactory=
+ // ResourcesPlugin.getWorkspace().getRuleFactory();
+ // if (file == null || !file.exists())
+ // return ruleFactory.createRule(file);
+ // else
+ // return ruleFactory.modifyRule(file);
+ // } else
+ // return null;
+ // }
+ // };
+ // }
+ // return null;
+ final FileInfo info = getFileInfo(element);
+ if (info instanceof CompilationUnitInfo) {
+ return new DocumentProviderOperation() {
+ /*
+ * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void execute(IProgressMonitor monitor)
+ throws CoreException {
+ commitWorkingCopy(monitor, element,
+ (CompilationUnitInfo) info, overwrite);
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
+ */
+ public ISchedulingRule getSchedulingRule() {
+ if (info.fElement instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput) info.fElement)
+ .getFile();
+ return computeSchedulingRule(file);
+ } else
+ return null;
+ }
+ };
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractDocumentProvider
+ */
+ // protected IDocument createDocument(Object element) throws CoreException {
+ // if (element instanceof IEditorInput) {
+ // Document document = new PartiallySynchronizedDocument();
+ // if (setDocumentContent(document, (IEditorInput) element,
+ // getEncoding(element))) {
+ // initializeDocument(document, (IEditorInput) element);
+ //
+ // //
+ // // IDocument document = super.createDocument(element);
+ // // if (document != null) {
+ // // IDocumentPartitioner partitioner = null;
+ // // if (element instanceof FileEditorInput) {
+ // // IFile file = (IFile) ((FileEditorInput)
+ // element).getAdapter(IFile.class);
+ // // String filename = file.getLocation().toString();
+ // // String extension = filename.substring(filename.lastIndexOf("."),
+ // filename.length());
+ // // // System.out.println(extension);
+ // // if (extension.equalsIgnoreCase(".html") ||
+ // extension.equalsIgnoreCase(".htm")) {
+ // // // html
+ // // partitioner = createHTMLPartitioner();
+ // // } else if (extension.equalsIgnoreCase(".xml")) {
+ // // // xml
+ // // partitioner = createXMLPartitioner();
+ // // } else if (extension.equalsIgnoreCase(".js")) {
+ // // // javascript
+ // // partitioner = createJavaScriptPartitioner();
+ // // } else if (extension.equalsIgnoreCase(".css")) {
+ // // // cascading style sheets
+ // // partitioner = createCSSPartitioner();
+ // // } else if (extension.equalsIgnoreCase(".tpl")) {
+ // // // smarty ?
+ // // partitioner = createSmartyPartitioner();
+ // // } else if (extension.equalsIgnoreCase(".inc")) {
+ // // // php include files ?
+ // // partitioner = createIncludePartitioner();
+ // // }
+ // // }
+ // //
+ // // if (partitioner == null) {
+ // // partitioner = createPHPPartitioner();
+ // // }
+ // // document.setDocumentPartitioner(partitioner);
+ // // partitioner.connect(document);
+ // }
+ // return document;
+ // }
+ // return null;
+ // }
+ // /**
+ // * Return a partitioner for .html files.
+ // */
+ // private IDocumentPartitioner createHTMLPartitioner() {
+ // return new DefaultPartitioner(getHTMLPartitionScanner(), TYPES);
+ // }
+ //
+ // private IDocumentPartitioner createIncludePartitioner() {
+ // return new DefaultPartitioner(getPHPPartitionScanner(), TYPES);
+ // }
+ //
+ // private IDocumentPartitioner createJavaScriptPartitioner() {
+ // return new DefaultPartitioner(getHTMLPartitionScanner(), TYPES);
+ // }
+ /**
+ * Creates a line tracker working with the same line delimiters as the
+ * document of the given element. Assumes the element to be managed by this
+ * document provider.
+ *
+ * @param element
+ * the element serving as blue print
+ * @return a line tracker based on the same line delimiters as the element's
+ * document
+ */
+ public ILineTracker createLineTracker(Object element) {
+ return new DefaultLineTracker();
+ }
+
+ // /**
+ // * Return a partitioner for .php files.
+ // */
+ // private IDocumentPartitioner createPHPPartitioner() {
+ // return new DefaultPartitioner(getPHPPartitionScanner(), TYPES);
+ // }
+ //
+ // private IDocumentPartitioner createSmartyPartitioner() {
+ // return new DefaultPartitioner(getSmartyPartitionScanner(), TYPES);
+ // }
+ //
+ // private IDocumentPartitioner createXMLPartitioner() {
+ // return new DefaultPartitioner(getXMLPartitionScanner(), TYPES);
+ // }
+ //
+ // /**
+ // * Return a scanner for creating html partitions.
+ // */
+ // private PHPPartitionScanner getHTMLPartitionScanner() {
+ // if (HTML_PARTITION_SCANNER == null)
+ // HTML_PARTITION_SCANNER = new
+ // PHPPartitionScanner(IPHPPartitionScannerConstants.HTML_FILE);
+ // return HTML_PARTITION_SCANNER;
+ // }
+ // /**
+ // * Return a scanner for creating php partitions.
+ // */
+ // private PHPPartitionScanner getPHPPartitionScanner() {
+ // if (PHP_PARTITION_SCANNER == null)
+ // PHP_PARTITION_SCANNER = new
+ // PHPPartitionScanner(IPHPPartitionScannerConstants.PHP_FILE);
+ // return PHP_PARTITION_SCANNER;
+ // }
+ //
+ // /**
+ // * Return a scanner for creating smarty partitions.
+ // */
+ // private PHPPartitionScanner getSmartyPartitionScanner() {
+ // if (SMARTY_PARTITION_SCANNER == null)
+ // SMARTY_PARTITION_SCANNER = new
+ // PHPPartitionScanner(IPHPPartitionScannerConstants.SMARTY_FILE);
+ // return SMARTY_PARTITION_SCANNER;
+ // }
+ //
+ // /**
+ // * Return a scanner for creating xml partitions.
+ // */
+ // private PHPPartitionScanner getXMLPartitionScanner() {
+ // if (XML_PARTITION_SCANNER == null)
+ // XML_PARTITION_SCANNER = new
+ // PHPPartitionScanner(IPHPPartitionScannerConstants.XML_FILE);
+ // return XML_PARTITION_SCANNER;
+ // }
+
+ // protected void initializeDocument(IDocument document, IEditorInput
+ // editorInput) {
+ // if (document != null) {
+ // JavaTextTools tools = PHPeclipsePlugin.getDefault().getJavaTextTools();
+ // IDocumentPartitioner partitioner = null;
+ // if (editorInput != null && editorInput instanceof FileEditorInput) {
+ // IFile file = (IFile) ((FileEditorInput)
+ // editorInput).getAdapter(IFile.class);
+ // String filename = file.getLocation().toString();
+ // String extension = filename.substring(filename.lastIndexOf("."),
+ // filename.length());
+ // partitioner = tools.createDocumentPartitioner(extension);
+ // } else {
+ // partitioner = tools.createDocumentPartitioner(".php");
+ // }
+ // document.setDocumentPartitioner(partitioner);
+ // partitioner.connect(document);
+ // }
+ // }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doResetDocument(java.lang.Object,
+ * org.eclipse.core.runtime.IProgressMonitor)
+ */
+ // protected void doResetDocument(Object element, IProgressMonitor monitor)
+ // throws CoreException {
+ // if (element == null)
+ // return;
+ //
+ // ElementInfo elementInfo= getElementInfo(element);
+ // if (elementInfo instanceof CompilationUnitInfo) {
+ // CompilationUnitInfo info= (CompilationUnitInfo) elementInfo;
+ //
+ // IDocument document;
+ // IStatus status= null;
+ //
+ // try {
+ //
+ // ICompilationUnit original= (ICompilationUnit)
+ // info.fCopy.getOriginalElement();
+ // IResource resource= original.getResource();
+ // if (resource instanceof IFile) {
+ //
+ // IFile file= (IFile) resource;
+ //
+ // try {
+ // refreshFile(file, monitor);
+ // } catch (CoreException x) {
+ // handleCoreException(x,
+ // PHPEditorMessages.getString("CompilationUnitDocumentProvider.error.resetDocument"));
+ // //$NON-NLS-1$
+ // }
+ //
+ // IFileEditorInput input= new FileEditorInput(file);
+ // document= super.createDocument(input);
+ //
+ // } else {
+ // document= createEmptyDocument();
+ // }
+ //
+ // } catch (CoreException x) {
+ // document= createEmptyDocument();
+ // status= x.getStatus();
+ // }
+ //
+ // fireElementContentAboutToBeReplaced(element);
+ //
+ // removeUnchangedElementListeners(element, info);
+ // info.fDocument.set(document.get());
+ // info.fCanBeSaved= false;
+ // info.fStatus= status;
+ // addUnchangedElementListeners(element, info);
+ //
+ // fireElementContentReplaced(element);
+ // fireElementDirtyStateChanged(element, false);
+ //
+ // } else {
+ // super.doResetDocument(element, monitor);
+ // }
+ // }
+ /*
+ * @see AbstractDocumentProvider#resetDocument(Object)
+ */
+ // public void resetDocument(Object element) throws CoreException {
+ // if (element == null)
+ // return;
+ //
+ // ElementInfo elementInfo = getElementInfo(element);
+ // if (elementInfo instanceof CompilationUnitInfo) {
+ // CompilationUnitInfo info = (CompilationUnitInfo) elementInfo;
+ //
+ // IDocument document;
+ // IStatus status = null;
+ //
+ // try {
+ //
+ // ICompilationUnit original = (ICompilationUnit)
+ // info.fCopy.getOriginalElement();
+ // IResource resource = original.getResource();
+ // if (resource instanceof IFile) {
+ //
+ // IFile file = (IFile) resource;
+ //
+ // try {
+ // refreshFile(file);
+ // } catch (CoreException x) {
+ // handleCoreException(x,
+ // PHPEditorMessages.getString("PHPDocumentProvider.error.resetDocument"));
+ // //$NON-NLS-1$
+ // }
+ //
+ // IFileEditorInput input = new FileEditorInput(file);
+ // document = super.createDocument(input);
+ //
+ // } else {
+ // document = new Document();
+ // }
+ //
+ // } catch (CoreException x) {
+ // document = new Document();
+ // status = x.getStatus();
+ // }
+ //
+ // fireElementContentAboutToBeReplaced(element);
+ //
+ // removeUnchangedElementListeners(element, info);
+ // info.fDocument.set(document.get());
+ // info.fCanBeSaved = false;
+ // info.fStatus = status;
+ // addUnchangedElementListeners(element, info);
+ //
+ // fireElementContentReplaced(element);
+ // fireElementDirtyStateChanged(element, false);
+ //
+ // } else {
+ // super.resetDocument(element);
+ // }
+ // }
+ /**
+ * Saves the content of the given document to the given element. This is
+ * only performed when this provider initiated the save.
+ *
+ * @param monitor
+ * the progress monitor
+ * @param element
+ * the element to which to save
+ * @param document
+ * the document to save
+ * @param overwrite
+ * true
if the save should be enforced
+ */
+ public void saveDocumentContent(IProgressMonitor monitor, Object element,
+ IDocument document, boolean overwrite) throws CoreException {
+ if (!fIsAboutToSave)
+ return;
+ super.saveDocument(monitor, element, document, overwrite);
+ // if (!fIsAboutToSave)
+ // return;
+ //
+ // if (element instanceof IFileEditorInput) {
+ // IFileEditorInput input = (IFileEditorInput) element;
+ // try {
+ // String encoding = getEncoding(element);
+ // if (encoding == null)
+ // encoding = ResourcesPlugin.getEncoding();
+ // InputStream stream = new
+ // ByteArrayInputStream(document.get().getBytes(encoding));
+ // IFile file = input.getFile();
+ // file.setContents(stream, overwrite, true, monitor);
+ // } catch (IOException x) {
+ // IStatus s = new Status(IStatus.ERROR, PHPeclipsePlugin.PLUGIN_ID,
+ // IStatus.OK, x.getMessage(), x);
+ // throw new CoreException(s);
+ // }
+ // }
+ }
+
+ /**
+ * Returns the underlying resource for the given element.
+ *
+ * @param the
+ * element
+ * @return the underlying resource of the given element
+ */
+ // public IResource getUnderlyingResource(Object element) {
+ // if (element instanceof IFileEditorInput) {
+ // IFileEditorInput input = (IFileEditorInput) element;
+ // return input.getFile();
+ // }
+ // return null;
+ // }
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.ICompilationUnitDocumentProvider#getWorkingCopy(java.lang.Object)
+ */
+ public ICompilationUnit getWorkingCopy(Object element) {
+ FileInfo fileInfo = getFileInfo(element);
+ if (fileInfo instanceof CompilationUnitInfo) {
+ CompilationUnitInfo info = (CompilationUnitInfo) fileInfo;
+ return info.fCopy;
+ }
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.ICompilationUnitDocumentProvider#shutdown()
+ */
+ public void shutdown() {
+ WebUI.getDefault().getPreferenceStore()
+ .removePropertyChangeListener(fPropertyListener);
+ Iterator e = getConnectedElementsIterator();
+ while (e.hasNext())
+ disconnect(e.next());
+ }
+
+ /**
+ * Returns the preference whether handling temporary problems is enabled.
+ */
+ protected boolean isHandlingTemporaryProblems() {
+ IPreferenceStore store = WebUI.getDefault()
+ .getPreferenceStore();
+ return store.getBoolean(HANDLE_TEMPORARY_PROBLEMS);
+ }
+
+ /**
+ * Switches the state of problem acceptance according to the value in the
+ * preference store.
+ */
+ protected void enableHandlingTemporaryProblems() {
+ boolean enable = isHandlingTemporaryProblems();
+ for (Iterator iter = getFileInfosIterator(); iter.hasNext();) {
+ FileInfo info = (FileInfo) iter.next();
+ if (info.fModel instanceof IProblemRequestorExtension) {
+ IProblemRequestorExtension extension = (IProblemRequestorExtension) info.fModel;
+ extension.setIsActive(enable);
+ }
+ }
+ }
+
+ /**
+ * Adds a listener that reports changes from all compilation unit annotation
+ * models.
+ */
+ public void addGlobalAnnotationModelListener(
+ IAnnotationModelListener listener) {
+ fGlobalAnnotationModelListener.addListener(listener);
+ }
+
+ /**
+ * Removes the listener.
+ */
+ public void removeGlobalAnnotationModelListener(
+ IAnnotationModelListener listener) {
+ fGlobalAnnotationModelListener.removeListener(listener);
+ }
+
+ /**
+ * Computes the scheduling rule needed to create or modify a resource. If
+ * the resource exists, its modify rule is returned. If it does not, the
+ * resource hierarchy is iterated towards the workspace root to find the
+ * first parent of toCreateOrModify
that exists. Then the
+ * 'create' rule for the last non-existing resource is returned.
+ *
+ * XXX This is a workaround for
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=67601
+ * IResourceRuleFactory.createRule should iterate the hierarchy itself.
+ *
+ *
+ * XXX to be replaced by call to
+ * TextFileDocumentProvider.computeSchedulingRule after 3.0
+ *
+ *
+ * @param toCreateOrModify
+ * the resource to create or modify
+ * @return the minimal scheduling rule needed to modify or create a resource
+ */
+ protected ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) {
+ IResourceRuleFactory factory = ResourcesPlugin.getWorkspace()
+ .getRuleFactory();
+ if (toCreateOrModify.exists()) {
+ return factory.modifyRule(toCreateOrModify);
+ } else {
+ IResource parent = toCreateOrModify;
+ do {
+ toCreateOrModify = parent;
+ parent = toCreateOrModify.getParent();
+ } while (parent != null && !parent.exists());
+
+ return factory.createRule(toCreateOrModify);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java
new file mode 100644
index 0000000..446b848
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java
@@ -0,0 +1,6104 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IImportContainer;
+import net.sourceforge.phpdt.core.IImportDeclaration;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
+import net.sourceforge.phpdt.internal.ui.actions.FoldingActionGroup;
+import net.sourceforge.phpdt.internal.ui.actions.SelectionConverter;
+import net.sourceforge.phpdt.internal.ui.text.CustomSourceInformationControl;
+import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator;
+import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder;
+import net.sourceforge.phpdt.internal.ui.text.JavaWordIterator;
+import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
+import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter;
+import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaExpandHover;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ISelectionListenerWithAST;
+import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
+import net.sourceforge.phpdt.ui.IContextMenuConstants;
+import net.sourceforge.phpdt.ui.JavaUI;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
+import net.sourceforge.phpdt.ui.actions.OpenEditorActionGroup;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.ExternalEditorInput;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.editor.BrowserUtil;
+import net.sourceforge.phpeclipse.webbrowser.views.BrowserView;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+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.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ISelectionValidator;
+import org.eclipse.jface.text.ISynchronizable;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextPresentationListener;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension2;
+import org.eclipse.jface.text.ITextViewerExtension4;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.InformationPresenter;
+import org.eclipse.jface.text.link.LinkedModeModel;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationRulerColumn;
+import org.eclipse.jface.text.source.CompositeRuler;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelExtension;
+import org.eclipse.jface.text.source.IOverviewRuler;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.ISourceViewerExtension2;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.IVerticalRulerColumn;
+import org.eclipse.jface.text.source.OverviewRuler;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BidiSegmentEvent;
+import org.eclipse.swt.custom.BidiSegmentListener;
+import org.eclipse.swt.custom.ST;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionContext;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.editors.text.DefaultEncodingSupport;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.IEncodingSupport;
+import org.eclipse.ui.ide.FileStoreEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.part.IShowInSource;
+import org.eclipse.ui.part.IShowInTargetList;
+import org.eclipse.ui.part.ShowInContext;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.IEditorStatusLine;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+import org.eclipse.ui.texteditor.TextEditorAction;
+import org.eclipse.ui.texteditor.TextNavigationAction;
+import org.eclipse.ui.texteditor.TextOperationAction;
+import org.eclipse.ui.views.contentoutline.ContentOutline;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.eclipse.ui.views.tasklist.TaskList;
+
+/**
+ * PHP specific text editor.
+ */
+public abstract class PHPEditor extends AbstractDecoratedTextEditor implements
+ IViewPartInputProvider, IShowInTargetList, IShowInSource {
+ // extends StatusTextEditor implements IViewPartInputProvider { // extends
+ // TextEditor {
+
+ /**
+ * Internal implementation class for a change listener.
+ *
+ * @since 3.0
+ */
+ protected abstract class AbstractSelectionChangedListener implements
+ ISelectionChangedListener {
+
+ /**
+ * Installs this selection changed listener with the given selection
+ * provider. If the selection provider is a post selection provider,
+ * post selection changed events are the preferred choice, otherwise
+ * normal selection changed events are requested.
+ *
+ * @param selectionProvider
+ */
+ public void install(ISelectionProvider selectionProvider) {
+ if (selectionProvider == null)
+ return;
+
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+ provider.addPostSelectionChangedListener(this);
+ } else {
+ selectionProvider.addSelectionChangedListener(this);
+ }
+ }
+
+ /**
+ * Removes this selection changed listener from the given selection
+ * provider.
+ *
+ * @param selectionProvider
+ * the selection provider
+ */
+ public void uninstall(ISelectionProvider selectionProvider) {
+ if (selectionProvider == null)
+ return;
+
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+ provider.removePostSelectionChangedListener(this);
+ } else {
+ selectionProvider.removeSelectionChangedListener(this);
+ }
+ }
+ }
+
+ /**
+ * Updates the Java outline page selection and this editor's range
+ * indicator.
+ *
+ * @since 3.0
+ */
+ private class EditorSelectionChangedListener extends
+ AbstractSelectionChangedListener {
+
+ /*
+ * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ // XXX: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=56161
+ PHPEditor.this.selectionChanged();
+ }
+ }
+
+ /**
+ * "Smart" runnable for updating the outline page's selection.
+ */
+ // class OutlinePageSelectionUpdater implements Runnable {
+ //
+ // /** Has the runnable already been posted? */
+ // private boolean fPosted = false;
+ //
+ // public OutlinePageSelectionUpdater() {
+ // }
+ //
+ // /*
+ // * @see Runnable#run()
+ // */
+ // public void run() {
+ // synchronizeOutlinePageSelection();
+ // fPosted = false;
+ // }
+ //
+ // /**
+ // * Posts this runnable into the event queue.
+ // */
+ // public void post() {
+ // if (fPosted)
+ // return;
+ //
+ // Shell shell = getSite().getShell();
+ // if (shell != null & !shell.isDisposed()) {
+ // fPosted = true;
+ // shell.getDisplay().asyncExec(this);
+ // }
+ // }
+ // };
+ class SelectionChangedListener implements ISelectionChangedListener {
+ public void selectionChanged(SelectionChangedEvent event) {
+ doSelectionChanged(event);
+ }
+ };
+
+ /**
+ * Adapts an options {@link java.util.Map}to
+ * {@link org.eclipse.jface.preference.IPreferenceStore}.
+ *
+ * This preference store is read-only i.e. write access throws an
+ * {@link java.lang.UnsupportedOperationException}.
+ *
+ *
+ * @since 3.0
+ */
+ private static class OptionsAdapter implements IPreferenceStore {
+
+ /**
+ * A property change event filter.
+ */
+ public interface IPropertyChangeEventFilter {
+
+ /**
+ * Should the given event be filtered?
+ *
+ * @param event
+ * The property change event.
+ * @return true
iff the given event should be
+ * filtered.
+ */
+ public boolean isFiltered(PropertyChangeEvent event);
+
+ }
+
+ /**
+ * Property change listener. Listens for events in the options Map and
+ * fires a {@link org.eclipse.jface.util.PropertyChangeEvent}on this
+ * adapter with arguments from the received event.
+ */
+ private class PropertyChangeListener implements IPropertyChangeListener {
+
+ /**
+ * {@inheritDoc}
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (getFilter().isFiltered(event))
+ return;
+
+ if (event.getNewValue() == null)
+ fOptions.remove(event.getProperty());
+ else
+ fOptions.put(event.getProperty(), event.getNewValue());
+
+ firePropertyChangeEvent(event.getProperty(), event
+ .getOldValue(), event.getNewValue());
+ }
+ }
+
+ /** Listeners on this adapter */
+ private ListenerList fListeners = new ListenerList();
+
+ /** Listener on the adapted options Map */
+ private IPropertyChangeListener fListener = new PropertyChangeListener();
+
+ /** Adapted options Map */
+ private Map fOptions;
+
+ /** Preference store through which events are received. */
+ private IPreferenceStore fMockupPreferenceStore;
+
+ /** Property event filter. */
+ private IPropertyChangeEventFilter fFilter;
+
+ /**
+ * Initialize with the given options.
+ *
+ * @param options
+ * The options to wrap
+ * @param mockupPreferenceStore
+ * the mock-up preference store
+ * @param filter
+ * the property change filter
+ */
+ public OptionsAdapter(Map options,
+ IPreferenceStore mockupPreferenceStore,
+ IPropertyChangeEventFilter filter) {
+ fMockupPreferenceStore = mockupPreferenceStore;
+ fOptions = options;
+ setFilter(filter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addPropertyChangeListener(IPropertyChangeListener listener) {
+ if (fListeners.size() == 0)
+ fMockupPreferenceStore.addPropertyChangeListener(fListener);
+ fListeners.add(listener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removePropertyChangeListener(
+ IPropertyChangeListener listener) {
+ fListeners.remove(listener);
+ if (fListeners.size() == 0)
+ fMockupPreferenceStore.removePropertyChangeListener(fListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean contains(String name) {
+ return fOptions.containsKey(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void firePropertyChangeEvent(String name, Object oldValue,
+ Object newValue) {
+ PropertyChangeEvent event = new PropertyChangeEvent(this, name,
+ oldValue, newValue);
+ Object[] listeners = fListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++)
+ ((IPropertyChangeListener) listeners[i]).propertyChange(event);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean getBoolean(String name) {
+ boolean value = BOOLEAN_DEFAULT_DEFAULT;
+ String s = (String) fOptions.get(name);
+ if (s != null)
+ value = s.equals(TRUE);
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean getDefaultBoolean(String name) {
+ return BOOLEAN_DEFAULT_DEFAULT;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getDefaultDouble(String name) {
+ return DOUBLE_DEFAULT_DEFAULT;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public float getDefaultFloat(String name) {
+ return FLOAT_DEFAULT_DEFAULT;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDefaultInt(String name) {
+ return INT_DEFAULT_DEFAULT;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getDefaultLong(String name) {
+ return LONG_DEFAULT_DEFAULT;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDefaultString(String name) {
+ return STRING_DEFAULT_DEFAULT;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getDouble(String name) {
+ double value = DOUBLE_DEFAULT_DEFAULT;
+ String s = (String) fOptions.get(name);
+ if (s != null) {
+ try {
+ value = new Double(s).doubleValue();
+ } catch (NumberFormatException e) {
+ }
+ }
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public float getFloat(String name) {
+ float value = FLOAT_DEFAULT_DEFAULT;
+ String s = (String) fOptions.get(name);
+ if (s != null) {
+ try {
+ value = new Float(s).floatValue();
+ } catch (NumberFormatException e) {
+ }
+ }
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getInt(String name) {
+ int value = INT_DEFAULT_DEFAULT;
+ String s = (String) fOptions.get(name);
+ if (s != null) {
+ try {
+ value = new Integer(s).intValue();
+ } catch (NumberFormatException e) {
+ }
+ }
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLong(String name) {
+ long value = LONG_DEFAULT_DEFAULT;
+ String s = (String) fOptions.get(name);
+ if (s != null) {
+ try {
+ value = new Long(s).longValue();
+ } catch (NumberFormatException e) {
+ }
+ }
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getString(String name) {
+ String value = (String) fOptions.get(name);
+ if (value == null)
+ value = STRING_DEFAULT_DEFAULT;
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDefault(String name) {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean needsSaving() {
+ return !fOptions.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void putValue(String name, String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, double value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, float value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, long value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, String defaultObject) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDefault(String name, boolean value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setToDefault(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, double value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, float value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, long value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setValue(String name, boolean value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the adapted options Map.
+ *
+ * @return Returns the adapted options Map.
+ */
+ public Map getOptions() {
+ return fOptions;
+ }
+
+ /**
+ * Returns the mock-up preference store, events are received through
+ * this preference store.
+ *
+ * @return Returns the mock-up preference store.
+ */
+ public IPreferenceStore getMockupPreferenceStore() {
+ return fMockupPreferenceStore;
+ }
+
+ /**
+ * Set the event filter to the given filter.
+ *
+ * @param filter
+ * The new filter.
+ */
+ public void setFilter(IPropertyChangeEventFilter filter) {
+ fFilter = filter;
+ }
+
+ /**
+ * Returns the event filter.
+ *
+ * @return The event filter.
+ */
+ public IPropertyChangeEventFilter getFilter() {
+ return fFilter;
+ }
+ }
+
+ /*
+ * Link mode.
+ */
+ // class MouseClickListener implements KeyListener, MouseListener,
+ // MouseMoveListener, FocusListener, PaintListener,
+ // IPropertyChangeListener, IDocumentListener, ITextInputListener {
+ //
+ // /** The session is active. */
+ // private boolean fActive;
+ //
+ // /** The currently active style range. */
+ // private IRegion fActiveRegion;
+ //
+ // /** The currently active style range as position. */
+ // private Position fRememberedPosition;
+ //
+ // /** The hand cursor. */
+ // private Cursor fCursor;
+ //
+ // /** The link color. */
+ // private Color fColor;
+ //
+ // /** The key modifier mask. */
+ // private int fKeyModifierMask;
+ //
+ // public void deactivate() {
+ // deactivate(false);
+ // }
+ //
+ // public void deactivate(boolean redrawAll) {
+ // if (!fActive)
+ // return;
+ //
+ // repairRepresentation(redrawAll);
+ // fActive = false;
+ // }
+ //
+ // public void install() {
+ //
+ // ISourceViewer sourceViewer = getSourceViewer();
+ // if (sourceViewer == null)
+ // return;
+ //
+ // StyledText text = sourceViewer.getTextWidget();
+ // if (text == null || text.isDisposed())
+ // return;
+ //
+ // updateColor(sourceViewer);
+ //
+ // sourceViewer.addTextInputListener(this);
+ //
+ // IDocument document = sourceViewer.getDocument();
+ // if (document != null)
+ // document.addDocumentListener(this);
+ //
+ // text.addKeyListener(this);
+ // text.addMouseListener(this);
+ // text.addMouseMoveListener(this);
+ // text.addFocusListener(this);
+ // text.addPaintListener(this);
+ //
+ // updateKeyModifierMask();
+ //
+ // IPreferenceStore preferenceStore = getPreferenceStore();
+ // preferenceStore.addPropertyChangeListener(this);
+ // }
+ //
+ // private void updateKeyModifierMask() {
+ // String modifiers =
+ // getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER);
+ // fKeyModifierMask = computeStateMask(modifiers);
+ // if (fKeyModifierMask == -1) {
+ // // Fallback to stored state mask
+ // fKeyModifierMask =
+ // getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
+ // }
+ // ;
+ // }
+ //
+ // private int computeStateMask(String modifiers) {
+ // if (modifiers == null)
+ // return -1;
+ //
+ // if (modifiers.length() == 0)
+ // return SWT.NONE;
+ //
+ // int stateMask = 0;
+ // StringTokenizer modifierTokenizer = new StringTokenizer(modifiers,
+ // ",;.:+-*
+ // "); //$NON-NLS-1$
+ // while (modifierTokenizer.hasMoreTokens()) {
+ // int modifier =
+ // EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
+ // if (modifier == 0 || (stateMask & modifier) == modifier)
+ // return -1;
+ // stateMask = stateMask | modifier;
+ // }
+ // return stateMask;
+ // }
+ //
+ // public void uninstall() {
+ //
+ // if (fColor != null) {
+ // fColor.dispose();
+ // fColor = null;
+ // }
+ //
+ // if (fCursor != null) {
+ // fCursor.dispose();
+ // fCursor = null;
+ // }
+ //
+ // ISourceViewer sourceViewer = getSourceViewer();
+ // if (sourceViewer == null)
+ // return;
+ //
+ // sourceViewer.removeTextInputListener(this);
+ //
+ // IDocument document = sourceViewer.getDocument();
+ // if (document != null)
+ // document.removeDocumentListener(this);
+ //
+ // IPreferenceStore preferenceStore = getPreferenceStore();
+ // if (preferenceStore != null)
+ // preferenceStore.removePropertyChangeListener(this);
+ //
+ // StyledText text = sourceViewer.getTextWidget();
+ // if (text == null || text.isDisposed())
+ // return;
+ //
+ // text.removeKeyListener(this);
+ // text.removeMouseListener(this);
+ // text.removeMouseMoveListener(this);
+ // text.removeFocusListener(this);
+ // text.removePaintListener(this);
+ // }
+ //
+ // /*
+ // * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ // */
+ // public void propertyChange(PropertyChangeEvent event) {
+ // if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
+ // ISourceViewer viewer = getSourceViewer();
+ // if (viewer != null)
+ // updateColor(viewer);
+ // } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
+ // updateKeyModifierMask();
+ // }
+ // }
+ //
+ // private void updateColor(ISourceViewer viewer) {
+ // if (fColor != null)
+ // fColor.dispose();
+ //
+ // StyledText text = viewer.getTextWidget();
+ // if (text == null || text.isDisposed())
+ // return;
+ //
+ // Display display = text.getDisplay();
+ // fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR,
+ // display);
+ // }
+ //
+ // /**
+ // * Creates a color from the information stored in the given preference
+ // store. Returns null
if there is no such
+ // * information available.
+ // */
+ // private Color createColor(IPreferenceStore store, String key, Display
+ // display) {
+ //
+ // RGB rgb = null;
+ //
+ // if (store.contains(key)) {
+ //
+ // if (store.isDefault(key))
+ // rgb = PreferenceConverter.getDefaultColor(store, key);
+ // else
+ // rgb = PreferenceConverter.getColor(store, key);
+ //
+ // if (rgb != null)
+ // return new Color(display, rgb);
+ // }
+ //
+ // return null;
+ // }
+ //
+ // private void repairRepresentation() {
+ // repairRepresentation(false);
+ // }
+ //
+ // private void repairRepresentation(boolean redrawAll) {
+ //
+ // if (fActiveRegion == null)
+ // return;
+ //
+ // ISourceViewer viewer = getSourceViewer();
+ // if (viewer != null) {
+ // resetCursor(viewer);
+ //
+ // int offset = fActiveRegion.getOffset();
+ // int length = fActiveRegion.getLength();
+ //
+ // // remove style
+ // if (!redrawAll && viewer instanceof ITextViewerExtension2)
+ // ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset,
+ // length);
+ // else
+ // viewer.invalidateTextPresentation();
+ //
+ // // remove underline
+ // if (viewer instanceof ITextViewerExtension3) {
+ // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+ // offset = extension.modelOffset2WidgetOffset(offset);
+ // } else {
+ // offset -= viewer.getVisibleRegion().getOffset();
+ // }
+ //
+ // StyledText text = viewer.getTextWidget();
+ // try {
+ // text.redrawRange(offset, length, true);
+ // } catch (IllegalArgumentException x) {
+ // PHPeclipsePlugin.log(x);
+ // }
+ // }
+ //
+ // fActiveRegion = null;
+ // }
+ //
+ // // will eventually be replaced by a method provided by jdt.core
+ // private IRegion selectWord(IDocument document, int anchor) {
+ //
+ // try {
+ // int offset = anchor;
+ // char c;
+ //
+ // while (offset >= 0) {
+ // c = document.getChar(offset);
+ // if (!Scanner.isPHPIdentifierPart(c))
+ // break;
+ // --offset;
+ // }
+ //
+ // int start = offset;
+ //
+ // offset = anchor;
+ // int length = document.getLength();
+ //
+ // while (offset < length) {
+ // c = document.getChar(offset);
+ // if (!Scanner.isPHPIdentifierPart(c))
+ // break;
+ // ++offset;
+ // }
+ //
+ // int end = offset;
+ //
+ // if (start == end)
+ // return new Region(start, 0);
+ // else
+ // return new Region(start + 1, end - start - 1);
+ //
+ // } catch (BadLocationException x) {
+ // return null;
+ // }
+ // }
+ //
+ // IRegion getCurrentTextRegion(ISourceViewer viewer) {
+ //
+ // int offset = getCurrentTextOffset(viewer);
+ // if (offset == -1)
+ // return null;
+ //
+ // return null;
+ // // IJavaElement input= SelectionConverter.getInput(PHPEditor.this);
+ // // if (input == null)
+ // // return null;
+ // //
+ // // try {
+ // //
+ // // IJavaElement[] elements= null;
+ // // synchronized (input) {
+ // // elements= ((ICodeAssist) input).codeSelect(offset, 0);
+ // // }
+ // //
+ // // if (elements == null || elements.length == 0)
+ // // return null;
+ // //
+ // // return selectWord(viewer.getDocument(), offset);
+ // //
+ // // } catch (JavaModelException e) {
+ // // return null;
+ // // }
+ // }
+ //
+ // private int getCurrentTextOffset(ISourceViewer viewer) {
+ //
+ // try {
+ // StyledText text = viewer.getTextWidget();
+ // if (text == null || text.isDisposed())
+ // return -1;
+ //
+ // Display display = text.getDisplay();
+ // Point absolutePosition = display.getCursorLocation();
+ // Point relativePosition = text.toControl(absolutePosition);
+ //
+ // int widgetOffset = text.getOffsetAtLocation(relativePosition);
+ // if (viewer instanceof ITextViewerExtension3) {
+ // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+ // return extension.widgetOffset2ModelOffset(widgetOffset);
+ // } else {
+ // return widgetOffset + viewer.getVisibleRegion().getOffset();
+ // }
+ //
+ // } catch (IllegalArgumentException e) {
+ // return -1;
+ // }
+ // }
+ //
+ // private void highlightRegion(ISourceViewer viewer, IRegion region) {
+ //
+ // if (region.equals(fActiveRegion))
+ // return;
+ //
+ // repairRepresentation();
+ //
+ // StyledText text = viewer.getTextWidget();
+ // if (text == null || text.isDisposed())
+ // return;
+ //
+ // // highlight region
+ // int offset = 0;
+ // int length = 0;
+ //
+ // if (viewer instanceof ITextViewerExtension3) {
+ // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+ // IRegion widgetRange = extension.modelRange2WidgetRange(region);
+ // if (widgetRange == null)
+ // return;
+ //
+ // offset = widgetRange.getOffset();
+ // length = widgetRange.getLength();
+ //
+ // } else {
+ // offset = region.getOffset() - viewer.getVisibleRegion().getOffset();
+ // length = region.getLength();
+ // }
+ //
+ // StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset);
+ // Color foregroundColor = fColor;
+ // Color backgroundColor = oldStyleRange == null ? text.getBackground() :
+ // oldStyleRange.background;
+ // StyleRange styleRange = new StyleRange(offset, length, foregroundColor,
+ // backgroundColor);
+ // text.setStyleRange(styleRange);
+ //
+ // // underline
+ // text.redrawRange(offset, length, true);
+ //
+ // fActiveRegion = region;
+ // }
+ //
+ // private void activateCursor(ISourceViewer viewer) {
+ // StyledText text = viewer.getTextWidget();
+ // if (text == null || text.isDisposed())
+ // return;
+ // Display display = text.getDisplay();
+ // if (fCursor == null)
+ // fCursor = new Cursor(display, SWT.CURSOR_HAND);
+ // text.setCursor(fCursor);
+ // }
+ //
+ // private void resetCursor(ISourceViewer viewer) {
+ // StyledText text = viewer.getTextWidget();
+ // if (text != null && !text.isDisposed())
+ // text.setCursor(null);
+ //
+ // if (fCursor != null) {
+ // fCursor.dispose();
+ // fCursor = null;
+ // }
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
+ // */
+ // public void keyPressed(KeyEvent event) {
+ //
+ // if (fActive) {
+ // deactivate();
+ // return;
+ // }
+ //
+ // if (event.keyCode != fKeyModifierMask) {
+ // deactivate();
+ // return;
+ // }
+ //
+ // fActive = true;
+ //
+ // // removed for #25871
+ // //
+ // // ISourceViewer viewer= getSourceViewer();
+ // // if (viewer == null)
+ // // return;
+ // //
+ // // IRegion region= getCurrentTextRegion(viewer);
+ // // if (region == null)
+ // // return;
+ // //
+ // // highlightRegion(viewer, region);
+ // // activateCursor(viewer);
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
+ // */
+ // public void keyReleased(KeyEvent event) {
+ //
+ // if (!fActive)
+ // return;
+ //
+ // deactivate();
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+ // */
+ // public void mouseDoubleClick(MouseEvent e) {
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+ // */
+ // public void mouseDown(MouseEvent event) {
+ //
+ // if (!fActive)
+ // return;
+ //
+ // if (event.stateMask != fKeyModifierMask) {
+ // deactivate();
+ // return;
+ // }
+ //
+ // if (event.button != 1) {
+ // deactivate();
+ // return;
+ // }
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+ // */
+ // public void mouseUp(MouseEvent e) {
+ //
+ // if (!fActive)
+ // return;
+ //
+ // if (e.button != 1) {
+ // deactivate();
+ // return;
+ // }
+ //
+ // boolean wasActive = fCursor != null;
+ //
+ // deactivate();
+ //
+ // if (wasActive) {
+ // IAction action = getAction("OpenEditor"); //$NON-NLS-1$
+ // if (action != null)
+ // action.run();
+ // }
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
+ // */
+ // public void mouseMove(MouseEvent event) {
+ //
+ // if (event.widget instanceof Control && !((Control)
+ // event.widget).isFocusControl()) {
+ // deactivate();
+ // return;
+ // }
+ //
+ // if (!fActive) {
+ // if (event.stateMask != fKeyModifierMask)
+ // return;
+ // // modifier was already pressed
+ // fActive = true;
+ // }
+ //
+ // ISourceViewer viewer = getSourceViewer();
+ // if (viewer == null) {
+ // deactivate();
+ // return;
+ // }
+ //
+ // StyledText text = viewer.getTextWidget();
+ // if (text == null || text.isDisposed()) {
+ // deactivate();
+ // return;
+ // }
+ //
+ // if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() !=
+ // 0)
+ // {
+ // deactivate();
+ // return;
+ // }
+ //
+ // IRegion region = getCurrentTextRegion(viewer);
+ // if (region == null || region.getLength() == 0) {
+ // repairRepresentation();
+ // return;
+ // }
+ //
+ // highlightRegion(viewer, region);
+ // activateCursor(viewer);
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
+ // */
+ // public void focusGained(FocusEvent e) {
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+ // */
+ // public void focusLost(FocusEvent event) {
+ // deactivate();
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+ // */
+ // public void documentAboutToBeChanged(DocumentEvent event) {
+ // if (fActive && fActiveRegion != null) {
+ // fRememberedPosition = new Position(fActiveRegion.getOffset(),
+ // fActiveRegion.getLength());
+ // try {
+ // event.getDocument().addPosition(fRememberedPosition);
+ // } catch (BadLocationException x) {
+ // fRememberedPosition = null;
+ // }
+ // }
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+ // */
+ // public void documentChanged(DocumentEvent event) {
+ // if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) {
+ // event.getDocument().removePosition(fRememberedPosition);
+ // fActiveRegion = new Region(fRememberedPosition.getOffset(),
+ // fRememberedPosition.getLength());
+ // }
+ // fRememberedPosition = null;
+ //
+ // ISourceViewer viewer = getSourceViewer();
+ // if (viewer != null) {
+ // StyledText widget = viewer.getTextWidget();
+ // if (widget != null && !widget.isDisposed()) {
+ // widget.getDisplay().asyncExec(new Runnable() {
+ // public void run() {
+ // deactivate();
+ // }
+ // });
+ // }
+ // }
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
+ // * org.eclipse.jface.text.IDocument)
+ // */
+ // public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument
+ // newInput) {
+ // if (oldInput == null)
+ // return;
+ // deactivate();
+ // oldInput.removeDocumentListener(this);
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
+ // * org.eclipse.jface.text.IDocument)
+ // */
+ // public void inputDocumentChanged(IDocument oldInput, IDocument newInput)
+ // {
+ // if (newInput == null)
+ // return;
+ // newInput.addDocumentListener(this);
+ // }
+ //
+ // /*
+ // * @see PaintListener#paintControl(PaintEvent)
+ // */
+ // public void paintControl(PaintEvent event) {
+ // if (fActiveRegion == null)
+ // return;
+ //
+ // ISourceViewer viewer = getSourceViewer();
+ // if (viewer == null)
+ // return;
+ //
+ // StyledText text = viewer.getTextWidget();
+ // if (text == null || text.isDisposed())
+ // return;
+ //
+ // int offset = 0;
+ // int length = 0;
+ //
+ // if (viewer instanceof ITextViewerExtension3) {
+ //
+ // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+ // IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset,
+ // length));
+ // if (widgetRange == null)
+ // return;
+ //
+ // offset = widgetRange.getOffset();
+ // length = widgetRange.getLength();
+ //
+ // } else {
+ //
+ // IRegion region = viewer.getVisibleRegion();
+ // if (!includes(region, fActiveRegion))
+ // return;
+ //
+ // offset = fActiveRegion.getOffset() - region.getOffset();
+ // length = fActiveRegion.getLength();
+ // }
+ //
+ // // support for bidi
+ // Point minLocation = getMinimumLocation(text, offset, length);
+ // Point maxLocation = getMaximumLocation(text, offset, length);
+ //
+ // int x1 = minLocation.x;
+ // int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
+ // int y = minLocation.y + text.getLineHeight() - 1;
+ //
+ // GC gc = event.gc;
+ // if (fColor != null && !fColor.isDisposed())
+ // gc.setForeground(fColor);
+ // gc.drawLine(x1, y, x2, y);
+ // }
+ //
+ // private boolean includes(IRegion region, IRegion position) {
+ // return position.getOffset() >= region.getOffset()
+ // && position.getOffset() + position.getLength() <= region.getOffset() +
+ // region.getLength();
+ // }
+ //
+ // private Point getMinimumLocation(StyledText text, int offset, int length)
+ // {
+ // Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ //
+ // for (int i = 0; i <= length; i++) {
+ // Point location = text.getLocationAtOffset(offset + i);
+ //
+ // if (location.x < minLocation.x)
+ // minLocation.x = location.x;
+ // if (location.y < minLocation.y)
+ // minLocation.y = location.y;
+ // }
+ //
+ // return minLocation;
+ // }
+ //
+ // private Point getMaximumLocation(StyledText text, int offset, int length)
+ // {
+ // Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
+ //
+ // for (int i = 0; i <= length; i++) {
+ // Point location = text.getLocationAtOffset(offset + i);
+ //
+ // if (location.x > maxLocation.x)
+ // maxLocation.x = location.x;
+ // if (location.y > maxLocation.y)
+ // maxLocation.y = location.y;
+ // }
+ //
+ // return maxLocation;
+ // }
+ // };
+ /*
+ * Link mode.
+ */
+ class MouseClickListener implements KeyListener, MouseListener,
+ MouseMoveListener, FocusListener, PaintListener,
+ IPropertyChangeListener, IDocumentListener, ITextInputListener,
+ ITextPresentationListener {
+
+ /** The session is active. */
+ private boolean fActive;
+
+ /** The currently active style range. */
+ private IRegion fActiveRegion;
+
+ /** The currently active style range as position. */
+ private Position fRememberedPosition;
+
+ /** The hand cursor. */
+ private Cursor fCursor;
+
+ /** The link color. */
+ private Color fColor;
+
+ /** The key modifier mask. */
+ private int fKeyModifierMask;
+
+ public void deactivate() {
+ deactivate(false);
+ }
+
+ public void deactivate(boolean redrawAll) {
+ if (!fActive)
+ return;
+
+ repairRepresentation(redrawAll);
+ fActive = false;
+ }
+
+ public void install() {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null)
+ return;
+
+ StyledText text = sourceViewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+
+ updateColor(sourceViewer);
+
+ sourceViewer.addTextInputListener(this);
+
+ IDocument document = sourceViewer.getDocument();
+ if (document != null)
+ document.addDocumentListener(this);
+
+ text.addKeyListener(this);
+ text.addMouseListener(this);
+ text.addMouseMoveListener(this);
+ text.addFocusListener(this);
+ text.addPaintListener(this);
+
+ ((ITextViewerExtension4) sourceViewer)
+ .addTextPresentationListener(this);
+
+ updateKeyModifierMask();
+
+ IPreferenceStore preferenceStore = getPreferenceStore();
+ preferenceStore.addPropertyChangeListener(this);
+ }
+
+ private void updateKeyModifierMask() {
+ String modifiers = getPreferenceStore().getString(
+ BROWSER_LIKE_LINKS_KEY_MODIFIER);
+ fKeyModifierMask = computeStateMask(modifiers);
+ if (fKeyModifierMask == -1) {
+ // Fall back to stored state mask
+ fKeyModifierMask = getPreferenceStore().getInt(
+ BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
+ }
+ }
+
+ private int computeStateMask(String modifiers) {
+ if (modifiers == null)
+ return -1;
+
+ if (modifiers.length() == 0)
+ return SWT.NONE;
+
+ int stateMask = 0;
+ StringTokenizer modifierTokenizer = new StringTokenizer(modifiers,
+ ",;.:+-* "); //$NON-NLS-1$
+ while (modifierTokenizer.hasMoreTokens()) {
+ int modifier = EditorUtility
+ .findLocalizedModifier(modifierTokenizer.nextToken());
+ if (modifier == 0 || (stateMask & modifier) == modifier)
+ return -1;
+ stateMask = stateMask | modifier;
+ }
+ return stateMask;
+ }
+
+ public void uninstall() {
+
+ if (fColor != null) {
+ fColor.dispose();
+ fColor = null;
+ }
+
+ if (fCursor != null) {
+ fCursor.dispose();
+ fCursor = null;
+ }
+
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer != null)
+ sourceViewer.removeTextInputListener(this);
+
+ IDocumentProvider documentProvider = getDocumentProvider();
+ if (documentProvider != null) {
+ IDocument document = documentProvider
+ .getDocument(getEditorInput());
+ if (document != null)
+ document.removeDocumentListener(this);
+ }
+
+ IPreferenceStore preferenceStore = getPreferenceStore();
+ if (preferenceStore != null)
+ preferenceStore.removePropertyChangeListener(this);
+
+ if (sourceViewer == null)
+ return;
+
+ StyledText text = sourceViewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+
+ text.removeKeyListener(this);
+ text.removeMouseListener(this);
+ text.removeMouseMoveListener(this);
+ text.removeFocusListener(this);
+ text.removePaintListener(this);
+
+ ((ITextViewerExtension4) sourceViewer)
+ .removeTextPresentationListener(this);
+ }
+
+ /*
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer != null)
+ updateColor(viewer);
+ } else if (event.getProperty().equals(
+ BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
+ updateKeyModifierMask();
+ }
+ }
+
+ private void updateColor(ISourceViewer viewer) {
+ if (fColor != null)
+ fColor.dispose();
+
+ StyledText text = viewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+
+ Display display = text.getDisplay();
+ fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR,
+ display);
+ }
+
+ /**
+ * Creates a color from the information stored in the given preference
+ * store.
+ *
+ * @param store
+ * the preference store
+ * @param key
+ * the key
+ * @param display
+ * the display
+ * @return the color or null
if there is no such
+ * information available
+ */
+ private Color createColor(IPreferenceStore store, String key,
+ Display display) {
+
+ RGB rgb = null;
+
+ if (store.contains(key)) {
+
+ if (store.isDefault(key))
+ rgb = PreferenceConverter.getDefaultColor(store, key);
+ else
+ rgb = PreferenceConverter.getColor(store, key);
+
+ if (rgb != null)
+ return new Color(display, rgb);
+ }
+
+ return null;
+ }
+
+ private void repairRepresentation() {
+ repairRepresentation(false);
+ }
+
+ private void repairRepresentation(boolean redrawAll) {
+
+ if (fActiveRegion == null)
+ return;
+
+ int offset = fActiveRegion.getOffset();
+ int length = fActiveRegion.getLength();
+ fActiveRegion = null;
+
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer != null) {
+
+ resetCursor(viewer);
+
+ // Invalidate ==> remove applied text presentation
+ if (!redrawAll && viewer instanceof ITextViewerExtension2)
+ ((ITextViewerExtension2) viewer)
+ .invalidateTextPresentation(offset, length);
+ else
+ viewer.invalidateTextPresentation();
+
+ // Remove underline
+ if (viewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+ offset = extension.modelOffset2WidgetOffset(offset);
+ } else {
+ offset -= viewer.getVisibleRegion().getOffset();
+ }
+ try {
+ StyledText text = viewer.getTextWidget();
+
+ text.redrawRange(offset, length, false);
+ } catch (IllegalArgumentException x) {
+ // JavaPlugin.log(x);
+ }
+ }
+ }
+
+ // will eventually be replaced by a method provided by jdt.core
+ private IRegion selectWord(IDocument document, int anchor) {
+
+ try {
+ int offset = anchor;
+ char c;
+
+ while (offset >= 0) {
+ c = document.getChar(offset);
+ if (!Scanner.isPHPIdentifierPart(c) && c != '$')
+ break;
+ --offset;
+ }
+
+ int start = offset;
+
+ offset = anchor;
+ int length = document.getLength();
+
+ while (offset < length) {
+ c = document.getChar(offset);
+ if (!Scanner.isPHPIdentifierPart(c) && c != '$')
+ break;
+ ++offset;
+ }
+
+ int end = offset;
+
+ if (start == end)
+ return new Region(start, 0);
+ else
+ return new Region(start + 1, end - start - 1);
+
+ } catch (BadLocationException x) {
+ return null;
+ }
+ }
+
+ IRegion getCurrentTextRegion(ISourceViewer viewer) {
+
+ int offset = getCurrentTextOffset(viewer);
+ if (offset == -1)
+ return null;
+
+ IJavaElement input = SelectionConverter.getInput(PHPEditor.this);
+ if (input == null)
+ return null;
+
+ // try {
+
+ // IJavaElement[] elements= null;
+ // synchronized (input) {
+ // elements= ((ICodeAssist) input).codeSelect(offset, 0);
+ // }
+ //
+ // if (elements == null || elements.length == 0)
+ // return null;
+
+ return selectWord(viewer.getDocument(), offset);
+
+ // } catch (JavaModelException e) {
+ // return null;
+ // }
+ }
+
+ private int getCurrentTextOffset(ISourceViewer viewer) {
+
+ try {
+ StyledText text = viewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return -1;
+
+ Display display = text.getDisplay();
+ Point absolutePosition = display.getCursorLocation();
+ Point relativePosition = text.toControl(absolutePosition);
+
+ int widgetOffset = text.getOffsetAtLocation(relativePosition);
+ if (viewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+ return extension.widgetOffset2ModelOffset(widgetOffset);
+ } else {
+ return widgetOffset + viewer.getVisibleRegion().getOffset();
+ }
+
+ } catch (IllegalArgumentException e) {
+ return -1;
+ }
+ }
+
+ public void applyTextPresentation(TextPresentation textPresentation) {
+ if (fActiveRegion == null)
+ return;
+ IRegion region = textPresentation.getExtent();
+ if (fActiveRegion.getOffset() + fActiveRegion.getLength() >= region
+ .getOffset()
+ && region.getOffset() + region.getLength() > fActiveRegion
+ .getOffset())
+ textPresentation.mergeStyleRange(new StyleRange(fActiveRegion
+ .getOffset(), fActiveRegion.getLength(), fColor, null));
+ }
+
+ private void highlightRegion(ISourceViewer viewer, IRegion region) {
+
+ if (region.equals(fActiveRegion))
+ return;
+
+ repairRepresentation();
+
+ StyledText text = viewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+
+ // Underline
+ int offset = 0;
+ int length = 0;
+ if (viewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+ IRegion widgetRange = extension.modelRange2WidgetRange(region);
+ if (widgetRange == null)
+ return;
+
+ offset = widgetRange.getOffset();
+ length = widgetRange.getLength();
+
+ } else {
+ offset = region.getOffset()
+ - viewer.getVisibleRegion().getOffset();
+ length = region.getLength();
+ }
+ text.redrawRange(offset, length, false);
+
+ // Invalidate region ==> apply text presentation
+ fActiveRegion = region;
+ if (viewer instanceof ITextViewerExtension2)
+ ((ITextViewerExtension2) viewer).invalidateTextPresentation(
+ region.getOffset(), region.getLength());
+ else
+ viewer.invalidateTextPresentation();
+ }
+
+ private void activateCursor(ISourceViewer viewer) {
+ StyledText text = viewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+ Display display = text.getDisplay();
+ if (fCursor == null)
+ fCursor = new Cursor(display, SWT.CURSOR_HAND);
+ text.setCursor(fCursor);
+ }
+
+ private void resetCursor(ISourceViewer viewer) {
+ StyledText text = viewer.getTextWidget();
+ if (text != null && !text.isDisposed())
+ text.setCursor(null);
+
+ if (fCursor != null) {
+ fCursor.dispose();
+ fCursor = null;
+ }
+ }
+
+ /*
+ * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
+ */
+ public void keyPressed(KeyEvent event) {
+
+ if (fActive) {
+ deactivate();
+ return;
+ }
+
+ if (event.keyCode != fKeyModifierMask) {
+ deactivate();
+ return;
+ }
+
+ fActive = true;
+
+ // removed for #25871
+ //
+ // ISourceViewer viewer= getSourceViewer();
+ // if (viewer == null)
+ // return;
+ //
+ // IRegion region= getCurrentTextRegion(viewer);
+ // if (region == null)
+ // return;
+ //
+ // highlightRegion(viewer, region);
+ // activateCursor(viewer);
+ }
+
+ /*
+ * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
+ */
+ public void keyReleased(KeyEvent event) {
+
+ if (!fActive)
+ return;
+
+ deactivate();
+ }
+
+ /*
+ * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseDoubleClick(MouseEvent e) {
+ }
+
+ /*
+ * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseDown(MouseEvent event) {
+
+ if (!fActive)
+ return;
+
+ if (event.stateMask != fKeyModifierMask) {
+ deactivate();
+ return;
+ }
+
+ if (event.button != 1) {
+ deactivate();
+ return;
+ }
+ }
+
+ /*
+ * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseUp(MouseEvent e) {
+
+ if (!fActive)
+ return;
+
+ if (e.button != 1) {
+ deactivate();
+ return;
+ }
+
+ boolean wasActive = fCursor != null;
+
+ deactivate();
+
+ if (wasActive) {
+ IAction action = getAction("OpenEditor"); //$NON-NLS-1$
+ if (action != null)
+ action.run();
+ }
+ }
+
+ /*
+ * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseMove(MouseEvent event) {
+
+ if (event.widget instanceof Control
+ && !((Control) event.widget).isFocusControl()) {
+ deactivate();
+ return;
+ }
+
+ if (!fActive) {
+ if (event.stateMask != fKeyModifierMask)
+ return;
+ // modifier was already pressed
+ fActive = true;
+ }
+
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer == null) {
+ deactivate();
+ return;
+ }
+
+ StyledText text = viewer.getTextWidget();
+ if (text == null || text.isDisposed()) {
+ deactivate();
+ return;
+ }
+
+ if ((event.stateMask & SWT.BUTTON1) != 0
+ && text.getSelectionCount() != 0) {
+ deactivate();
+ return;
+ }
+
+ IRegion region = getCurrentTextRegion(viewer);
+ if (region == null || region.getLength() == 0) {
+ repairRepresentation();
+ return;
+ }
+
+ highlightRegion(viewer, region);
+ activateCursor(viewer);
+ }
+
+ /*
+ * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
+ */
+ public void focusGained(FocusEvent e) {
+ }
+
+ /*
+ * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+ */
+ public void focusLost(FocusEvent event) {
+ deactivate();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ if (fActive && fActiveRegion != null) {
+ fRememberedPosition = new Position(fActiveRegion.getOffset(),
+ fActiveRegion.getLength());
+ try {
+ event.getDocument().addPosition(fRememberedPosition);
+ } catch (BadLocationException x) {
+ fRememberedPosition = null;
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ if (fRememberedPosition != null) {
+ if (!fRememberedPosition.isDeleted()) {
+
+ event.getDocument().removePosition(fRememberedPosition);
+ fActiveRegion = new Region(fRememberedPosition.getOffset(),
+ fRememberedPosition.getLength());
+ fRememberedPosition = null;
+
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer != null) {
+ StyledText widget = viewer.getTextWidget();
+ if (widget != null && !widget.isDisposed()) {
+ widget.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ deactivate();
+ }
+ });
+ }
+ }
+
+ } else {
+ fActiveRegion = null;
+ fRememberedPosition = null;
+ deactivate();
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
+ * org.eclipse.jface.text.IDocument)
+ */
+ public void inputDocumentAboutToBeChanged(IDocument oldInput,
+ IDocument newInput) {
+ if (oldInput == null)
+ return;
+ deactivate();
+ oldInput.removeDocumentListener(this);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
+ * org.eclipse.jface.text.IDocument)
+ */
+ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+ if (newInput == null)
+ return;
+ newInput.addDocumentListener(this);
+ }
+
+ /*
+ * @see PaintListener#paintControl(PaintEvent)
+ */
+ public void paintControl(PaintEvent event) {
+ if (fActiveRegion == null)
+ return;
+
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer == null)
+ return;
+
+ StyledText text = viewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+
+ int offset = 0;
+ int length = 0;
+
+ if (viewer instanceof ITextViewerExtension5) {
+
+ ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+ IRegion widgetRange = extension
+ .modelRange2WidgetRange(fActiveRegion);
+ if (widgetRange == null)
+ return;
+
+ offset = widgetRange.getOffset();
+ length = widgetRange.getLength();
+
+ } else {
+
+ IRegion region = viewer.getVisibleRegion();
+ if (!includes(region, fActiveRegion))
+ return;
+
+ offset = fActiveRegion.getOffset() - region.getOffset();
+ length = fActiveRegion.getLength();
+ }
+
+ // support for bidi
+ Point minLocation = getMinimumLocation(text, offset, length);
+ Point maxLocation = getMaximumLocation(text, offset, length);
+
+ int x1 = minLocation.x;
+ int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
+ int y = minLocation.y + text.getLineHeight() - 1;
+
+ GC gc = event.gc;
+ if (fColor != null && !fColor.isDisposed())
+ gc.setForeground(fColor);
+ gc.drawLine(x1, y, x2, y);
+ }
+
+ private boolean includes(IRegion region, IRegion position) {
+ return position.getOffset() >= region.getOffset()
+ && position.getOffset() + position.getLength() <= region
+ .getOffset()
+ + region.getLength();
+ }
+
+ private Point getMinimumLocation(StyledText text, int offset, int length) {
+ Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+
+ for (int i = 0; i <= length; i++) {
+ Point location = text.getLocationAtOffset(offset + i);
+
+ if (location.x < minLocation.x)
+ minLocation.x = location.x;
+ if (location.y < minLocation.y)
+ minLocation.y = location.y;
+ }
+
+ return minLocation;
+ }
+
+ private Point getMaximumLocation(StyledText text, int offset, int length) {
+ Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
+
+ for (int i = 0; i <= length; i++) {
+ Point location = text.getLocationAtOffset(offset + i);
+
+ if (location.x > maxLocation.x)
+ maxLocation.x = location.x;
+ if (location.y > maxLocation.y)
+ maxLocation.y = location.y;
+ }
+
+ return maxLocation;
+ }
+ }
+
+ /**
+ * This action dispatches into two behaviours: If there is no current text
+ * hover, the javadoc is displayed using information presenter. If there is
+ * a current text hover, it is converted into a information presenter in
+ * order to make it sticky.
+ */
+ class InformationDispatchAction extends TextEditorAction {
+
+ /** The wrapped text operation action. */
+ private final TextOperationAction fTextOperationAction;
+
+ /**
+ * Creates a dispatch action.
+ */
+ public InformationDispatchAction(ResourceBundle resourceBundle,
+ String prefix, final TextOperationAction textOperationAction) {
+ super(resourceBundle, prefix, PHPEditor.this);
+ if (textOperationAction == null)
+ throw new IllegalArgumentException();
+ fTextOperationAction = textOperationAction;
+ }
+
+ /*
+ * @see org.eclipse.jface.action.IAction#run()
+ */
+ public void run() {
+
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null) {
+ fTextOperationAction.run();
+ return;
+ }
+
+ if (!(sourceViewer instanceof ITextViewerExtension2)) {
+ fTextOperationAction.run();
+ return;
+ }
+
+ ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer;
+
+ // does a text hover exist?
+ ITextHover textHover = textViewerExtension2.getCurrentTextHover();
+ if (textHover == null) {
+ fTextOperationAction.run();
+ return;
+ }
+
+ Point hoverEventLocation = textViewerExtension2
+ .getHoverEventLocation();
+ int offset = computeOffsetAtLocation(sourceViewer,
+ hoverEventLocation.x, hoverEventLocation.y);
+ if (offset == -1) {
+ fTextOperationAction.run();
+ return;
+ }
+
+ try {
+ // get the text hover content
+ IDocument document = sourceViewer.getDocument();
+ String contentType = document.getContentType(offset);
+
+ final IRegion hoverRegion = textHover.getHoverRegion(
+ sourceViewer, offset);
+ if (hoverRegion == null)
+ return;
+
+ final String hoverInfo = textHover.getHoverInfo(sourceViewer,
+ hoverRegion);
+
+ // with information provider
+ IInformationProvider informationProvider = new IInformationProvider() {
+ /*
+ * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer,
+ * int)
+ */
+ public IRegion getSubject(ITextViewer textViewer, int offset) {
+ return hoverRegion;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer,
+ * org.eclipse.jface.text.IRegion)
+ */
+ public String getInformation(ITextViewer textViewer,
+ IRegion subject) {
+ return hoverInfo;
+ }
+ };
+
+ fInformationPresenter.setOffset(offset);
+ fInformationPresenter.setInformationProvider(
+ informationProvider, contentType);
+ fInformationPresenter.showInformation();
+
+ } catch (BadLocationException e) {
+ }
+ }
+
+ // modified version from TextViewer
+ private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) {
+
+ StyledText styledText = textViewer.getTextWidget();
+ IDocument document = textViewer.getDocument();
+
+ if (document == null)
+ return -1;
+
+ try {
+ int widgetLocation = styledText.getOffsetAtLocation(new Point(
+ x, y));
+ if (textViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) textViewer;
+ return extension.widgetOffset2ModelOffset(widgetLocation);
+ } else {
+ IRegion visibleRegion = textViewer.getVisibleRegion();
+ return widgetLocation + visibleRegion.getOffset();
+ }
+ } catch (IllegalArgumentException e) {
+ return -1;
+ }
+
+ }
+ };
+
+ /**
+ * This action implements smart home.
+ *
+ * Instead of going to the start of a line it does the following: - if smart
+ * home/end is enabled and the caret is after the line's first
+ * non-whitespace then the caret is moved directly before it, taking JavaDoc
+ * and multi-line comments into account. - if the caret is before the line's
+ * first non-whitespace the caret is moved to the beginning of the line - if
+ * the caret is at the beginning of the line see first case.
+ *
+ * @since 3.0
+ */
+ protected class SmartLineStartAction extends LineStartAction {
+
+ /**
+ * Creates a new smart line start action
+ *
+ * @param textWidget
+ * the styled text widget
+ * @param doSelect
+ * a boolean flag which tells if the text up to the beginning
+ * of the line should be selected
+ */
+ public SmartLineStartAction(final StyledText textWidget,
+ final boolean doSelect) {
+ super(textWidget, doSelect);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor.LineStartAction#getLineStartPosition(java.lang.String,
+ * int, java.lang.String)
+ */
+ protected int getLineStartPosition(final IDocument document,
+ final String line, final int length, final int offset) {
+
+ String type = IDocument.DEFAULT_CONTENT_TYPE;
+ try {
+ type = TextUtilities.getContentType(document,
+ IPHPPartitions.PHP_PARTITIONING, offset, true);
+ } catch (BadLocationException exception) {
+ // Should not happen
+ }
+
+ int index = super.getLineStartPosition(document, line, length,
+ offset);
+ if (type.equals(IPHPPartitions.PHP_PHPDOC_COMMENT)
+ || type.equals(IPHPPartitions.PHP_MULTILINE_COMMENT)) {
+ if (index < length - 1 && line.charAt(index) == '*'
+ && line.charAt(index + 1) != '/') {
+ do {
+ ++index;
+ } while (index < length
+ && Character.isWhitespace(line.charAt(index)));
+ }
+ } else {
+ if (index < length - 1 && line.charAt(index) == '/'
+ && line.charAt(index + 1) == '/') {
+ index++;
+ do {
+ ++index;
+ } while (index < length
+ && Character.isWhitespace(line.charAt(index)));
+ }
+ }
+ return index;
+ }
+ }
+
+ /**
+ * Text navigation action to navigate to the next sub-word.
+ *
+ * @since 3.0
+ */
+ protected abstract class NextSubWordAction extends TextNavigationAction {
+
+ protected JavaWordIterator fIterator = new JavaWordIterator();
+
+ /**
+ * Creates a new next sub-word action.
+ *
+ * @param code
+ * Action code for the default operation. Must be an action
+ * code from
+ * @see org.eclipse.swt.custom.ST.
+ */
+ protected NextSubWordAction(int code) {
+ super(getSourceViewer().getTextWidget(), code);
+ }
+
+ /*
+ * @see org.eclipse.jface.action.IAction#run()
+ */
+ public void run() {
+ // Check whether we are in a java code partition and the preference
+ // is
+ // enabled
+ final IPreferenceStore store = getPreferenceStore();
+ if (!store
+ .getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
+ super.run();
+ return;
+ }
+
+ final ISourceViewer viewer = getSourceViewer();
+ final IDocument document = viewer.getDocument();
+ fIterator
+ .setText((CharacterIterator) new DocumentCharacterIterator(
+ document));
+ int position = widgetOffset2ModelOffset(viewer, viewer
+ .getTextWidget().getCaretOffset());
+ if (position == -1)
+ return;
+
+ int next = findNextPosition(position);
+ if (next != BreakIterator.DONE) {
+ setCaretPosition(next);
+ getTextWidget().showSelection();
+ fireSelectionChanged();
+ }
+
+ }
+
+ /**
+ * Finds the next position after the given position.
+ *
+ * @param position
+ * the current position
+ * @return the next position
+ */
+ protected int findNextPosition(int position) {
+ ISourceViewer viewer = getSourceViewer();
+ int widget = -1;
+ while (position != BreakIterator.DONE && widget == -1) { // TODO:
+ // optimize
+ position = fIterator.following(position);
+ if (position != BreakIterator.DONE)
+ widget = modelOffset2WidgetOffset(viewer, position);
+ }
+ return position;
+ }
+
+ /**
+ * Sets the caret position to the sub-word boundary given with
+ * position
.
+ *
+ * @param position
+ * Position where the action should move the caret
+ */
+ protected abstract void setCaretPosition(int position);
+ }
+
+ /**
+ * Text navigation action to navigate to the next sub-word.
+ *
+ * @since 3.0
+ */
+ protected class NavigateNextSubWordAction extends NextSubWordAction {
+
+ /**
+ * Creates a new navigate next sub-word action.
+ */
+ public NavigateNextSubWordAction() {
+ super(ST.WORD_NEXT);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
+ */
+ protected void setCaretPosition(final int position) {
+ getTextWidget().setCaretOffset(
+ modelOffset2WidgetOffset(getSourceViewer(), position));
+ }
+ }
+
+ /**
+ * Text operation action to delete the next sub-word.
+ *
+ * @since 3.0
+ */
+ protected class DeleteNextSubWordAction extends NextSubWordAction implements
+ IUpdate {
+
+ /**
+ * Creates a new delete next sub-word action.
+ */
+ public DeleteNextSubWordAction() {
+ super(ST.DELETE_WORD_NEXT);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
+ */
+ protected void setCaretPosition(final int position) {
+ if (!validateEditorInputState())
+ return;
+
+ final ISourceViewer viewer = getSourceViewer();
+ final int caret = widgetOffset2ModelOffset(viewer, viewer
+ .getTextWidget().getCaretOffset());
+
+ try {
+ viewer.getDocument().replace(caret, position - caret, ""); //$NON-NLS-1$
+ } catch (BadLocationException exception) {
+ // Should not happen
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#findNextPosition(int)
+ */
+ protected int findNextPosition(int position) {
+ return fIterator.following(position);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ setEnabled(isEditorInputModifiable());
+ }
+ }
+
+ /**
+ * Text operation action to select the next sub-word.
+ *
+ * @since 3.0
+ */
+ protected class SelectNextSubWordAction extends NextSubWordAction {
+
+ /**
+ * Creates a new select next sub-word action.
+ */
+ public SelectNextSubWordAction() {
+ super(ST.SELECT_WORD_NEXT);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
+ */
+ protected void setCaretPosition(final int position) {
+ final ISourceViewer viewer = getSourceViewer();
+
+ final StyledText text = viewer.getTextWidget();
+ if (text != null && !text.isDisposed()) {
+
+ final Point selection = text.getSelection();
+ final int caret = text.getCaretOffset();
+ final int offset = modelOffset2WidgetOffset(viewer, position);
+
+ if (caret == selection.x)
+ text.setSelectionRange(selection.y, offset - selection.y);
+ else
+ text.setSelectionRange(selection.x, offset - selection.x);
+ }
+ }
+ }
+
+ /**
+ * Text navigation action to navigate to the previous sub-word.
+ *
+ * @since 3.0
+ */
+ protected abstract class PreviousSubWordAction extends TextNavigationAction {
+
+ protected JavaWordIterator fIterator = new JavaWordIterator();
+
+ /**
+ * Creates a new previous sub-word action.
+ *
+ * @param code
+ * Action code for the default operation. Must be an action
+ * code from
+ * @see org.eclipse.swt.custom.ST.
+ */
+ protected PreviousSubWordAction(final int code) {
+ super(getSourceViewer().getTextWidget(), code);
+ }
+
+ /*
+ * @see org.eclipse.jface.action.IAction#run()
+ */
+ public void run() {
+ // Check whether we are in a java code partition and the preference
+ // is
+ // enabled
+ final IPreferenceStore store = getPreferenceStore();
+ if (!store
+ .getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
+ super.run();
+ return;
+ }
+
+ final ISourceViewer viewer = getSourceViewer();
+ final IDocument document = viewer.getDocument();
+ fIterator
+ .setText((CharacterIterator) new DocumentCharacterIterator(
+ document));
+ int position = widgetOffset2ModelOffset(viewer, viewer
+ .getTextWidget().getCaretOffset());
+ if (position == -1)
+ return;
+
+ int previous = findPreviousPosition(position);
+ if (previous != BreakIterator.DONE) {
+ setCaretPosition(previous);
+ getTextWidget().showSelection();
+ fireSelectionChanged();
+ }
+
+ }
+
+ /**
+ * Finds the previous position before the given position.
+ *
+ * @param position
+ * the current position
+ * @return the previous position
+ */
+ protected int findPreviousPosition(int position) {
+ ISourceViewer viewer = getSourceViewer();
+ int widget = -1;
+ while (position != BreakIterator.DONE && widget == -1) { // TODO:
+ // optimize
+ position = fIterator.preceding(position);
+ if (position != BreakIterator.DONE)
+ widget = modelOffset2WidgetOffset(viewer, position);
+ }
+ return position;
+ }
+
+ /**
+ * Sets the caret position to the sub-word boundary given with
+ * position
.
+ *
+ * @param position
+ * Position where the action should move the caret
+ */
+ protected abstract void setCaretPosition(int position);
+ }
+
+ /**
+ * Text navigation action to navigate to the previous sub-word.
+ *
+ * @since 3.0
+ */
+ protected class NavigatePreviousSubWordAction extends PreviousSubWordAction {
+
+ /**
+ * Creates a new navigate previous sub-word action.
+ */
+ public NavigatePreviousSubWordAction() {
+ super(ST.WORD_PREVIOUS);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
+ */
+ protected void setCaretPosition(final int position) {
+ getTextWidget().setCaretOffset(
+ modelOffset2WidgetOffset(getSourceViewer(), position));
+ }
+ }
+
+ /**
+ * Text operation action to delete the previous sub-word.
+ *
+ * @since 3.0
+ */
+ protected class DeletePreviousSubWordAction extends PreviousSubWordAction
+ implements IUpdate {
+
+ /**
+ * Creates a new delete previous sub-word action.
+ */
+ public DeletePreviousSubWordAction() {
+ super(ST.DELETE_WORD_PREVIOUS);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
+ */
+ protected void setCaretPosition(final int position) {
+ if (!validateEditorInputState())
+ return;
+
+ final ISourceViewer viewer = getSourceViewer();
+ final int caret = widgetOffset2ModelOffset(viewer, viewer
+ .getTextWidget().getCaretOffset());
+
+ try {
+ viewer.getDocument().replace(position, caret - position, ""); //$NON-NLS-1$
+ } catch (BadLocationException exception) {
+ // Should not happen
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#findPreviousPosition(int)
+ */
+ protected int findPreviousPosition(int position) {
+ return fIterator.preceding(position);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ setEnabled(isEditorInputModifiable());
+ }
+ }
+
+ /**
+ * Text operation action to select the previous sub-word.
+ *
+ * @since 3.0
+ */
+ protected class SelectPreviousSubWordAction extends PreviousSubWordAction {
+
+ /**
+ * Creates a new select previous sub-word action.
+ */
+ public SelectPreviousSubWordAction() {
+ super(ST.SELECT_WORD_PREVIOUS);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
+ */
+ protected void setCaretPosition(final int position) {
+ final ISourceViewer viewer = getSourceViewer();
+
+ final StyledText text = viewer.getTextWidget();
+ if (text != null && !text.isDisposed()) {
+
+ final Point selection = text.getSelection();
+ final int caret = text.getCaretOffset();
+ final int offset = modelOffset2WidgetOffset(viewer, position);
+
+ if (caret == selection.x)
+ text.setSelectionRange(selection.y, offset - selection.y);
+ else
+ text.setSelectionRange(selection.x, offset - selection.x);
+ }
+ }
+ }
+
+ // static protected class AnnotationAccess implements IAnnotationAccess {
+ // /*
+ // * @see
+ // org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation)
+ // */
+ // public Object getType(Annotation annotation) {
+ // if (annotation instanceof IJavaAnnotation) {
+ // IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
+ // // if (javaAnnotation.isRelevant())
+ // // return javaAnnotation.getAnnotationType();
+ // }
+ // return null;
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation)
+ // */
+ // public boolean isMultiLine(Annotation annotation) {
+ // return true;
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation)
+ // */
+ // public boolean isTemporary(Annotation annotation) {
+ // if (annotation instanceof IJavaAnnotation) {
+ // IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
+ // if (javaAnnotation.isRelevant())
+ // return javaAnnotation.isTemporary();
+ // }
+ // return false;
+ // }
+ // };
+
+ private class PropertyChangeListener implements
+ org.eclipse.core.runtime.Preferences.IPropertyChangeListener {
+ /*
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(
+ org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
+ handlePreferencePropertyChanged(event);
+ }
+ };
+
+ /**
+ * Finds and marks occurrence annotations.
+ *
+ * @since 3.0
+ */
+ class OccurrencesFinderJob extends Job {
+
+ private IDocument fDocument;
+
+ private ISelection fSelection;
+
+ private ISelectionValidator fPostSelectionValidator;
+
+ private boolean fCanceled = false;
+
+ private IProgressMonitor fProgressMonitor;
+
+ private Position[] fPositions;
+
+ public OccurrencesFinderJob(IDocument document, Position[] positions,
+ ISelection selection) {
+ super(PHPEditorMessages.JavaEditor_markOccurrences_job_name);
+ fDocument = document;
+ fSelection = selection;
+ fPositions = positions;
+
+ if (getSelectionProvider() instanceof ISelectionValidator)
+ fPostSelectionValidator = (ISelectionValidator) getSelectionProvider();
+ }
+
+ // cannot use cancel() because it is declared final
+ void doCancel() {
+ fCanceled = true;
+ cancel();
+ }
+
+ private boolean isCanceled() {
+ return fCanceled
+ || fProgressMonitor.isCanceled()
+ || fPostSelectionValidator != null
+ && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection)
+ || LinkedModeModel.hasInstalledModel(fDocument);
+ }
+
+ /*
+ * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus run(IProgressMonitor progressMonitor) {
+
+ fProgressMonitor = progressMonitor;
+
+ if (isCanceled())
+ return Status.CANCEL_STATUS;
+
+ ITextViewer textViewer = getViewer();
+ if (textViewer == null)
+ return Status.CANCEL_STATUS;
+
+ IDocument document = textViewer.getDocument();
+ if (document == null)
+ return Status.CANCEL_STATUS;
+
+ IDocumentProvider documentProvider = getDocumentProvider();
+ if (documentProvider == null)
+ return Status.CANCEL_STATUS;
+
+ IAnnotationModel annotationModel = documentProvider
+ .getAnnotationModel(getEditorInput());
+ if (annotationModel == null)
+ return Status.CANCEL_STATUS;
+
+ // Add occurrence annotations
+ int length = fPositions.length;
+ Map annotationMap = new HashMap(length);
+ for (int i = 0; i < length; i++) {
+
+ if (isCanceled())
+ return Status.CANCEL_STATUS;
+
+ String message;
+ Position position = fPositions[i];
+
+ // Create & add annotation
+ try {
+ message = document.get(position.offset, position.length);
+ } catch (BadLocationException ex) {
+ // Skip this match
+ continue;
+ }
+ annotationMap
+ .put(
+ new Annotation(
+ "net.sourceforge.phpdt.ui.occurrences", false, message), //$NON-NLS-1$
+ position);
+ }
+
+ if (isCanceled())
+ return Status.CANCEL_STATUS;
+
+ synchronized (getLockObject(annotationModel)) {
+ if (annotationModel instanceof IAnnotationModelExtension) {
+ ((IAnnotationModelExtension) annotationModel)
+ .replaceAnnotations(fOccurrenceAnnotations,
+ annotationMap);
+ } else {
+ removeOccurrenceAnnotations();
+ Iterator iter = annotationMap.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry mapEntry = (Map.Entry) iter.next();
+ annotationModel.addAnnotation((Annotation) mapEntry
+ .getKey(), (Position) mapEntry.getValue());
+ }
+ }
+ fOccurrenceAnnotations = (Annotation[]) annotationMap.keySet()
+ .toArray(new Annotation[annotationMap.keySet().size()]);
+ }
+
+ return Status.OK_STATUS;
+ }
+ }
+
+ /**
+ * Cancels the occurrences finder job upon document changes.
+ *
+ * @since 3.0
+ */
+ class OccurrencesFinderJobCanceler implements IDocumentListener,
+ ITextInputListener {
+
+ public void install() {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null)
+ return;
+
+ StyledText text = sourceViewer.getTextWidget();
+ if (text == null || text.isDisposed())
+ return;
+
+ sourceViewer.addTextInputListener(this);
+
+ IDocument document = sourceViewer.getDocument();
+ if (document != null)
+ document.addDocumentListener(this);
+ }
+
+ public void uninstall() {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer != null)
+ sourceViewer.removeTextInputListener(this);
+
+ IDocumentProvider documentProvider = getDocumentProvider();
+ if (documentProvider != null) {
+ IDocument document = documentProvider
+ .getDocument(getEditorInput());
+ if (document != null)
+ document.removeDocumentListener(this);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ if (fOccurrencesFinderJob != null)
+ fOccurrencesFinderJob.doCancel();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
+ * org.eclipse.jface.text.IDocument)
+ */
+ public void inputDocumentAboutToBeChanged(IDocument oldInput,
+ IDocument newInput) {
+ if (oldInput == null)
+ return;
+
+ oldInput.removeDocumentListener(this);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
+ * org.eclipse.jface.text.IDocument)
+ */
+ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+ if (newInput == null)
+ return;
+ newInput.addDocumentListener(this);
+ }
+ }
+
+ /**
+ * Internal activation listener.
+ *
+ * @since 3.0
+ */
+ private class ActivationListener implements IWindowListener {
+
+ /*
+ * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
+ * @since 3.1
+ */
+ public void windowActivated(IWorkbenchWindow window) {
+ if (window == getEditorSite().getWorkbenchWindow()
+ && fMarkOccurrenceAnnotations && isActivePart()) {
+ fForcedMarkOccurrencesSelection = getSelectionProvider()
+ .getSelection();
+ SelectionListenerWithASTManager
+ .getDefault()
+ .forceSelectionChange(
+ PHPEditor.this,
+ (ITextSelection) fForcedMarkOccurrencesSelection);
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
+ * @since 3.1
+ */
+ public void windowDeactivated(IWorkbenchWindow window) {
+ if (window == getEditorSite().getWorkbenchWindow()
+ && fMarkOccurrenceAnnotations && isActivePart())
+ removeOccurrenceAnnotations();
+ }
+
+ /*
+ * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
+ * @since 3.1
+ */
+ public void windowClosed(IWorkbenchWindow window) {
+ }
+
+ /*
+ * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
+ * @since 3.1
+ */
+ public void windowOpened(IWorkbenchWindow window) {
+ }
+ }
+
+ /**
+ * Updates the selection in the editor's widget with the selection of the
+ * outline page.
+ */
+ class OutlineSelectionChangedListener extends
+ AbstractSelectionChangedListener {
+ public void selectionChanged(SelectionChangedEvent event) {
+ doSelectionChanged(event);
+ }
+ }
+
+ /**
+ * The internal shell activation listener for updating occurrences.
+ *
+ * @since 3.0
+ */
+ private ActivationListener fActivationListener = new ActivationListener();
+
+ private ISelectionListenerWithAST fPostSelectionListenerWithAST;
+
+ private OccurrencesFinderJob fOccurrencesFinderJob;
+
+ /** The occurrences finder job canceler */
+ private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler;
+
+ /**
+ * Holds the current occurrence annotations.
+ *
+ * @since 3.0
+ */
+ private Annotation[] fOccurrenceAnnotations = null;
+
+ /**
+ * Tells whether all occurrences of the element at the current caret
+ * location are automatically marked in this editor.
+ *
+ * @since 3.0
+ */
+ private boolean fMarkOccurrenceAnnotations;
+
+ /**
+ * The selection used when forcing occurrence marking through code.
+ *
+ * @since 3.0
+ */
+ private ISelection fForcedMarkOccurrencesSelection;
+
+ /**
+ * The document modification stamp at the time when the last occurrence
+ * marking took place.
+ *
+ * @since 3.1
+ */
+ private long fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
+
+ /**
+ * The region of the word under the caret used to when computing the current
+ * occurrence markings.
+ *
+ * @since 3.1
+ */
+ private IRegion fMarkOccurrenceTargetRegion;
+
+ /**
+ * Tells whether the occurrence annotations are sticky i.e. whether they
+ * stay even if there's no valid Java element at the current caret position.
+ * Only valid if {@link #fMarkOccurrenceAnnotations} is true
.
+ *
+ * @since 3.0
+ */
+ private boolean fStickyOccurrenceAnnotations;
+
+ /** Preference key for the link color */
+ private final static String LINK_COLOR = PreferenceConstants.EDITOR_LINK_COLOR;
+
+ /** Preference key for compiler task tags */
+ private final static String COMPILER_TASK_TAGS = JavaCore.COMPILER_TASK_TAGS;
+
+ // protected PHPActionGroup fActionGroups;
+ // /** The outline page */
+ // private AbstractContentOutlinePage fOutlinePage;
+ /** The outline page */
+ protected JavaOutlinePage fOutlinePage;
+
+ /** Outliner context menu Id */
+ protected String fOutlinerContextMenuId;
+
+ /**
+ * Indicates whether this editor should react on outline page selection
+ * changes
+ */
+ private int fIgnoreOutlinePageSelection;
+
+ /** The outline page selection updater */
+ // private OutlinePageSelectionUpdater fUpdater;
+ // protected PHPSyntaxParserThread fValidationThread = null;
+ // private IPreferenceStore fPHPPrefStore;
+ /** The selection changed listener */
+ // protected ISelectionChangedListener fSelectionChangedListener = new
+ // SelectionChangedListener();
+ /**
+ * The editor selection changed listener.
+ *
+ * @since 3.0
+ */
+ private EditorSelectionChangedListener fEditorSelectionChangedListener;
+
+ /** The selection changed listener */
+ protected AbstractSelectionChangedListener fOutlineSelectionChangedListener = new OutlineSelectionChangedListener();
+
+ /** The editor's bracket matcher */
+ private PHPPairMatcher fBracketMatcher = new PHPPairMatcher(BRACKETS);
+
+ /** The line number ruler column */
+ // private LineNumberRulerColumn fLineNumberRulerColumn;
+ /** This editor's encoding support */
+ private DefaultEncodingSupport fEncodingSupport;
+
+ /** The mouse listener */
+ private MouseClickListener fMouseListener;
+
+ /**
+ * Indicates whether this editor is about to update any annotation views.
+ *
+ * @since 3.0
+ */
+ private boolean fIsUpdatingAnnotationViews = false;
+
+ /**
+ * The marker that served as last target for a goto marker request.
+ *
+ * @since 3.0
+ */
+ private IMarker fLastMarkerTarget = null;
+
+ protected CompositeActionGroup fActionGroups;
+
+ protected CompositeActionGroup fContextMenuGroup;
+
+ /**
+ * This editor's projection support
+ *
+ * @since 3.0
+ */
+ private ProjectionSupport fProjectionSupport;
+
+ /**
+ * This editor's projection model updater
+ *
+ * @since 3.0
+ */
+ private IJavaFoldingStructureProvider fProjectionModelUpdater;
+
+ /**
+ * The override and implements indicator manager for this editor.
+ *
+ * @since 3.0
+ */
+ // protected OverrideIndicatorManager fOverrideIndicatorManager;
+ /**
+ * The action group for folding.
+ *
+ * @since 3.0
+ */
+ private FoldingActionGroup fFoldingGroup;
+
+ /** The information presenter. */
+ private InformationPresenter fInformationPresenter;
+
+ /** The annotation access */
+ // protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess();
+ /** The overview ruler */
+ protected OverviewRuler isOverviewRulerVisible;
+
+ /** The source viewer decoration support */
+ // protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
+ /** The overview ruler */
+ // protected OverviewRuler fOverviewRuler;
+ /** The preference property change listener for java core. */
+ private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
+
+ /**
+ * Returns the most narrow java element including the given offset
+ *
+ * @param offset
+ * the offset inside of the requested element
+ */
+ abstract protected IJavaElement getElementAt(int offset);
+
+ /**
+ * Returns the java element of this editor's input corresponding to the
+ * given IJavaElement
+ */
+ abstract protected IJavaElement getCorrespondingElement(IJavaElement element);
+
+ /**
+ * Sets the input of the editor's outline page.
+ */
+ abstract protected void setOutlinePageInput(JavaOutlinePage page,
+ IEditorInput input);
+
+ /**
+ * Default constructor.
+ */
+ public PHPEditor() {
+ super();
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes()
+ */
+ protected void initializeKeyBindingScopes() {
+ setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" }); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
+ */
+ protected void initializeEditor() {
+ // jsurfer old code
+ // JavaTextTools textTools =
+ // PHPeclipsePlugin.getDefault().getJavaTextTools();
+ // setSourceViewerConfiguration(new
+ // PHPSourceViewerConfiguration(textTools,
+ // this, IPHPPartitions.PHP_PARTITIONING)); //,
+ // IJavaPartitions.JAVA_PARTITIONING));
+ IPreferenceStore store = createCombinedPreferenceStore(null);
+ setPreferenceStore(store);
+ JavaTextTools textTools = WebUI.getDefault()
+ .getJavaTextTools();
+ setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools
+ .getColorManager(), store, this,
+ IPHPPartitions.PHP_PARTITIONING));
+
+ // TODO changed in 3.x ?
+ // setRangeIndicator(new DefaultRangeIndicator());
+ // if
+ // (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
+ // fUpdater = new OutlinePageSelectionUpdater();
+ // jsurfer end
+
+ // IPreferenceStore store= createCombinedPreferenceStore(null);
+ // setPreferenceStore(store);
+ // JavaTextTools textTools=
+ // PHPeclipsePlugin.getDefault().getJavaTextTools();
+ // setSourceViewerConfiguration(new
+ // JavaSourceViewerConfiguration(textTools.getColorManager(), store,
+ // this, IJavaPartitions.JAVA_PARTITIONING));
+ fMarkOccurrenceAnnotations = store
+ .getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
+ fStickyOccurrenceAnnotations = store
+ .getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
+ // fMarkTypeOccurrences=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
+ // fMarkMethodOccurrences=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
+ // fMarkConstantOccurrences=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
+ // fMarkFieldOccurrences=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
+ // fMarkLocalVariableypeOccurrences=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
+ // fMarkExceptions=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES);
+ // fMarkImplementors=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS);
+ // fMarkMethodExitPoints=
+ // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS);
+
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
+ */
+ protected void updatePropertyDependentActions() {
+ super.updatePropertyDependentActions();
+ if (fEncodingSupport != null)
+ fEncodingSupport.reset();
+ }
+
+ /*
+ * Update the hovering behavior depending on the preferences.
+ */
+ private void updateHoverBehavior() {
+ SourceViewerConfiguration configuration = getSourceViewerConfiguration();
+ String[] types = configuration
+ .getConfiguredContentTypes(getSourceViewer());
+
+ for (int i = 0; i < types.length; i++) {
+
+ String t = types[i];
+
+ int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(
+ getSourceViewer(), t);
+
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer instanceof ITextViewerExtension2) {
+ if (stateMasks != null) {
+ for (int j = 0; j < stateMasks.length; j++) {
+ int stateMask = stateMasks[j];
+ ITextHover textHover = configuration.getTextHover(
+ sourceViewer, t, stateMask);
+ ((ITextViewerExtension2) sourceViewer).setTextHover(
+ textHover, t, stateMask);
+ }
+ } else {
+ ITextHover textHover = configuration.getTextHover(
+ sourceViewer, t);
+ ((ITextViewerExtension2) sourceViewer).setTextHover(
+ textHover, t,
+ ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
+ }
+ } else
+ sourceViewer.setTextHover(configuration.getTextHover(
+ sourceViewer, t), t);
+ }
+ }
+
+ public void updatedTitleImage(Image image) {
+ setTitleImage(image);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
+ */
+ public Object getViewPartInput() {
+ return getEditorInput().getAdapter(IResource.class);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetSelection(ISelection)
+ */
+ protected void doSetSelection(ISelection selection) {
+ super.doSetSelection(selection);
+ synchronizeOutlinePageSelection();
+ }
+
+ boolean isFoldingEnabled() {
+ return WebUI.getDefault().getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_FOLDING_ENABLED);
+ }
+
+ /*
+ * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.
+ * widgets.Composite)
+ */
+ public void createPartControl(Composite parent) {
+ super.createPartControl(parent);
+
+ // fSourceViewerDecorationSupport.install(getPreferenceStore());
+
+ ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
+
+ fProjectionSupport = new ProjectionSupport(projectionViewer,
+ getAnnotationAccess(), getSharedColors());
+ fProjectionSupport
+ .addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
+ fProjectionSupport
+ .addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
+ fProjectionSupport
+ .setHoverControlCreator(new IInformationControlCreator() {
+ public IInformationControl createInformationControl(
+ Shell shell) {
+ return new CustomSourceInformationControl(shell,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ }
+ });
+ fProjectionSupport.install();
+
+ fProjectionModelUpdater = WebUI.getDefault()
+ .getFoldingStructureProviderRegistry()
+ .getCurrentFoldingProvider();
+ if (fProjectionModelUpdater != null)
+ fProjectionModelUpdater.install(this, projectionViewer);
+
+ if (isFoldingEnabled())
+ projectionViewer.doOperation(ProjectionViewer.TOGGLE);
+ Preferences preferences = PHPeclipsePlugin.getDefault()
+ .getPluginPreferences();
+ preferences.addPropertyChangeListener(fPropertyChangeListener);
+ IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ boolean cutDown = false;
+ int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
+ return new DefaultInformationControl(parent, SWT.RESIZE, style,
+ new HTMLTextPresenter(cutDown));
+ }
+ };
+
+ fInformationPresenter = new InformationPresenter(
+ informationControlCreator);
+ fInformationPresenter.setSizeConstraints(60, 10, true, true);
+ fInformationPresenter.install(getSourceViewer());
+
+ fEditorSelectionChangedListener = new EditorSelectionChangedListener();
+ fEditorSelectionChangedListener.install(getSelectionProvider());
+
+ if (isBrowserLikeLinks())
+ enableBrowserLikeLinks();
+
+ if (PreferenceConstants.getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE))
+ enableOverwriteMode(false);
+
+ if (fMarkOccurrenceAnnotations)
+ installOccurrencesFinder();
+
+ PlatformUI.getWorkbench().addWindowListener(fActivationListener);
+
+ /*
+ * start of EDITOR_SAVE_ON_BLUR
+ * ed_mann
+ */
+ final PHPEditor editor = this;
+ FocusListener focusListener = new FocusListener() {
+
+ public void focusGained(FocusEvent e) {
+ return;
+ }
+
+ public void focusLost(FocusEvent e) {
+ //viewer.get
+ if(editor.isDirty() && WebUI.getDefault().getPreferenceStore()
+ .getBoolean(PreferenceConstants.EDITOR_SAVE_ON_BLUR)){
+ editor.doSave(null);
+ }
+ }
+ };
+ projectionViewer.getTextWidget().addFocusListener(focusListener);
+ /*
+ * end of EDITOR_SAVE_ON_BLUR
+ * ed_mann
+ */
+
+ setWordWrap();
+ }
+
+ private void setWordWrap() {
+ if (getSourceViewer() != null) {
+ getSourceViewer().getTextWidget().setWordWrap(
+ WebUI.getDefault().getPreferenceStore()
+ .getBoolean(PreferenceConstants.EDITOR_WRAP_WORDS));
+ }
+ }
+
+ protected void configureSourceViewerDecorationSupport(
+ SourceViewerDecorationSupport support) {
+
+ support.setCharacterPairMatcher(fBracketMatcher);
+ support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS,
+ MATCHING_BRACKETS_COLOR);
+
+ super.configureSourceViewerDecorationSupport(support);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#gotoMarker(org.eclipse.core.resources.IMarker)
+ */
+ public void gotoMarker(IMarker marker) {
+ fLastMarkerTarget = marker;
+ if (!fIsUpdatingAnnotationViews) {
+ super.gotoMarker(marker);
+ }
+ }
+
+ /**
+ * Jumps to the next enabled annotation according to the given direction. An
+ * annotation type is enabled if it is configured to be in the Next/Previous
+ * tool bar drop down menu and if it is checked.
+ *
+ * @param forward
+ * true
if search direction is forward,
+ * false
if backward
+ */
+ public Annotation gotoAnnotation(boolean forward) {
+ ITextSelection selection = (ITextSelection) getSelectionProvider()
+ .getSelection();
+ Position position = new Position(0, 0);
+ Annotation annotation = null;
+ if (false /* delayed - see bug 18316 */) {
+ annotation = getNextAnnotation(selection.getOffset(), selection
+ .getLength(), forward, position);
+ selectAndReveal(position.getOffset(), position.getLength());
+ } else /* no delay - see bug 18316 */{
+ annotation = getNextAnnotation(selection.getOffset(), selection
+ .getLength(), forward, position);
+ setStatusLineErrorMessage(null);
+ setStatusLineMessage(null);
+ if (annotation != null) {
+ updateAnnotationViews(annotation);
+ selectAndReveal(position.getOffset(), position.getLength());
+ setStatusLineMessage(annotation.getText());
+ }
+ }
+ return annotation;
+ }
+
+ /**
+ * Returns the lock object for the given annotation model.
+ *
+ * @param annotationModel
+ * the annotation model
+ * @return the annotation model's lock object
+ * @since 3.0
+ */
+ private Object getLockObject(IAnnotationModel annotationModel) {
+ if (annotationModel instanceof ISynchronizable)
+ return ((ISynchronizable) annotationModel).getLockObject();
+ else
+ return annotationModel;
+ }
+
+ /**
+ * Updates the annotation views that show the given annotation.
+ *
+ * @param annotation
+ * the annotation
+ */
+ private void updateAnnotationViews(Annotation annotation) {
+ IMarker marker = null;
+ if (annotation instanceof MarkerAnnotation)
+ marker = ((MarkerAnnotation) annotation).getMarker();
+ else if (annotation instanceof IJavaAnnotation) {
+ Iterator e = ((IJavaAnnotation) annotation).getOverlaidIterator();
+ if (e != null) {
+ while (e.hasNext()) {
+ Object o = e.next();
+ if (o instanceof MarkerAnnotation) {
+ marker = ((MarkerAnnotation) o).getMarker();
+ break;
+ }
+ }
+ }
+ }
+
+ if (marker != null && !marker.equals(fLastMarkerTarget)) {
+ try {
+ boolean isProblem = marker.isSubtypeOf(IMarker.PROBLEM);
+ IWorkbenchPage page = getSite().getPage();
+ IViewPart view = page
+ .findView(isProblem ? IPageLayout.ID_PROBLEM_VIEW
+ : IPageLayout.ID_TASK_LIST); //$NON-NLS-1$ //$NON-NLS-2$
+ if (view != null) {
+ Method method = view
+ .getClass()
+ .getMethod(
+ "setSelection", new Class[] { IStructuredSelection.class, boolean.class }); //$NON-NLS-1$
+ method.invoke(view, new Object[] {
+ new StructuredSelection(marker), Boolean.TRUE });
+ }
+ } catch (CoreException x) {
+ } catch (NoSuchMethodException x) {
+ } catch (IllegalAccessException x) {
+ } catch (InvocationTargetException x) {
+ }
+ // ignore exceptions, don't update any of the lists, just set status
+ // line
+ }
+ }
+
+ /**
+ * Returns this document's complete text.
+ *
+ * @return the document's complete text
+ */
+ public String get() {
+ IDocument doc = this.getDocumentProvider().getDocument(
+ this.getEditorInput());
+ return doc.get();
+ }
+
+ /**
+ * Sets the outliner's context menu ID.
+ */
+ protected void setOutlinerContextMenuId(String menuId) {
+ fOutlinerContextMenuId = menuId;
+ }
+
+ /**
+ * Returns the standard action group of this editor.
+ */
+ protected ActionGroup getActionGroup() {
+ return fActionGroups;
+ }
+
+ // public JavaOutlinePage getfOutlinePage() {
+ // return fOutlinePage;
+ // }
+
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method extend the actions to add those
+ * specific to the receiver
+ */
+ protected void createActions() {
+ super.createActions();
+
+ ActionGroup oeg, ovg, jsg, sg;
+ fActionGroups = new CompositeActionGroup(
+ new ActionGroup[] { oeg = new OpenEditorActionGroup(this),
+ // sg= new ShowActionGroup(this),
+ // ovg= new OpenViewActionGroup(this),
+ // jsg= new JavaSearchActionGroup(this)
+ });
+ fContextMenuGroup = new CompositeActionGroup(new ActionGroup[] { oeg });
+ // , ovg, sg, jsg});
+
+ fFoldingGroup = new FoldingActionGroup(this, getViewer());
+
+ // ResourceAction resAction = new
+ // TextOperationAction(PHPEditorMessages.getResourceBundle(),
+ // "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$
+ // resAction = new
+ // InformationDispatchAction(PHPEditorMessages.getResourceBundle(),
+ // "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
+ // resAction.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC);
+ // setAction("ShowJavaDoc", resAction); //$NON-NLS-1$
+
+ // WorkbenchHelp.setHelp(resAction,
+ // IJavaHelpContextIds.SHOW_JAVADOC_ACTION);
+
+ Action action = new GotoMatchingBracketAction(this);
+ action
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
+ setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
+
+ // action= new
+ // TextOperationAction(PHPEditorMessages.getResourceBundle(),"ShowOutline.",
+ // this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE);
+ // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE, action);
+ // // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.SHOW_OUTLINE_ACTION);
+ //
+ // action= new
+ // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenStructure.",
+ // this, JavaSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE);
+ // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE,
+ // action);
+ // // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.OPEN_STRUCTURE_ACTION);
+ //
+ // action= new
+ // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenHierarchy.",
+ // this, JavaSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY);
+ // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY,
+ // action);
+ // // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.OPEN_HIERARCHY_ACTION);
+
+ fEncodingSupport = new DefaultEncodingSupport();
+ fEncodingSupport.initialize(this);
+
+ // fSelectionHistory= new SelectionHistory(this);
+ //
+ // action= new StructureSelectEnclosingAction(this, fSelectionHistory);
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_ENCLOSING);
+ // setAction(StructureSelectionAction.ENCLOSING, action);
+ //
+ // action= new StructureSelectNextAction(this, fSelectionHistory);
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_NEXT);
+ // setAction(StructureSelectionAction.NEXT, action);
+ //
+ // action= new StructureSelectPreviousAction(this, fSelectionHistory);
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_PREVIOUS);
+ // setAction(StructureSelectionAction.PREVIOUS, action);
+ //
+ // StructureSelectHistoryAction historyAction= new
+ // StructureSelectHistoryAction(this, fSelectionHistory);
+ // historyAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_LAST);
+ // setAction(StructureSelectionAction.HISTORY, historyAction);
+ // fSelectionHistory.setHistoryAction(historyAction);
+ //
+ // action= GoToNextPreviousMemberAction.newGoToNextMemberAction(this);
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_NEXT_MEMBER);
+ // setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action);
+ //
+ // action=
+ // GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this);
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);
+ // setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action);
+ //
+ // action= new QuickFormatAction();
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.QUICK_FORMAT);
+ // setAction(IJavaEditorActionDefinitionIds.QUICK_FORMAT, action);
+ //
+ // action= new RemoveOccurrenceAnnotations(this);
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
+ // setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$
+
+ // add annotation actions
+ action = new JavaSelectMarkerRulerAction2(PHPEditorMessages
+ .getResourceBundle(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
+ setAction("AnnotationAction", action); //$NON-NLS-1$
+ }
+
+ private void internalDoSetInput(IEditorInput input) throws CoreException {
+ super.doSetInput(input);
+
+ if (getSourceViewer() instanceof JavaSourceViewer) {
+ JavaSourceViewer viewer = (JavaSourceViewer) getSourceViewer();
+ if (viewer.getReconciler() == null) {
+ IReconciler reconciler = getSourceViewerConfiguration()
+ .getReconciler(viewer);
+ if (reconciler != null) {
+ reconciler.install(viewer);
+ viewer.setReconciler(reconciler);
+ }
+ }
+ }
+
+ if (fEncodingSupport != null)
+ fEncodingSupport.reset();
+
+ setOutlinePageInput(fOutlinePage, input);
+
+ if (fProjectionModelUpdater != null)
+ fProjectionModelUpdater.initialize();
+
+ // if (isShowingOverrideIndicators())
+ // installOverrideIndicator(false);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore)
+ * @since 3.0
+ */
+ protected void setPreferenceStore(IPreferenceStore store) {
+ super.setPreferenceStore(store);
+ if (getSourceViewerConfiguration() instanceof PHPSourceViewerConfiguration) {
+ JavaTextTools textTools = WebUI.getDefault()
+ .getJavaTextTools();
+ setSourceViewerConfiguration(new PHPSourceViewerConfiguration(
+ textTools.getColorManager(), store, this,
+ IPHPPartitions.PHP_PARTITIONING));
+ }
+ if (getSourceViewer() instanceof JavaSourceViewer)
+ ((JavaSourceViewer) getSourceViewer()).setPreferenceStore(store);
+ }
+
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method performs any extra disposal
+ * actions required by the php editor.
+ */
+ public void dispose() {
+ if (fProjectionModelUpdater != null) {
+ fProjectionModelUpdater.uninstall();
+ fProjectionModelUpdater = null;
+ }
+
+ if (fProjectionSupport != null) {
+ fProjectionSupport.dispose();
+ fProjectionSupport = null;
+ }
+ // PHPEditorEnvironment.disconnect(this);
+ if (fOutlinePage != null)
+ fOutlinePage.setInput(null);
+
+ if (fActionGroups != null)
+ fActionGroups.dispose();
+
+ if (isBrowserLikeLinks())
+ disableBrowserLikeLinks();
+
+ // cancel possible running computation
+ fMarkOccurrenceAnnotations = false;
+ uninstallOccurrencesFinder();
+
+ uninstallOverrideIndicator();
+
+ if (fActivationListener != null) {
+ PlatformUI.getWorkbench().removeWindowListener(fActivationListener);
+ fActivationListener = null;
+ }
+
+ if (fEncodingSupport != null) {
+ fEncodingSupport.dispose();
+ fEncodingSupport = null;
+ }
+
+ if (fPropertyChangeListener != null) {
+ Preferences preferences = PHPeclipsePlugin.getDefault()
+ .getPluginPreferences();
+ preferences.removePropertyChangeListener(fPropertyChangeListener);
+ fPropertyChangeListener = null;
+ }
+
+ // if (fSourceViewerDecorationSupport != null) {
+ // fSourceViewerDecorationSupport.dispose();
+ // fSourceViewerDecorationSupport = null;
+ // }
+
+ if (fBracketMatcher != null) {
+ fBracketMatcher.dispose();
+ fBracketMatcher = null;
+ }
+
+ if (fEditorSelectionChangedListener != null) {
+ fEditorSelectionChangedListener.uninstall(getSelectionProvider());
+ fEditorSelectionChangedListener = null;
+ }
+
+ super.dispose();
+ }
+
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method performs any extra revert
+ * behavior required by the php editor.
+ */
+ // public void doRevertToSaved() {
+ // super.doRevertToSaved();
+ // if (fOutlinePage != null)
+ // fOutlinePage.update();
+ // }
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method performs any extra save behavior
+ * required by the php editor.
+ */
+ // public void doSave(IProgressMonitor monitor) {
+ // super.doSave(monitor);
+ // compile or not, according to the user preferences
+ // IPreferenceStore store = getPreferenceStore();
+ // the parse on save was changed to the eclipse "builders" concept
+ // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
+ // IAction a = PHPParserAction.getInstance();
+ // if (a != null)
+ // a.run();
+ // }
+ // if (SWT.getPlatform().equals("win32")) {
+ // IAction a = ShowExternalPreviewAction.getInstance();
+ // if (a != null)
+ // a.run();
+ // }
+ // if (fOutlinePage != null)
+ // fOutlinePage.update();
+ // }
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method performs any extra save as
+ * behavior required by the php editor.
+ */
+ // public void doSaveAs() {
+ // super.doSaveAs();
+ // if (fOutlinePage != null)
+ // fOutlinePage.update();
+ // }
+ /*
+ * @see StatusTextEditor#getStatusHeader(IStatus)
+ */
+ protected String getStatusHeader(IStatus status) {
+ if (fEncodingSupport != null) {
+ String message = fEncodingSupport.getStatusHeader(status);
+ if (message != null)
+ return message;
+ }
+ return super.getStatusHeader(status);
+ }
+
+ /*
+ * @see StatusTextEditor#getStatusBanner(IStatus)
+ */
+ protected String getStatusBanner(IStatus status) {
+ if (fEncodingSupport != null) {
+ String message = fEncodingSupport.getStatusBanner(status);
+ if (message != null)
+ return message;
+ }
+ return super.getStatusBanner(status);
+ }
+
+ /*
+ * @see StatusTextEditor#getStatusMessage(IStatus)
+ */
+ protected String getStatusMessage(IStatus status) {
+ if (fEncodingSupport != null) {
+ String message = fEncodingSupport.getStatusMessage(status);
+ if (message != null)
+ return message;
+ }
+ return super.getStatusMessage(status);
+ }
+
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method performs sets the input of the
+ * outline page after AbstractTextEditor has set input.
+ */
+ // protected void doSetInput(IEditorInput input) throws CoreException {
+ // super.doSetInput(input);
+ // if (fEncodingSupport != null)
+ // fEncodingSupport.reset();
+ // setOutlinePageInput(fOutlinePage, input);
+ // }
+ /*
+ * @see AbstractTextEditor#doSetInput
+ */
+ protected void doSetInput(IEditorInput input) throws CoreException {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (!(sourceViewer instanceof ISourceViewerExtension2)) {
+ setPreferenceStore(createCombinedPreferenceStore(input));
+ internalDoSetInput(input);
+ return;
+ }
+
+ // uninstall & unregister preference store listener
+ if (isBrowserLikeLinks())
+ disableBrowserLikeLinks();
+ getSourceViewerDecorationSupport(sourceViewer).uninstall();
+ ((ISourceViewerExtension2) sourceViewer).unconfigure();
+
+ setPreferenceStore(createCombinedPreferenceStore(input));
+
+ // install & register preference store listener
+ sourceViewer.configure(getSourceViewerConfiguration());
+ getSourceViewerDecorationSupport(sourceViewer).install(
+ getPreferenceStore());
+ if (isBrowserLikeLinks())
+ enableBrowserLikeLinks();
+
+ internalDoSetInput(input);
+ }
+
+ /*
+ * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
+ */
+ // public Object getViewPartInput() {
+ // return getEditorInput().getAdapter(IFile.class);
+ // }
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method adds any PHPEditor specific
+ * entries.
+ */
+ public void editorContextMenuAboutToShow(MenuManager menu) {
+ super.editorContextMenuAboutToShow(menu);
+ menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO,
+ new Separator(IContextMenuConstants.GROUP_OPEN));
+ menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(
+ IContextMenuConstants.GROUP_SHOW));
+
+ ActionContext context = new ActionContext(getSelectionProvider()
+ .getSelection());
+ fContextMenuGroup.setContext(context);
+ fContextMenuGroup.fillContextMenu(menu);
+ fContextMenuGroup.setContext(null);
+ // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format");
+ // //$NON-NLS-1$
+ //
+ // ActionContext context =
+ // new ActionContext(getSelectionProvider().getSelection());
+ // fContextMenuGroup.setContext(context);
+ // fContextMenuGroup.fillContextMenu(menu);
+ // fContextMenuGroup.setContext(null);
+ }
+
+ /**
+ * Creates the outline page used with this editor.
+ */
+ protected JavaOutlinePage createOutlinePage() {
+ JavaOutlinePage page = new JavaOutlinePage(fOutlinerContextMenuId, this);
+ fOutlineSelectionChangedListener.install(page);
+ setOutlinePageInput(page, getEditorInput());
+ return page;
+ }
+
+ /**
+ * Informs the editor that its outliner has been closed.
+ */
+ public void outlinePageClosed() {
+ if (fOutlinePage != null) {
+ fOutlineSelectionChangedListener.uninstall(fOutlinePage);
+ fOutlinePage = null;
+ resetHighlightRange();
+ }
+ }
+
+ /**
+ * Synchronizes the outliner selection with the given element position in
+ * the editor.
+ *
+ * @param element
+ * the java element to select
+ */
+ protected void synchronizeOutlinePage(ISourceReference element) {
+ synchronizeOutlinePage(element, true);
+ }
+
+ /**
+ * Synchronizes the outliner selection with the given element position in
+ * the editor.
+ *
+ * @param element
+ * the java element to select
+ * @param checkIfOutlinePageActive
+ * true
if check for active outline page needs to
+ * be done
+ */
+ protected void synchronizeOutlinePage(ISourceReference element,
+ boolean checkIfOutlinePageActive) {
+ if (fOutlinePage != null && element != null
+ && !(checkIfOutlinePageActive && isJavaOutlinePageActive())) {
+ fOutlineSelectionChangedListener.uninstall(fOutlinePage);
+ fOutlinePage.select(element);
+ fOutlineSelectionChangedListener.install(fOutlinePage);
+ }
+ }
+
+ /**
+ * Synchronizes the outliner selection with the actual cursor position in
+ * the editor.
+ */
+ public void synchronizeOutlinePageSelection() {
+ synchronizeOutlinePage(computeHighlightRangeSourceReference());
+
+ // ISourceViewer sourceViewer = getSourceViewer();
+ // if (sourceViewer == null || fOutlinePage == null)
+ // return;
+ //
+ // StyledText styledText = sourceViewer.getTextWidget();
+ // if (styledText == null)
+ // return;
+ //
+ // int caret = 0;
+ // if (sourceViewer instanceof ITextViewerExtension3) {
+ // ITextViewerExtension3 extension = (ITextViewerExtension3)
+ // sourceViewer;
+ // caret =
+ // extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
+ // } else {
+ // int offset = sourceViewer.getVisibleRegion().getOffset();
+ // caret = offset + styledText.getCaretOffset();
+ // }
+ //
+ // IJavaElement element = getElementAt(caret);
+ // if (element instanceof ISourceReference) {
+ // fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
+ // fOutlinePage.select((ISourceReference) element);
+ // fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
+ // }
+ }
+
+ protected void setSelection(ISourceReference reference, boolean moveCursor) {
+
+ ISelection selection = getSelectionProvider().getSelection();
+ if (selection instanceof TextSelection) {
+ TextSelection textSelection = (TextSelection) selection;
+ if (textSelection.getOffset() != 0
+ || textSelection.getLength() != 0)
+ markInNavigationHistory();
+ }
+
+ if (reference != null) {
+
+ StyledText textWidget = null;
+
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer != null)
+ textWidget = sourceViewer.getTextWidget();
+
+ if (textWidget == null)
+ return;
+
+ try {
+
+ ISourceRange range = reference.getSourceRange();
+ if (range == null)
+ return;
+
+ int offset = range.getOffset();
+ int length = range.getLength();
+
+ if (offset < 0 || length < 0)
+ return;
+
+ textWidget.setRedraw(false);
+
+ setHighlightRange(offset, length, moveCursor);
+
+ if (!moveCursor)
+ return;
+
+ offset = -1;
+ length = -1;
+
+ if (reference instanceof IMember) {
+ range = ((IMember) reference).getNameRange();
+ if (range != null) {
+ offset = range.getOffset();
+ length = range.getLength();
+ }
+ }
+ // else if (reference instanceof IImportDeclaration) {
+ // String name= ((IImportDeclaration)
+ // reference).getElementName();
+ // if (name != null && name.length() > 0) {
+ // String content= reference.getSource();
+ // if (content != null) {
+ // offset= range.getOffset() + content.indexOf(name);
+ // length= name.length();
+ // }
+ // }
+ // } else if (reference instanceof IPackageDeclaration) {
+ // String name= ((IPackageDeclaration)
+ // reference).getElementName();
+ // if (name != null && name.length() > 0) {
+ // String content= reference.getSource();
+ // if (content != null) {
+ // offset= range.getOffset() + content.indexOf(name);
+ // length= name.length();
+ // }
+ // }
+ // }
+
+ if (offset > -1 && length > 0) {
+ sourceViewer.revealRange(offset, length);
+ sourceViewer.setSelectedRange(offset, length);
+ }
+
+ } catch (JavaModelException x) {
+ } catch (IllegalArgumentException x) {
+ } finally {
+ if (textWidget != null)
+ textWidget.setRedraw(true);
+ }
+
+ } else if (moveCursor) {
+ resetHighlightRange();
+ }
+
+ markInNavigationHistory();
+ }
+
+ public void setSelection(IJavaElement element) {
+ if (element == null || element instanceof ICompilationUnit) { // ||
+ // element
+ // instanceof
+ // IClassFile)
+ // {
+ /*
+ * If the element is an ICompilationUnit this unit is either the
+ * input of this editor or not being displayed. In both cases,
+ * nothing should happened.
+ * (http://dev.eclipse.org/bugs/show_bug.cgi?id=5128)
+ */
+ return;
+ }
+
+ IJavaElement corresponding = getCorrespondingElement(element);
+ if (corresponding instanceof ISourceReference) {
+ ISourceReference reference = (ISourceReference) corresponding;
+ // set highlight range
+ setSelection(reference, true);
+ // set outliner selection
+ if (fOutlinePage != null) {
+ fOutlineSelectionChangedListener.uninstall(fOutlinePage);
+ fOutlinePage.select(reference);
+ fOutlineSelectionChangedListener.install(fOutlinePage);
+ }
+ }
+ }
+
+ public synchronized void editingScriptStarted() {
+ ++fIgnoreOutlinePageSelection;
+ }
+
+ public synchronized void editingScriptEnded() {
+ --fIgnoreOutlinePageSelection;
+ }
+
+ public synchronized boolean isEditingScriptRunning() {
+ return (fIgnoreOutlinePageSelection > 0);
+ }
+
+ /**
+ * The PHPEditor
implementation of this
+ * AbstractTextEditor
method performs gets the java content
+ * outline page if request is for a an outline page.
+ */
+ public Object getAdapter(Class required) {
+
+ if (IContentOutlinePage.class.equals(required)) {
+ if (fOutlinePage == null)
+ fOutlinePage = createOutlinePage();
+ return fOutlinePage;
+ }
+
+ if (IEncodingSupport.class.equals(required))
+ return fEncodingSupport;
+
+ if (required == IShowInTargetList.class) {
+ return new IShowInTargetList() {
+ public String[] getShowInTargetIds() {
+ return new String[] { JavaUI.ID_PACKAGES,
+ IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
+ }
+
+ };
+ }
+ if (fProjectionSupport != null) {
+ Object adapter = fProjectionSupport.getAdapter(getSourceViewer(),
+ required);
+ if (adapter != null)
+ return adapter;
+ }
+
+ return super.getAdapter(required);
+ }
+
+ // public Object getAdapter(Class required) {
+ // if (IContentOutlinePage.class.equals(required)) {
+ // if (fOutlinePage == null) {
+ // fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
+ // if (getEditorInput() != null)
+ // fOutlinePage.setInput(getEditorInput());
+ // }
+ // return fOutlinePage;
+ // }
+ //
+ // if (IEncodingSupport.class.equals(required))
+ // return fEncodingSupport;
+ //
+ // return super.getAdapter(required);
+ // }
+
+ protected void doSelectionChanged(SelectionChangedEvent event) {
+ ISourceReference reference = null;
+
+ ISelection selection = event.getSelection();
+ Iterator iter = ((IStructuredSelection) selection).iterator();
+ while (iter.hasNext()) {
+ Object o = iter.next();
+ if (o instanceof ISourceReference) {
+ reference = (ISourceReference) o;
+ break;
+ }
+ }
+
+ if (!isActivePart() && WebUI.getActivePage() != null)
+ WebUI.getActivePage().bringToTop(this);
+
+ try {
+ editingScriptStarted();
+ setSelection(reference, !isActivePart());
+ } finally {
+ editingScriptEnded();
+ }
+ }
+
+ /*
+ * @see AbstractTextEditor#adjustHighlightRange(int, int)
+ */
+ protected void adjustHighlightRange(int offset, int length) {
+
+ try {
+
+ IJavaElement element = getElementAt(offset);
+ while (element instanceof ISourceReference) {
+ ISourceRange range = ((ISourceReference) element)
+ .getSourceRange();
+ if (offset < range.getOffset() + range.getLength()
+ && range.getOffset() < offset + length) {
+
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+ extension.exposeModelRange(new Region(
+ range.getOffset(), range.getLength()));
+ }
+
+ setHighlightRange(range.getOffset(), range.getLength(),
+ true);
+ if (fOutlinePage != null) {
+ fOutlineSelectionChangedListener
+ .uninstall(fOutlinePage);
+ fOutlinePage.select((ISourceReference) element);
+ fOutlineSelectionChangedListener.install(fOutlinePage);
+ }
+
+ return;
+ }
+ element = element.getParent();
+ }
+
+ } catch (JavaModelException x) {
+ PHPeclipsePlugin.log(x.getStatus());
+ }
+
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+ extension.exposeModelRange(new Region(offset, length));
+ } else {
+ resetHighlightRange();
+ }
+
+ }
+
+ protected boolean isActivePart() {
+ IWorkbenchWindow window = getSite().getWorkbenchWindow();
+ IPartService service = window.getPartService();
+ IWorkbenchPart part = service.getActivePart();
+ return part != null && part.equals(this);
+ }
+
+ // public void openContextHelp() {
+ // IDocument doc =
+ // this.getDocumentProvider().getDocument(this.getEditorInput());
+ // ITextSelection selection = (ITextSelection)
+ // this.getSelectionProvider().getSelection();
+ // int pos = selection.getOffset();
+ // String word = getFunctionName(doc, pos);
+ // openContextHelp(word);
+ // }
+ //
+ // private void openContextHelp(String word) {
+ // open(word);
+ // }
+ //
+ // public static void open(String word) {
+ // IHelp help = WorkbenchHelp.getHelpSupport();
+ // if (help != null) {
+ // IHelpResource helpResource = new PHPFunctionHelpResource(word);
+ // WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
+ // } else {
+ // // showMessage(shell, dialogTitle, ActionMessages.getString("Open help
+ // not available"), false); //$NON-NLS-1$
+ // }
+ // }
+
+ // private String getFunctionName(IDocument doc, int pos) {
+ // Point word = PHPWordExtractor.findWord(doc, pos);
+ // if (word != null) {
+ // try {
+ // return doc.get(word.x, word.y).replace('_', '-');
+ // } catch (BadLocationException e) {
+ // }
+ // }
+ // return "";
+ // }
+
+ /*
+ * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
+ */
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+
+ try {
+
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null)
+ return;
+
+ String property = event.getProperty();
+
+ if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
+ Object value = event.getNewValue();
+ if (value instanceof Integer) {
+ sourceViewer.getTextWidget().setTabs(
+ ((Integer) value).intValue());
+ } else if (value instanceof String) {
+ try {
+ sourceViewer.getTextWidget().setTabs(
+ Integer.parseInt((String) value));
+ } catch (NumberFormatException e) {
+ // bug #1038071 - set default tab:
+ sourceViewer.getTextWidget().setTabs(80);
+ }
+ }
+ return;
+ }
+
+ // if (OVERVIEW_RULER.equals(property)) {
+ // if (isOverviewRulerVisible())
+ // showOverviewRuler();
+ // else
+ // hideOverviewRuler();
+ // return;
+ // }
+
+ // if (LINE_NUMBER_RULER.equals(property)) {
+ // if (isLineNumberRulerVisible())
+ // showLineNumberRuler();
+ // else
+ // hideLineNumberRuler();
+ // return;
+ // }
+
+ // if (fLineNumberRulerColumn != null
+ // && (LINE_NUMBER_COLOR.equals(property) ||
+ // PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) ||
+ // PREFERENCE_COLOR_BACKGROUND.equals(property))) {
+ //
+ // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
+ // }
+
+ if (isJavaEditorHoverProperty(property))
+ updateHoverBehavior();
+
+ if (BROWSER_LIKE_LINKS.equals(property)) {
+ if (isBrowserLikeLinks())
+ enableBrowserLikeLinks();
+ else
+ disableBrowserLikeLinks();
+ return;
+ }
+
+ if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE
+ .equals(property)) {
+ if (event.getNewValue() instanceof Boolean) {
+ Boolean disable = (Boolean) event.getNewValue();
+ enableOverwriteMode(!disable.booleanValue());
+ }
+ return;
+ }
+
+ boolean newBooleanValue = false;
+ Object newValue = event.getNewValue();
+ if (newValue != null)
+ newBooleanValue = Boolean.valueOf(newValue.toString())
+ .booleanValue();
+
+ if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE
+ .equals(property)) {
+ if (newBooleanValue)
+ selectionChanged();
+ return;
+ }
+
+ if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) {
+ if (newBooleanValue != fMarkOccurrenceAnnotations) {
+ fMarkOccurrenceAnnotations = newBooleanValue;
+ if (!fMarkOccurrenceAnnotations)
+ uninstallOccurrencesFinder();
+ else
+ installOccurrencesFinder();
+ }
+ return;
+ }
+
+ if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) {
+ fStickyOccurrenceAnnotations = newBooleanValue;
+ return;
+ }
+ // }
+ // }
+ // if
+ // (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property))
+ // {
+ // if (event.getNewValue() instanceof Boolean) {
+ // boolean stickyOccurrenceAnnotations=
+ // ((Boolean)event.getNewValue()).booleanValue();
+ // if (stickyOccurrenceAnnotations != fStickyOccurrenceAnnotations)
+ // {
+
+ ((PHPSourceViewerConfiguration) getSourceViewerConfiguration())
+ .handlePropertyChangeEvent(event);
+
+ // if (affectsOverrideIndicatorAnnotations(event)) {
+ // if (isShowingOverrideIndicators()) {
+ // if (fOverrideIndicatorManager == null)
+ // installOverrideIndicator(true);
+ // } else {
+ // if (fOverrideIndicatorManager != null)
+ // uninstallOverrideIndicator();
+ // }
+ // return;
+ // }
+
+ if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) {
+ if (sourceViewer instanceof ProjectionViewer) {
+ ProjectionViewer projectionViewer = (ProjectionViewer) sourceViewer;
+ if (fProjectionModelUpdater != null)
+ fProjectionModelUpdater.uninstall();
+ // either freshly enabled or provider changed
+ fProjectionModelUpdater = WebUI.getDefault()
+ .getFoldingStructureProviderRegistry()
+ .getCurrentFoldingProvider();
+ if (fProjectionModelUpdater != null) {
+ fProjectionModelUpdater.install(this, projectionViewer);
+ }
+ }
+ return;
+ }
+ } finally {
+ super.handlePreferenceStoreChanged(event);
+ }
+ }
+
+ // /*
+ // * @see
+ // AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
+ // */
+ // protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ //
+ // try {
+ //
+ // ISourceViewer sourceViewer = getSourceViewer();
+ // if (sourceViewer == null)
+ // return;
+ //
+ // String property = event.getProperty();
+ //
+ // // if
+ // (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
+ // // Object value= event.getNewValue();
+ // // if (value instanceof Integer) {
+ // // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
+ // // } else if (value instanceof String) {
+ // // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String)
+ // value));
+ // // }
+ // // return;
+ // // }
+ //
+ // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
+ // if (isLineNumberRulerVisible())
+ // showLineNumberRuler();
+ // else
+ // hideLineNumberRuler();
+ // return;
+ // }
+ //
+ // if (fLineNumberRulerColumn != null
+ // && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
+ // || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
+ // || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
+ //
+ // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
+ // }
+ //
+ // } finally {
+ // super.handlePreferenceStoreChanged(event);
+ // }
+ // }
+
+ // private boolean isJavaEditorHoverProperty(String property) {
+ // return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
+ // || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
+ // || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
+ // || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
+ // || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
+ // || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
+ // || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
+ // || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
+ // }
+
+ /**
+ * Shows the line number ruler column.
+ */
+ // private void showLineNumberRuler() {
+ // IVerticalRuler v = getVerticalRuler();
+ // if (v instanceof CompositeRuler) {
+ // CompositeRuler c = (CompositeRuler) v;
+ // c.addDecorator(1, createLineNumberRulerColumn());
+ // }
+ // }
+ private boolean isJavaEditorHoverProperty(String property) {
+ return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property);
+ }
+
+ /**
+ * Return whether the browser like links should be enabled according to the
+ * preference store settings.
+ *
+ * @return true
if the browser like links should be enabled
+ */
+ private boolean isBrowserLikeLinks() {
+ IPreferenceStore store = getPreferenceStore();
+ return store.getBoolean(BROWSER_LIKE_LINKS);
+ }
+
+ /**
+ * Enables browser like links.
+ */
+ private void enableBrowserLikeLinks() {
+ if (fMouseListener == null) {
+ fMouseListener = new MouseClickListener();
+ fMouseListener.install();
+ }
+ }
+
+ /**
+ * Disables browser like links.
+ */
+ private void disableBrowserLikeLinks() {
+ if (fMouseListener != null) {
+ fMouseListener.uninstall();
+ fMouseListener = null;
+ }
+ }
+
+ /**
+ * Handles a property change event describing a change of the java core's
+ * preferences and updates the preference related editor properties.
+ *
+ * @param event
+ * the property change event
+ */
+ protected void handlePreferencePropertyChanged(
+ org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
+ if (COMPILER_TASK_TAGS.equals(event.getProperty())) {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer != null
+ && affectsTextPresentation(new PropertyChangeEvent(event
+ .getSource(), event.getProperty(), event
+ .getOldValue(), event.getNewValue())))
+ sourceViewer.invalidateTextPresentation();
+ }
+ if (PreferenceConstants.EDITOR_WRAP_WORDS.equals(event.getProperty())) {
+ setWordWrap();
+ }
+ }
+
+ /**
+ * Return whether the line number ruler column should be visible according
+ * to the preference store settings.
+ *
+ * @return true
if the line numbers should be visible
+ */
+ // protected boolean isLineNumberRulerVisible() {
+ // IPreferenceStore store = getPreferenceStore();
+ // return store.getBoolean(LINE_NUMBER_RULER);
+ // }
+ /**
+ * Hides the line number ruler column.
+ */
+ // private void hideLineNumberRuler() {
+ // IVerticalRuler v = getVerticalRuler();
+ // if (v instanceof CompositeRuler) {
+ // CompositeRuler c = (CompositeRuler) v;
+ // try {
+ // c.removeDecorator(1);
+ // } catch (Throwable e) {
+ // }
+ // }
+ // }
+ /*
+ * @see AbstractTextEditor#handleCursorPositionChanged()
+ */
+ // protected void handleCursorPositionChanged() {
+ // super.handleCursorPositionChanged();
+ // if (!isEditingScriptRunning() && fUpdater != null)
+ // fUpdater.post();
+ // }
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleElementContentReplaced()
+ */
+ protected void handleElementContentReplaced() {
+ super.handleElementContentReplaced();
+ if (fProjectionModelUpdater != null)
+ fProjectionModelUpdater.initialize();
+ }
+
+ /**
+ * Initializes the given line number ruler column from the preference store.
+ *
+ * @param rulerColumn
+ * the ruler column to be initialized
+ */
+ // protected void initializeLineNumberRulerColumn(LineNumberRulerColumn
+ // rulerColumn) {
+ // JavaTextTools textTools =
+ // PHPeclipsePlugin.getDefault().getJavaTextTools();
+ // IColorManager manager = textTools.getColorManager();
+ //
+ // IPreferenceStore store = getPreferenceStore();
+ // if (store != null) {
+ //
+ // RGB rgb = null;
+ // // foreground color
+ // if (store.contains(LINE_NUMBER_COLOR)) {
+ // if (store.isDefault(LINE_NUMBER_COLOR))
+ // rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
+ // else
+ // rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
+ // }
+ // rulerColumn.setForeground(manager.getColor(rgb));
+ //
+ // rgb = null;
+ // // background color
+ // if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
+ // if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
+ // if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
+ // rgb = PreferenceConverter.getDefaultColor(store,
+ // PREFERENCE_COLOR_BACKGROUND);
+ // else
+ // rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
+ // }
+ // }
+ // rulerColumn.setBackground(manager.getColor(rgb));
+ // }
+ // }
+ /**
+ * Creates a new line number ruler column that is appropriately initialized.
+ */
+ // protected IVerticalRulerColumn createLineNumberRulerColumn() {
+ // fLineNumberRulerColumn = new LineNumberRulerColumn();
+ // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
+ // return fLineNumberRulerColumn;
+ // }
+ /*
+ * @see AbstractTextEditor#createVerticalRuler()
+ */
+ // protected IVerticalRuler createVerticalRuler() {
+ // CompositeRuler ruler = new CompositeRuler();
+ // ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
+ // if (isLineNumberRulerVisible())
+ // ruler.addDecorator(1, createLineNumberRulerColumn());
+ // return ruler;
+ // }
+ // private static IRegion getSignedSelection(ITextViewer viewer) {
+ //
+ // StyledText text = viewer.getTextWidget();
+ // int caretOffset = text.getCaretOffset();
+ // Point selection = text.getSelection();
+ //
+ // // caret left
+ // int offset, length;
+ // if (caretOffset == selection.x) {
+ // offset = selection.y;
+ // length = selection.x - selection.y;
+ //
+ // // caret right
+ // } else {
+ // offset = selection.x;
+ // length = selection.y - selection.x;
+ // }
+ //
+ // return new Region(offset, length);
+ // }
+ protected IRegion getSignedSelection(ISourceViewer sourceViewer) {
+ StyledText text = sourceViewer.getTextWidget();
+ Point selection = text.getSelectionRange();
+
+ if (text.getCaretOffset() == selection.x) {
+ selection.x = selection.x + selection.y;
+ selection.y = -selection.y;
+ }
+
+ selection.x = widgetOffset2ModelOffset(sourceViewer, selection.x);
+
+ return new Region(selection.x, selection.y);
+ }
+
+ /** Preference key for matching brackets */
+ protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
+
+ /** Preference key for matching brackets color */
+ protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
+
+ /** Preference key for highlighting current line */
+ // protected final static String CURRENT_LINE =
+ // PreferenceConstants.EDITOR_CURRENT_LINE;
+ /** Preference key for highlight color of current line */
+ // protected final static String CURRENT_LINE_COLOR =
+ // PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
+ /** Preference key for showing print marging ruler */
+ // protected final static String PRINT_MARGIN =
+ // PreferenceConstants.EDITOR_PRINT_MARGIN;
+ /** Preference key for print margin ruler color */
+ // protected final static String PRINT_MARGIN_COLOR =
+ // PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
+ /** Preference key for print margin ruler column */
+ // protected final static String PRINT_MARGIN_COLUMN =
+ // PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
+ /** Preference key for error indication */
+ // protected final static String ERROR_INDICATION =
+ // PreferenceConstants.EDITOR_PROBLEM_INDICATION;
+ /** Preference key for error color */
+ // protected final static String ERROR_INDICATION_COLOR =
+ // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
+ /** Preference key for warning indication */
+ // protected final static String WARNING_INDICATION =
+ // PreferenceConstants.EDITOR_WARNING_INDICATION;
+ /** Preference key for warning color */
+ // protected final static String WARNING_INDICATION_COLOR =
+ // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
+ /** Preference key for task indication */
+ protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
+
+ /** Preference key for task color */
+ protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
+
+ /** Preference key for bookmark indication */
+ protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
+
+ /** Preference key for bookmark color */
+ protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
+
+ /** Preference key for search result indication */
+ protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
+
+ /** Preference key for search result color */
+ protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
+
+ /** Preference key for unknown annotation indication */
+ protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
+
+ /** Preference key for unknown annotation color */
+ protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
+
+ /** Preference key for shwoing the overview ruler */
+ protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
+
+ /** Preference key for error indication in overview ruler */
+ protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for warning indication in overview ruler */
+ protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for task indication in overview ruler */
+ protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for bookmark indication in overview ruler */
+ protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for search result indication in overview ruler */
+ protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for unknown annotation indication in overview ruler */
+ protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
+
+ // /** Preference key for compiler task tags */
+ // private final static String COMPILER_TASK_TAGS=
+ // JavaCore.COMPILER_TASK_TAGS;
+ /** Preference key for browser like links */
+ private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS;
+
+ /** Preference key for key modifier of browser like links */
+ private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER;
+
+ /**
+ * Preference key for key modifier mask of browser like links. The value is
+ * only used if the value of EDITOR_BROWSER_LIKE_LINKS
cannot
+ * be resolved to valid SWT modifier bits.
+ *
+ * @since 2.1.1
+ */
+ private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK;
+
+ private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
+
+ private static boolean isBracket(char character) {
+ for (int i = 0; i != BRACKETS.length; ++i)
+ if (character == BRACKETS[i])
+ return true;
+ return false;
+ }
+
+ private static boolean isSurroundedByBrackets(IDocument document, int offset) {
+ if (offset == 0 || offset == document.getLength())
+ return false;
+
+ try {
+ return isBracket(document.getChar(offset - 1))
+ && isBracket(document.getChar(offset));
+
+ } catch (BadLocationException e) {
+ return false;
+ }
+ }
+
+ // protected void configureSourceViewerDecorationSupport() {
+ //
+ // fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
+ //
+ // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+ // AnnotationType.UNKNOWN,
+ // UNKNOWN_INDICATION_COLOR,
+ // UNKNOWN_INDICATION,
+ // UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
+ // 0);
+ // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+ // AnnotationType.BOOKMARK,
+ // BOOKMARK_INDICATION_COLOR,
+ // BOOKMARK_INDICATION,
+ // BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
+ // 1);
+ // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+ // AnnotationType.TASK,
+ // TASK_INDICATION_COLOR,
+ // TASK_INDICATION,
+ // TASK_INDICATION_IN_OVERVIEW_RULER,
+ // 2);
+ // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+ // AnnotationType.SEARCH,
+ // SEARCH_RESULT_INDICATION_COLOR,
+ // SEARCH_RESULT_INDICATION,
+ // SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
+ // 3);
+ // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+ // AnnotationType.WARNING,
+ // WARNING_INDICATION_COLOR,
+ // WARNING_INDICATION,
+ // WARNING_INDICATION_IN_OVERVIEW_RULER,
+ // 4);
+ // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+ // AnnotationType.ERROR,
+ // ERROR_INDICATION_COLOR,
+ // ERROR_INDICATION,
+ // ERROR_INDICATION_IN_OVERVIEW_RULER,
+ // 5);
+ //
+ // fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE,
+ // CURRENT_LINE_COLOR);
+ // fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN,
+ // PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
+ // fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS,
+ // MATCHING_BRACKETS_COLOR);
+ //
+ // fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey());
+ //
+ // }
+ /**
+ * Returns the Java element wrapped by this editors input.
+ *
+ * @return the Java element wrapped by this editors input.
+ * @since 3.0
+ */
+ abstract protected IJavaElement getInputJavaElement();
+
+ protected void updateStatusLine() {
+ ITextSelection selection = (ITextSelection) getSelectionProvider()
+ .getSelection();
+ Annotation annotation = getAnnotation(selection.getOffset(), selection
+ .getLength());
+ setStatusLineErrorMessage(null);
+ setStatusLineMessage(null);
+ if (annotation != null) {
+ try {
+ fIsUpdatingAnnotationViews = true;
+ updateAnnotationViews(annotation);
+ } finally {
+ fIsUpdatingAnnotationViews = false;
+ }
+ if (annotation instanceof IJavaAnnotation
+ && ((IJavaAnnotation) annotation).isProblem())
+ setStatusLineMessage(annotation.getText());
+ }
+ }
+
+ /**
+ * Jumps to the matching bracket.
+ */
+ public void gotoMatchingBracket() {
+
+ ISourceViewer sourceViewer = getSourceViewer();
+ IDocument document = sourceViewer.getDocument();
+ if (document == null)
+ return;
+
+ IRegion selection = getSignedSelection(sourceViewer);
+
+ int selectionLength = Math.abs(selection.getLength());
+ if (selectionLength > 1) {
+ setStatusLineErrorMessage(PHPEditorMessages
+ .getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$
+ sourceViewer.getTextWidget().getDisplay().beep();
+ return;
+ }
+
+ // #26314
+ int sourceCaretOffset = selection.getOffset() + selection.getLength();
+ if (isSurroundedByBrackets(document, sourceCaretOffset))
+ sourceCaretOffset -= selection.getLength();
+
+ IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
+ if (region == null) {
+ setStatusLineErrorMessage(PHPEditorMessages
+ .getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$
+ sourceViewer.getTextWidget().getDisplay().beep();
+ return;
+ }
+
+ int offset = region.getOffset();
+ int length = region.getLength();
+
+ if (length < 1)
+ return;
+
+ int anchor = fBracketMatcher.getAnchor();
+ int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset
+ + length - 1;
+
+ boolean visible = false;
+ if (sourceViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
+ visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
+ } else {
+ IRegion visibleRegion = sourceViewer.getVisibleRegion();
+ visible = (targetOffset >= visibleRegion.getOffset() && targetOffset < visibleRegion
+ .getOffset()
+ + visibleRegion.getLength());
+ }
+
+ if (!visible) {
+ setStatusLineErrorMessage(PHPEditorMessages
+ .getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$
+ sourceViewer.getTextWidget().getDisplay().beep();
+ return;
+ }
+
+ if (selection.getLength() < 0)
+ targetOffset -= selection.getLength();
+
+ sourceViewer.setSelectedRange(targetOffset, selection.getLength());
+ sourceViewer.revealRange(targetOffset, selection.getLength());
+ }
+
+ /**
+ * Ses the given message as error message to this editor's status line.
+ *
+ * @param msg
+ * message to be set
+ */
+ protected void setStatusLineErrorMessage(String msg) {
+ IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
+ if (statusLine != null)
+ statusLine.setMessage(true, msg, null);
+ }
+
+ /**
+ * Sets the given message as message to this editor's status line.
+ *
+ * @param msg
+ * message to be set
+ * @since 3.0
+ */
+ protected void setStatusLineMessage(String msg) {
+ IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
+ if (statusLine != null)
+ statusLine.setMessage(false, msg, null);
+ }
+
+ /**
+ * Returns the annotation closest to the given range respecting the given
+ * direction. If an annotation is found, the annotations current position is
+ * copied into the provided annotation position.
+ *
+ * @param offset
+ * the region offset
+ * @param length
+ * the region length
+ * @param forward
+ * true
for forwards, false
for
+ * backward
+ * @param annotationPosition
+ * the position of the found annotation
+ * @return the found annotation
+ */
+ private Annotation getNextAnnotation(final int offset, final int length,
+ boolean forward, Position annotationPosition) {
+
+ Annotation nextAnnotation = null;
+ Position nextAnnotationPosition = null;
+ Annotation containingAnnotation = null;
+ Position containingAnnotationPosition = null;
+ boolean currentAnnotation = false;
+
+ IDocument document = getDocumentProvider()
+ .getDocument(getEditorInput());
+ int endOfDocument = document.getLength();
+ int distance = Integer.MAX_VALUE;
+
+ IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+ getEditorInput());
+ Iterator e = new JavaAnnotationIterator(model, true, true);
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+ if ((a instanceof IJavaAnnotation)
+ && ((IJavaAnnotation) a).hasOverlay()
+ || !isNavigationTarget(a))
+ continue;
+
+ Position p = model.getPosition(a);
+ if (p == null)
+ continue;
+
+ if (forward && p.offset == offset || !forward
+ && p.offset + p.getLength() == offset + length) {// ||
+ // p.includes(offset))
+ // {
+ if (containingAnnotation == null
+ || (forward
+ && p.length >= containingAnnotationPosition.length || !forward
+ && p.length >= containingAnnotationPosition.length)) {
+ containingAnnotation = a;
+ containingAnnotationPosition = p;
+ currentAnnotation = p.length == length;
+ }
+ } else {
+ int currentDistance = 0;
+
+ if (forward) {
+ currentDistance = p.getOffset() - offset;
+ if (currentDistance < 0)
+ currentDistance = endOfDocument + currentDistance;
+
+ if (currentDistance < distance
+ || currentDistance == distance
+ && p.length < nextAnnotationPosition.length) {
+ distance = currentDistance;
+ nextAnnotation = a;
+ nextAnnotationPosition = p;
+ }
+ } else {
+ currentDistance = offset + length
+ - (p.getOffset() + p.length);
+ if (currentDistance < 0)
+ currentDistance = endOfDocument + currentDistance;
+
+ if (currentDistance < distance
+ || currentDistance == distance
+ && p.length < nextAnnotationPosition.length) {
+ distance = currentDistance;
+ nextAnnotation = a;
+ nextAnnotationPosition = p;
+ }
+ }
+ }
+ }
+ if (containingAnnotationPosition != null
+ && (!currentAnnotation || nextAnnotation == null)) {
+ annotationPosition.setOffset(containingAnnotationPosition
+ .getOffset());
+ annotationPosition.setLength(containingAnnotationPosition
+ .getLength());
+ return containingAnnotation;
+ }
+ if (nextAnnotationPosition != null) {
+ annotationPosition.setOffset(nextAnnotationPosition.getOffset());
+ annotationPosition.setLength(nextAnnotationPosition.getLength());
+ }
+
+ return nextAnnotation;
+ }
+
+ /**
+ * Returns the annotation overlapping with the given range or
+ * null
.
+ *
+ * @param offset
+ * the region offset
+ * @param length
+ * the region length
+ * @return the found annotation or null
+ * @since 3.0
+ */
+ private Annotation getAnnotation(int offset, int length) {
+ IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+ getEditorInput());
+ Iterator e = new JavaAnnotationIterator(model, true, true);
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+ if (!isNavigationTarget(a))
+ continue;
+
+ Position p = model.getPosition(a);
+ if (p != null && p.overlapsWith(offset, length))
+ return a;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns whether the given annotation is configured as a target for the
+ * "Go to Next/Previous Annotation" actions
+ *
+ * @param annotation
+ * the annotation
+ * @return true
if this is a target, false
+ * otherwise
+ * @since 3.0
+ */
+ protected boolean isNavigationTarget(Annotation annotation) {
+ Preferences preferences = EditorsUI.getPluginPreferences();
+ AnnotationPreference preference = getAnnotationPreferenceLookup()
+ .getAnnotationPreference(annotation);
+ // See bug 41689
+ // String key= forward ? preference.getIsGoToNextNavigationTargetKey() :
+ // preference.getIsGoToPreviousNavigationTargetKey();
+ String key = preference == null ? null : preference
+ .getIsGoToNextNavigationTargetKey();
+ return (key != null && preferences.getBoolean(key));
+ }
+
+ /**
+ * Returns a segmentation of the line of the given document appropriate for
+ * bidi rendering. The default implementation returns only the string
+ * literals of a php code line as segments.
+ *
+ * @param document
+ * the document
+ * @param lineOffset
+ * the offset of the line
+ * @return the line's bidi segmentation
+ * @throws BadLocationException
+ * in case lineOffset is not valid in document
+ */
+ public static int[] getBidiLineSegments(IDocument document, int lineOffset)
+ throws BadLocationException {
+
+ IRegion line = document.getLineInformationOfOffset(lineOffset);
+ ITypedRegion[] linePartitioning = document.computePartitioning(
+ lineOffset, line.getLength());
+
+ List segmentation = new ArrayList();
+ for (int i = 0; i < linePartitioning.length; i++) {
+ if (IPHPPartitions.PHP_STRING_DQ.equals(linePartitioning[i]
+ .getType())) {
+ segmentation.add(linePartitioning[i]);
+ } else if (IPHPPartitions.PHP_STRING_HEREDOC
+ .equals(linePartitioning[i].getType())) {
+ segmentation.add(linePartitioning[i]);
+ }
+ }
+
+ if (segmentation.size() == 0)
+ return null;
+
+ int size = segmentation.size();
+ int[] segments = new int[size * 2 + 1];
+
+ int j = 0;
+ for (int i = 0; i < size; i++) {
+ ITypedRegion segment = (ITypedRegion) segmentation.get(i);
+
+ if (i == 0)
+ segments[j++] = 0;
+
+ int offset = segment.getOffset() - lineOffset;
+ if (offset > segments[j - 1])
+ segments[j++] = offset;
+
+ if (offset + segment.getLength() >= line.getLength())
+ break;
+
+ segments[j++] = offset + segment.getLength();
+ }
+
+ if (j < segments.length) {
+ int[] result = new int[j];
+ System.arraycopy(segments, 0, result, 0, j);
+ segments = result;
+ }
+
+ return segments;
+ }
+
+ /**
+ * Returns a segmentation of the given line appropriate for bidi rendering.
+ * The default implementation returns only the string literals of a php code
+ * line as segments.
+ *
+ * @param lineOffset
+ * the offset of the line
+ * @param line
+ * the content of the line
+ * @return the line's bidi segmentation
+ */
+ protected int[] getBidiLineSegments(int lineOffset, String line) {
+ IDocumentProvider provider = getDocumentProvider();
+ if (provider != null && line != null && line.length() > 0) {
+ IDocument document = provider.getDocument(getEditorInput());
+ if (document != null)
+ try {
+ return getBidiLineSegments(document, lineOffset);
+ } catch (BadLocationException x) {
+ // ignore
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+ * int)
+ */
+ // protected final ISourceViewer createSourceViewer(
+ // Composite parent,
+ // IVerticalRuler ruler,
+ // int styles) {
+ // ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
+ // StyledText text = viewer.getTextWidget();
+ // text.addBidiSegmentListener(new BidiSegmentListener() {
+ // public void lineGetSegments(BidiSegmentEvent event) {
+ // event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
+ // }
+ // });
+ // // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
+ // return viewer;
+ // }
+ public final ISourceViewer getViewer() {
+ return getSourceViewer();
+ }
+
+ // protected void showOverviewRuler() {
+ // if (fOverviewRuler != null) {
+ // if (getSourceViewer() instanceof ISourceViewerExtension) {
+ // ((ISourceViewerExtension)
+ // getSourceViewer()).showAnnotationsOverview(true);
+ // fSourceViewerDecorationSupport.updateOverviewDecorations();
+ // }
+ // }
+ // }
+ //
+ // protected void hideOverviewRuler() {
+ // if (getSourceViewer() instanceof ISourceViewerExtension) {
+ // fSourceViewerDecorationSupport.hideAnnotationOverview();
+ // ((ISourceViewerExtension)
+ // getSourceViewer()).showAnnotationsOverview(false);
+ // }
+ // }
+
+ // protected boolean isOverviewRulerVisible() {
+ // IPreferenceStore store = getPreferenceStore();
+ // return store.getBoolean(OVERVIEW_RULER);
+ // }
+ /*
+ * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+ * int)
+ */
+ // protected ISourceViewer createJavaSourceViewer(
+ // Composite parent,
+ // IVerticalRuler ruler,
+ // IOverviewRuler overviewRuler,
+ // boolean isOverviewRulerVisible,
+ // int styles) {
+ // return new SourceViewer(parent, ruler, overviewRuler,
+ // isOverviewRulerVisible(), styles);
+ // }
+ /*
+ * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+ * int)
+ */
+ protected ISourceViewer createJavaSourceViewer(Composite parent,
+ IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
+ boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
+ return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(),
+ isOverviewRulerVisible(), styles, store);
+ }
+
+ /*
+ * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+ * int)
+ */
+ protected final ISourceViewer createSourceViewer(Composite parent,
+ IVerticalRuler verticalRuler, int styles) {
+
+ ISourceViewer viewer = createJavaSourceViewer(parent, verticalRuler,
+ getOverviewRuler(), isOverviewRulerVisible(), styles,
+ getPreferenceStore());
+
+ StyledText text = viewer.getTextWidget();
+ text.addBidiSegmentListener(new BidiSegmentListener() {
+ public void lineGetSegments(BidiSegmentEvent event) {
+ event.segments = getBidiLineSegments(event.lineOffset,
+ event.lineText);
+ }
+ });
+
+ // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
+
+ // ensure source viewer decoration support has been created and
+ // configured
+ getSourceViewerDecorationSupport(viewer);
+
+ return viewer;
+ }
+
+ /*
+ * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
+ */
+ protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+ return ((PHPSourceViewerConfiguration) getSourceViewerConfiguration())
+ .affectsTextPresentation(event)
+ || super.affectsTextPresentation(event);
+ }
+
+ //
+ // protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+ // JavaTextTools textTools =
+ // PHPeclipsePlugin.getDefault().getJavaTextTools();
+ // return textTools.affectsBehavior(event);
+ // }
+ /**
+ * Creates and returns the preference store for this Java editor with the
+ * given input.
+ *
+ * @param input
+ * The editor input for which to create the preference store
+ * @return the preference store for this editor
+ *
+ * @since 3.0
+ */
+ private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) {
+ List stores = new ArrayList(3);
+
+ IJavaProject project = EditorUtility.getJavaProject(input);
+ if (project != null)
+ stores.add(new OptionsAdapter(project.getOptions(false),
+ WebUI.getDefault().getMockupPreferenceStore(),
+ new OptionsAdapter.IPropertyChangeEventFilter() {
+
+ public boolean isFiltered(PropertyChangeEvent event) {
+ IJavaElement inputJavaElement = getInputJavaElement();
+ IJavaProject javaProject = inputJavaElement != null ? inputJavaElement
+ .getJavaProject()
+ : null;
+ if (javaProject == null)
+ return true;
+
+ return !javaProject.getProject().equals(
+ event.getSource());
+ }
+
+ }));
+
+ stores.add(WebUI.getDefault().getPreferenceStore());
+ stores.add(new PreferencesAdapter(JavaCore.getPlugin()
+ .getPluginPreferences()));
+ stores.add(EditorsUI.getPreferenceStore());
+
+ return new ChainedPreferenceStore((IPreferenceStore[]) stores
+ .toArray(new IPreferenceStore[stores.size()]));
+ }
+
+ /**
+ * Jumps to the error next according to the given direction.
+ */
+ public void gotoError(boolean forward) {
+
+ ISelectionProvider provider = getSelectionProvider();
+
+ ITextSelection s = (ITextSelection) provider.getSelection();
+ Position errorPosition = new Position(0, 0);
+ IJavaAnnotation nextError = getNextError(s.getOffset(), forward,
+ errorPosition);
+
+ if (nextError != null) {
+
+ IMarker marker = null;
+ if (nextError instanceof MarkerAnnotation)
+ marker = ((MarkerAnnotation) nextError).getMarker();
+ else {
+ Iterator e = nextError.getOverlaidIterator();
+ if (e != null) {
+ while (e.hasNext()) {
+ Object o = e.next();
+ if (o instanceof MarkerAnnotation) {
+ marker = ((MarkerAnnotation) o).getMarker();
+ break;
+ }
+ }
+ }
+ }
+
+ if (marker != null) {
+ IWorkbenchPage page = getSite().getPage();
+ IViewPart view = view = page
+ .findView("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$
+ if (view instanceof TaskList) {
+ StructuredSelection ss = new StructuredSelection(marker);
+ ((TaskList) view).setSelection(ss, true);
+ }
+ }
+
+ selectAndReveal(errorPosition.getOffset(), errorPosition
+ .getLength());
+ // setStatusLineErrorMessage(nextError.getMessage());
+
+ } else {
+
+ setStatusLineErrorMessage(null);
+
+ }
+ }
+
+ private IJavaAnnotation getNextError(int offset, boolean forward,
+ Position errorPosition) {
+
+ IJavaAnnotation nextError = null;
+ Position nextErrorPosition = null;
+
+ IDocument document = getDocumentProvider()
+ .getDocument(getEditorInput());
+ int endOfDocument = document.getLength();
+ int distance = 0;
+
+ IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+ getEditorInput());
+ Iterator e = new JavaAnnotationIterator(model, false);
+ while (e.hasNext()) {
+
+ IJavaAnnotation a = (IJavaAnnotation) e.next();
+ if (a.hasOverlay() || !a.isProblem())
+ continue;
+
+ Position p = model.getPosition((Annotation) a);
+ if (!p.includes(offset)) {
+
+ int currentDistance = 0;
+
+ if (forward) {
+ currentDistance = p.getOffset() - offset;
+ if (currentDistance < 0)
+ currentDistance = endOfDocument - offset
+ + p.getOffset();
+ } else {
+ currentDistance = offset - p.getOffset();
+ if (currentDistance < 0)
+ currentDistance = offset + endOfDocument
+ - p.getOffset();
+ }
+
+ if (nextError == null || currentDistance < distance) {
+ distance = currentDistance;
+ nextError = a;
+ nextErrorPosition = p;
+ }
+ }
+ }
+
+ if (nextErrorPosition != null) {
+ errorPosition.setOffset(nextErrorPosition.getOffset());
+ errorPosition.setLength(nextErrorPosition.getLength());
+ }
+
+ return nextError;
+ }
+
+ protected void uninstallOverrideIndicator() {
+ // if (fOverrideIndicatorManager != null) {
+ // fOverrideIndicatorManager.removeAnnotations();
+ // fOverrideIndicatorManager= null;
+ // }
+ }
+
+ protected void installOverrideIndicator(boolean waitForReconcilation) {
+ uninstallOverrideIndicator();
+ IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+ getEditorInput());
+ final IJavaElement inputElement = getInputJavaElement();
+
+ if (model == null || inputElement == null)
+ return;
+
+ // fOverrideIndicatorManager= new OverrideIndicatorManager(model,
+ // inputElement, null);
+ //
+ // if (provideAST) {
+ // Job job= new
+ // Job(JavaEditorMessages.getString("OverrideIndicatorManager.intallJob"))
+ // {
+ // //$NON-NLS-1$
+ // /*
+ // * @see
+ // org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ // * @since 3.0
+ // */
+ // protected IStatus run(IProgressMonitor monitor) {
+ // CompilationUnit ast=
+ // JavaPlugin.getDefault().getASTProvider().getAST(inputElement, true,
+ // null);
+ // if (fOverrideIndicatorManager != null) // editor might have been
+ // closed
+ // in the meanwhile
+ // fOverrideIndicatorManager.reconciled(ast, true, monitor);
+ // return Status.OK_STATUS;
+ // }
+ // };
+ // job.setPriority(Job.DECORATE);
+ // job.setSystem(true);
+ // job.schedule();
+ // }
+ }
+
+ /**
+ * Tells whether override indicators are shown.
+ *
+ * @return true
if the override indicators are shown
+ * @since 3.0
+ */
+ // protected boolean isShowingOverrideIndicators() {
+ // AnnotationPreference preference=
+ // getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE);
+ // IPreferenceStore store= getPreferenceStore();
+ // return getBoolean(store, preference.getHighlightPreferenceKey())
+ // || getBoolean(store, preference.getVerticalRulerPreferenceKey())
+ // || getBoolean(store, preference.getOverviewRulerPreferenceKey())
+ // || getBoolean(store, preference.getTextPreferenceKey());
+ // }
+ /**
+ * Returns the boolean preference for the given key.
+ *
+ * @param store
+ * the preference store
+ * @param key
+ * the preference key
+ * @return true
if the key exists in the store and its value
+ * is true
+ * @since 3.0
+ */
+ private boolean getBoolean(IPreferenceStore store, String key) {
+ return key != null && store.getBoolean(key);
+ }
+
+ protected boolean isPrefQuickDiffAlwaysOn() {
+ return false; // never show change ruler for the non-editable java
+ // editor.
+ // Overridden in subclasses like PHPUnitEditor
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions()
+ */
+ protected void createNavigationActions() {
+ super.createNavigationActions();
+
+ final StyledText textWidget = getSourceViewer().getTextWidget();
+
+ IAction action = new SmartLineStartAction(textWidget, false);
+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START);
+ setAction(ITextEditorActionDefinitionIds.LINE_START, action);
+
+ action = new SmartLineStartAction(textWidget, true);
+ action
+ .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START);
+ setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START, action);
+
+ action = new NavigatePreviousSubWordAction();
+ action
+ .setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS);
+ setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action);
+ textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL);
+
+ action = new NavigateNextSubWordAction();
+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT);
+ setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action);
+ textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL);
+
+ action = new SelectPreviousSubWordAction();
+ action
+ .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS);
+ setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action);
+ textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT,
+ SWT.NULL);
+
+ action = new SelectNextSubWordAction();
+ action
+ .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT);
+ setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action);
+ textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT,
+ SWT.NULL);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createCompositeRuler()
+ */
+ // protected CompositeRuler createCompositeRuler() {
+ // if
+ // (!getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
+ // return super.createCompositeRuler();
+ //
+ // CompositeRuler ruler = new CompositeRuler();
+ // AnnotationRulerColumn column = new
+ // AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess());
+ // column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(), new
+ // IDoubleClickListener() {
+ //
+ // public void doubleClick(DoubleClickEvent event) {
+ // // for now: just invoke ruler double click action
+ // triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
+ // }
+ //
+ // private void triggerAction(String actionID) {
+ // IAction action = getAction(actionID);
+ // if (action != null) {
+ // if (action instanceof IUpdate)
+ // ((IUpdate) action).update();
+ // // hack to propagate line change
+ // if (action instanceof ISelectionListener) {
+ // ((ISelectionListener) action).selectionChanged(null, null);
+ // }
+ // if (action.isEnabled())
+ // action.run();
+ // }
+ // }
+ //
+ // }));
+ // ruler.addDecorator(0, column);
+ //
+ // if (isLineNumberRulerVisible())
+ // ruler.addDecorator(1, createLineNumberRulerColumn());
+ // else if (isPrefQuickDiffAlwaysOn())
+ // ruler.addDecorator(1, createChangeRulerColumn());
+ //
+ // return ruler;
+ // }
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createAnnotationRulerColumn(org.eclipse.jface.text.source.CompositeRuler)
+ * @since 3.2
+ */
+ protected IVerticalRulerColumn createAnnotationRulerColumn(
+ CompositeRuler ruler) {
+ if (!getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
+ return super.createAnnotationRulerColumn(ruler);
+
+ AnnotationRulerColumn column = new AnnotationRulerColumn(
+ VERTICAL_RULER_WIDTH, getAnnotationAccess());
+ column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(),
+ new IDoubleClickListener() {
+
+ public void doubleClick(DoubleClickEvent event) {
+ // for now: just invoke ruler double click action
+ triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
+ }
+
+ private void triggerAction(String actionID) {
+ IAction action = getAction(actionID);
+ if (action != null) {
+ if (action instanceof IUpdate)
+ ((IUpdate) action).update();
+ // hack to propagate line change
+ if (action instanceof ISelectionListener) {
+ ((ISelectionListener) action).selectionChanged(
+ null, null);
+ }
+ if (action.isEnabled())
+ action.run();
+ }
+ }
+
+ }));
+
+ return column;
+ }
+
+ /**
+ * Returns the folding action group, or null
if there is
+ * none.
+ *
+ * @return the folding action group, or null
if there is none
+ * @since 3.0
+ */
+ protected FoldingActionGroup getFoldingActionGroup() {
+ return fFoldingGroup;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#performRevert()
+ */
+ protected void performRevert() {
+ ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
+ projectionViewer.setRedraw(false);
+ try {
+
+ boolean projectionMode = projectionViewer.isProjectionMode();
+ if (projectionMode) {
+ projectionViewer.disableProjection();
+ if (fProjectionModelUpdater != null)
+ fProjectionModelUpdater.uninstall();
+ }
+
+ super.performRevert();
+
+ if (projectionMode) {
+ if (fProjectionModelUpdater != null)
+ fProjectionModelUpdater.install(this, projectionViewer);
+ projectionViewer.enableProjection();
+ }
+
+ } finally {
+ projectionViewer.setRedraw(true);
+ }
+ }
+
+ /**
+ * React to changed selection.
+ *
+ * @since 3.0
+ */
+ protected void selectionChanged() {
+ if (getSelectionProvider() == null)
+ return;
+ ISourceReference element = computeHighlightRangeSourceReference();
+ if (getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
+ synchronizeOutlinePage(element);
+ setSelection(element, false);
+ updateStatusLine();
+ }
+
+ private boolean isJavaOutlinePageActive() {
+ IWorkbenchPart part = getActivePart();
+ return part instanceof ContentOutline
+ && ((ContentOutline) part).getCurrentPage() == fOutlinePage;
+ }
+
+ private IWorkbenchPart getActivePart() {
+ IWorkbenchWindow window = getSite().getWorkbenchWindow();
+ IPartService service = window.getPartService();
+ IWorkbenchPart part = service.getActivePart();
+ return part;
+ }
+
+ /**
+ * Computes and returns the source reference that includes the caret and
+ * serves as provider for the outline page selection and the editor range
+ * indication.
+ *
+ * @return the computed source reference
+ * @since 3.0
+ */
+ protected ISourceReference computeHighlightRangeSourceReference() {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null)
+ return null;
+
+ StyledText styledText = sourceViewer.getTextWidget();
+ if (styledText == null)
+ return null;
+
+ int caret = 0;
+ if (sourceViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
+ caret = extension.widgetOffset2ModelOffset(styledText
+ .getCaretOffset());
+ } else {
+ int offset = sourceViewer.getVisibleRegion().getOffset();
+ caret = offset + styledText.getCaretOffset();
+ }
+
+ IJavaElement element = getElementAt(caret, false);
+
+ if (!(element instanceof ISourceReference))
+ return null;
+
+ if (element.getElementType() == IJavaElement.IMPORT_DECLARATION) {
+
+ IImportDeclaration declaration = (IImportDeclaration) element;
+ IImportContainer container = (IImportContainer) declaration
+ .getParent();
+ ISourceRange srcRange = null;
+
+ try {
+ srcRange = container.getSourceRange();
+ } catch (JavaModelException e) {
+ }
+
+ if (srcRange != null && srcRange.getOffset() == caret)
+ return container;
+ }
+
+ return (ISourceReference) element;
+ }
+
+ /**
+ * Returns the most narrow java element including the given offset.
+ *
+ * @param offset
+ * the offset inside of the requested element
+ * @param reconcile
+ * true
if editor input should be reconciled in
+ * advance
+ * @return the most narrow java element
+ * @since 3.0
+ */
+ protected IJavaElement getElementAt(int offset, boolean reconcile) {
+ return getElementAt(offset);
+ }
+
+ public ShowInContext getShowInContext() {
+ IFile file = null;
+ if(getEditorInput() instanceof FileStoreEditorInput){
+ FileStoreEditorInput fei = (FileStoreEditorInput) getEditorInput();
+ file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(fei.getURI().getPath()));
+ } else if (getEditorInput() instanceof FileEditorInput) {
+ FileEditorInput fei = (FileEditorInput) getEditorInput();
+ // added to fix ticket 637
+ file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(fei.getURI().getPath()));
+ } else if (getEditorInput() instanceof ExternalEditorInput) {
+ ExternalEditorInput fei = (ExternalEditorInput) getEditorInput();
+ file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(fei.getFullPath()/* .getURI().getPath()*/));
+ }
+
+ ShowInContext context = BrowserUtil.getShowInContext(file,
+ false, "");
+ if (context != null) {
+ return context;
+ }
+ return new ShowInContext(file, null);
+ }
+
+ public String[] getShowInTargetIds() {
+ return new String[] { BrowserView.ID_BROWSER };
+ }
+
+ /**
+ * Updates the occurrences annotations based on the current selection.
+ *
+ * @param selection
+ * the text selection
+ * @param astRoot
+ * the compilation unit AST
+ * @since 3.0
+ */
+ protected void updateOccurrenceAnnotations(ITextSelection selection) {// ,
+ // CompilationUnit
+ // astRoot)
+ // {
+
+ if (fOccurrencesFinderJob != null)
+ fOccurrencesFinderJob.cancel();
+
+ if (!fMarkOccurrenceAnnotations)
+ return;
+
+ // if (astRoot == null || selection == null)
+ if (selection == null)
+ return;
+
+ IDocument document = getSourceViewer().getDocument();
+ if (document == null)
+ return;
+
+ fMarkOccurrenceTargetRegion = null;
+ if (document instanceof IDocumentExtension4) {
+ int offset = selection.getOffset();
+ long currentModificationStamp = ((IDocumentExtension4) document)
+ .getModificationStamp();
+ if (fMarkOccurrenceTargetRegion != null
+ && currentModificationStamp == fMarkOccurrenceModificationStamp) {
+ if (fMarkOccurrenceTargetRegion.getOffset() <= offset
+ && offset <= fMarkOccurrenceTargetRegion.getOffset()
+ + fMarkOccurrenceTargetRegion.getLength())
+ return;
+ }
+ fMarkOccurrenceTargetRegion = JavaWordFinder.findWord(document,
+ offset);
+ fMarkOccurrenceModificationStamp = currentModificationStamp;
+ }
+
+ if (fMarkOccurrenceTargetRegion == null
+ || fMarkOccurrenceTargetRegion.getLength() == 0) {
+ return;
+ }
+
+ List matches = null;
+
+ if (matches == null) {
+ try {
+ matches = new ArrayList();
+
+ Scanner fScanner = new Scanner();
+ fScanner.setSource(document.get().toCharArray());
+ fScanner.setPHPMode(false);
+ String wordStr;
+ char[] word;
+
+ wordStr = document.get(fMarkOccurrenceTargetRegion.getOffset(),
+ fMarkOccurrenceTargetRegion.getLength());
+ if (wordStr != null) {
+ word = wordStr.toCharArray();
+ int fToken = ITerminalSymbols.TokenNameEOF;
+ try {
+ fToken = fScanner.getNextToken();
+ while (fToken != ITerminalSymbols.TokenNameEOF) { // &&
+ // fToken
+ // !=
+ // TokenNameERROR) {
+ if (fToken == ITerminalSymbols.TokenNameVariable
+ || fToken == ITerminalSymbols.TokenNameIdentifier) {
+ // global variable
+ if (fScanner.equalsCurrentTokenSource(word)) {
+ matches
+ .add(new Region(
+ fScanner
+ .getCurrentTokenStartPosition(),
+ fScanner
+ .getCurrentTokenEndPosition()
+ - fScanner
+ .getCurrentTokenStartPosition()
+ + 1));
+ }
+ }
+ fToken = fScanner.getNextToken();
+ }
+ } catch (InvalidInputException e) {
+ // ignore errors
+ } catch (SyntaxError e) {
+ // ignore errors
+ }
+ }
+ } catch (BadLocationException e1) {
+ // ignore errors
+ } catch (Exception e) {
+ e.printStackTrace();
+ // ignore errors
+ }
+
+ }
+
+ if (matches == null || matches.size() == 0) {
+ if (!fStickyOccurrenceAnnotations)
+ removeOccurrenceAnnotations();
+ return;
+ }
+
+ Position[] positions = new Position[matches.size()];
+ int i = 0;
+ for (Iterator each = matches.iterator(); each.hasNext();) {
+ IRegion currentNode = (IRegion) each.next();
+ positions[i++] = new Position(currentNode.getOffset(), currentNode
+ .getLength());
+ }
+
+ fOccurrencesFinderJob = new OccurrencesFinderJob(document, positions,
+ selection);
+ // fOccurrencesFinderJob.setPriority(Job.DECORATE);
+ // fOccurrencesFinderJob.setSystem(true);
+ // fOccurrencesFinderJob.schedule();
+ fOccurrencesFinderJob.run(new NullProgressMonitor());
+ }
+
+ protected void installOccurrencesFinder() {
+ fMarkOccurrenceAnnotations = true;
+
+ fPostSelectionListenerWithAST = new ISelectionListenerWithAST() {
+ public void selectionChanged(IEditorPart part,
+ ITextSelection selection) { // ,
+ // CompilationUnit
+ // astRoot)
+ // {
+ updateOccurrenceAnnotations(selection);// , astRoot);
+ }
+ };
+ SelectionListenerWithASTManager.getDefault().addListener(this,
+ fPostSelectionListenerWithAST);
+ if (getSelectionProvider() != null) {
+ fForcedMarkOccurrencesSelection = getSelectionProvider()
+ .getSelection();
+ SelectionListenerWithASTManager.getDefault().forceSelectionChange(
+ this, (ITextSelection) fForcedMarkOccurrencesSelection);
+ }
+
+ if (fOccurrencesFinderJobCanceler == null) {
+ fOccurrencesFinderJobCanceler = new OccurrencesFinderJobCanceler();
+ fOccurrencesFinderJobCanceler.install();
+ }
+ }
+
+ protected void uninstallOccurrencesFinder() {
+ fMarkOccurrenceAnnotations = false;
+
+ if (fOccurrencesFinderJob != null) {
+ fOccurrencesFinderJob.cancel();
+ fOccurrencesFinderJob = null;
+ }
+
+ if (fOccurrencesFinderJobCanceler != null) {
+ fOccurrencesFinderJobCanceler.uninstall();
+ fOccurrencesFinderJobCanceler = null;
+ }
+
+ if (fPostSelectionListenerWithAST != null) {
+ SelectionListenerWithASTManager.getDefault().removeListener(this,
+ fPostSelectionListenerWithAST);
+ fPostSelectionListenerWithAST = null;
+ }
+
+ removeOccurrenceAnnotations();
+ }
+
+ protected boolean isMarkingOccurrences() {
+ return fMarkOccurrenceAnnotations;
+ }
+
+ void removeOccurrenceAnnotations() {
+ fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
+ fMarkOccurrenceTargetRegion = null;
+
+ IDocumentProvider documentProvider = getDocumentProvider();
+ if (documentProvider == null)
+ return;
+
+ IAnnotationModel annotationModel = documentProvider
+ .getAnnotationModel(getEditorInput());
+ if (annotationModel == null || fOccurrenceAnnotations == null)
+ return;
+
+ synchronized (getLockObject(annotationModel)) {
+ if (annotationModel instanceof IAnnotationModelExtension) {
+ ((IAnnotationModelExtension) annotationModel)
+ .replaceAnnotations(fOccurrenceAnnotations, null);
+ } else {
+ for (int i = 0, length = fOccurrenceAnnotations.length; i < length; i++)
+ annotationModel.removeAnnotation(fOccurrenceAnnotations[i]);
+ }
+ fOccurrenceAnnotations = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorActionDefinitionIds.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorActionDefinitionIds.java
new file mode 100644
index 0000000..e5569e9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorActionDefinitionIds.java
@@ -0,0 +1,84 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+
+public interface PHPEditorActionDefinitionIds extends
+ ITextEditorActionDefinitionIds {
+ /**
+ * Action definition ID of the edit -> go to matching bracket action (value
+ * "org.phpeclipse.phpdt.ui.edit.text.php.goto.matching.bracket"
).
+ *
+ * @since 2.1
+ */
+ public static final String GOTO_MATCHING_BRACKET = "net.sourceforge.phpeclipse.ui.edit.text.php.goto.matching.bracket"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the edit -> go to next member action (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.goto.next.member"
).
+ *
+ * @since 2.1
+ */
+ public static final String GOTO_NEXT_MEMBER = "net.sourceforge.phpeclipse.ui.edit.text.php.goto.next.member"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the edit -> go to previous member action (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.goto.previous.member"
).
+ *
+ * @since 2.1
+ */
+ public static final String GOTO_PREVIOUS_MEMBER = "net.sourceforge.phpeclipse.ui.edit.text.php.goto.previous.member"; //$NON-NLS-1$
+
+ /**
+ * Value: net.sourceforge.phpeclipse.phpeditor.comment
+ */
+ public static final String COMMENT = "net.sourceforge.phpeclipse.phpeditor.comment";
+
+ /**
+ * Value: net.sourceforge.phpeclipse.phpeditor.uncomment
+ */
+ public static final String UNCOMMENT = "net.sourceforge.phpeclipse.phpeditor.uncomment";
+
+ /**
+ * Action definition ID of the source -> toggle comment action (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.toggle.comment"
).
+ *
+ * @since 3.0
+ */
+ public static final String TOGGLE_COMMENT = "net.sourceforge.phpeclipse.phpeditor.toggle.comment"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the source -> add block comment action (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.add.block.comment"
).
+ *
+ * @since 3.0
+ */
+ public static final String ADD_BLOCK_COMMENT = "net.sourceforge.phpeclipse.phpeditor.add.block.comment"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the source -> remove block comment action (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.remove.block.comment"
).
+ *
+ * @since 3.0
+ */
+ public static final String REMOVE_BLOCK_COMMENT = "net.sourceforge.phpeclipse.phpeditor.remove.block.comment"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the source -> indent action (value
+ * "net.sourceforge.phpdt.ui.edit.text.java.indent"
).
+ */
+ public static final String INDENT = "net.sourceforge.phpeclipse.phpeditor.indent"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the source -> format action
+ */
+ public static final String FORMAT = "net.sourceforge.phpeclipse.phpeditor.format"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the edit -> content assist proposal action (value
+ * "org.phpeclipse.phpdt.ui.edit.text.php.content.assist. proposals"
+ *
).
+ */
+ // public static final String CONTENT_ASSIST_PROPOSALS =
+ // "net.sourceforge.phpeclipse.ui.edit.text.php.content.assist.proposals";
+ // //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.java
new file mode 100644
index 0000000..41536b9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.java
@@ -0,0 +1,48 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class PHPEditorMessages {
+
+ private static final String RESOURCE_BUNDLE = "net.sourceforge.phpeclipse.phpeditor.PHPEditorMessages";//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ public static String JavaEditor_markOccurrences_job_name = "JavaEditor.markOccurrences.job.name";
+
+ private PHPEditorMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * 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);
+ }
+
+ public static ResourceBundle getResourceBundle() {
+ return fgResourceBundle;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.properties
new file mode 100644
index 0000000..82cec7c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.properties
@@ -0,0 +1,147 @@
+#############################################################
+#
+# (c) Copyright IBM Corp. 2000, 2001.
+# All Rights Reserved.
+#
+#############################################################
+
+## Actions ##
+
+ContentAssistProposal.label=Content Assist@Ctrl+SPACE
+ContentAssistProposal.tooltip=Content Assist
+ContentAssistProposal.image=
+ContentAssistProposal.description=Content Assist
+
+ContentAssistTip.label=Content Tip@Ctrl+SHIFT+SPACE
+ContentAssistTip.tooltip=Content Tip
+ContentAssistTip.image=
+ContentAssistTip.description=Content Tip
+
+Format.label=F&ormat
+Format.tooltip=Format the Selected Text
+Format.description=Format the selected text
+
+Comment.label=Comment
+Comment.tooltip=Comment selected lines
+
+Uncomment.label=Uncomment
+Uncomment.tooltip=Uncomment selected lines
+
+TogglePresentation.label=Change Presentation
+TogglePresentation.tooltip=Enable/Disable Segmented Source Viewer
+TogglePresentation.image=togglepresentation.gif
+TogglePresentation.description=Enable/Disable Segmented Source Viewer
+
+ToggleComment.label=Togg&le Comment
+ToggleComment.tooltip=Toggle Comment For the Selected Lines
+ToggleComment.description=Toggle comment for the selected lines
+
+ToggleComment.error.title=Toggle Comment
+ToggleComment.error.message=An error occurred while toggling comments.
+
+AddBlockComment.label=Add &Block Comment
+AddBlockComment.tooltip=Enclose the Selection in a Block Comment
+AddBlockComment.description=Encloses the selection with block comment markers
+
+RemoveBlockComment.label=Remove Bloc&k Comment
+RemoveBlockComment.tooltip=Remove Block Comment Markers Enclosing the Caret
+RemoveBlockComment.description=Removes any block comment markers enclosing the caret
+
+
+OutlinePage.segment.title_pattern=position {0}
+
+AutoIndent.error.bad_location_1=JavaAutoIndentStrategy.getAutoIndentString: BadLocationException
+AutoIndent.error.bad_location_2=JavaAutoIndentStrategy.calcShiftBackReplace: BadLocationException
+
+CompletionProcessor.ContextInfo.display.pattern=proposal {0} at position {1}
+CompletionProcessor.ContextInfo.value.pattern=proposal {0} valid from {1} to {2}
+CompletionProcessor.Proposal.ContextInfo.pattern={0} valid 5 characters around insertion point
+CompletionProcessor.Proposal.hoverinfo.pattern=Java keyword: {0}
+
+ParserAction.label=Parse the PHP file
+ParserAction.tooltip=Parse the current PHP file
+ParserAction.image=java.gif
+ParserAction.description=Parse the current PHP file
+
+GotoMatchingBracket.label=Matching &Bracket
+GotoMatchingBracket.tooltip=Go to Matching Bracket
+GotoMatchingBracket.description=Go to Matching Bracket
+GotoMatchingBracket.error.invalidSelection=No bracket selected
+GotoMatchingBracket.error.noMatchingBracket=No matching bracket found
+GotoMatchingBracket.error.bracketOutsideSelectedElement=Matching bracket is outside of selected element
+
+GotoNextMember.label=N&ext Member
+GotoNextMember.tooltip=Go to N&ext Member
+GotoNextMember.description=Go to N&ext Member
+
+GotoPreviousMember.label=Previ&ous Member
+GotoPreviousMember.tooltip=Go to Previ&ous Member
+GotoPreviousMember.description=Go to Previ&ous Member
+
+AddTask.label=&Task...
+AddTask.tooltip=Add Task
+AddTask.image=
+AddTask.description=Add Task
+AddTask.dialog.title=Add Task
+AddTask.dialog.message=Enter Task description
+AddTask.error.dialog.title=Add Task
+AddTask.error.dialog.message=Problems adding new task
+
+ShowJavaDoc.label=Show &Tooltip Description
+ShowJavaDoc.tooltip=Shows Tooltip Description for Element at Cursor
+ShowJavaDoc.description=Shows the tooltip description for the element at the cursor
+
+EditorUtility.concatModifierStrings= {0} + {1}
+
+
+PHPUnitEditor.error.saving.message1=File has been deleted.
+PHPUnitEditor.error.saving.message2=Could not save file.
+PHPUnitEditor.error.saving.message3=Could not save file.
+PHPUnitEditor.error.saving.title1=Cannot Save
+PHPUnitEditor.error.saving.title2=Save Problems
+PHPUnitEditor.error.saving.title3=Save Problems
+PHPUnitEditor.warning.save.delete=The original file ''{0}'' has been deleted.
+
+PHPUnitEditor.warning.save.nonWorkbenchEncoding.title= Save Resource In Non-Workbench Encoding
+PHPUnitEditor.warning.save.nonWorkbenchEncoding.message1= {0} will be saved in \" {1} \" encoding which is not the current workbench encoding. This can result in conflicts with other tools. Continue anyway?
+PHPUnitEditor.warning.save.nonWorkbenchEncoding.message2= The resource will be saved in \" {0} \" encoding which is not the current platform encoding. This can result in conflicts with other tools. Continue anyway?
+
+JavaOutlinePage.ContextMenu.refactoring.label=&Refactor
+JavaOutlinePage.HideFields.description.checked=Shows Fields
+JavaOutlinePage.HideFields.description.unchecked=Hides Fields
+JavaOutlinePage.HideFields.label=Hide Fields
+JavaOutlinePage.HideFields.tooltip.checked=Show Fields
+JavaOutlinePage.HideFields.tooltip.unchecked=Hide Fields
+JavaOutlinePage.HideNonePublicMembers.description.checked=Shows non-public members
+JavaOutlinePage.HideNonePublicMembers.description.unchecked=Hides non-public members
+JavaOutlinePage.HideNonePublicMembers.label=Show Public Members Only
+JavaOutlinePage.HideNonePublicMembers.tooltip.checked=Show Non-Public Members
+JavaOutlinePage.HideNonePublicMembers.tooltip.unchecked=Hide Non-Public Members
+JavaOutlinePage.HideStaticMembers.description.checked=Shows static members
+JavaOutlinePage.HideStaticMembers.description.unchecked=Hides static members
+JavaOutlinePage.HideStaticMembers.label=Hide Static Members
+JavaOutlinePage.HideStaticMembers.tooltip.checked=Show Static Members
+JavaOutlinePage.HideStaticMembers.tooltip.unchecked=Hide Static Members
+JavaOutlinePage.Sort.label=Sort
+JavaOutlinePage.Sort.tooltip=Sort
+JavaOutlinePage.Sort.description=Enable Sorting
+JavaOutlinePage.GoIntoTopLevelType.label=Go Into Top Level Type
+JavaOutlinePage.GoIntoTopLevelType.tooltip=Go Into Top Level Type
+JavaOutlinePage.GoIntoTopLevelType.description=Show children of top level type only
+JavaOutlinePage.error.ChildrenProvider.getChildren.message1=JavaOutlinePage.ChildrenProvider.getChildren
+JavaOutlinePage.error.ChildrenProvider.hasChildren.message1=JavaOutlinePage.ChildrenProvider.hasChildren
+JavaOutlinePage.error.NoTopLevelType=Top level type not defined
+
+JavaEditor.markOccurrences.job.name= Occurrences Marker
+
+NextAnnotation.label= Ne&xt Annotation
+NextAnnotation.tooltip= Next Annotation
+NextAnnotation.description= Next Annotation
+
+PreviousAnnotation.label= Pre&vious Annotation
+PreviousAnnotation.tooltip= Previous Annotation
+PreviousAnnotation.description= Previous Annotation
+
+Indent.label=Correct &Indentation
+Indent.tooltip=&Indent Current Line to Correct Indentation
+Indent.description=&Indents the current line or selection depending on surrounding source code
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPSyntaxRdr.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPSyntaxRdr.java
new file mode 100644
index 0000000..01c578e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPSyntaxRdr.java
@@ -0,0 +1,349 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPConstant;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPElement;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPFunction;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPKeyword;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPType;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * PHPSyntaxRdr
reads PHP specifics from an XML file (eg.
+ * keywords)
+ */
+
+public class PHPSyntaxRdr {
+ // private static final String PHPDEFAULT_FILE = "default-syntax.xml";
+ // //$NON-NLS-1$
+ private static final String PHPSYNTAX_FILE = "syntax.xml"; //$NON-NLS-1$
+ // private static final String USERSYNTAX_FILE = "usersyntax.xml";
+ // //$NON-NLS-1$
+ // private static final String USERDEFAULT_FILE = "default-usersyntax.xml";
+ // //$NON-NLS-1$
+
+ private static final String PHPSYNTAX_TAG = "s"; //$NON-NLS-1$
+
+ private static final String KEYWORD_ATTR = "k"; //$NON-NLS-1$
+
+ private static final String TYPE_ATTR = "t"; //$NON-NLS-1$
+
+ private static final String CONSTANT_ATTR = "c"; //$NON-NLS-1$
+
+ private static final String FN_ATTR = "f"; //$NON-NLS-1$
+
+ private static final String USAGE_ATTR = "u"; //$NON-NLS-1$
+ // private static final String TOKENVAL_ATTR = "tokenval"; //$NON-NLS-1$
+
+ private static IPreferenceStore store;
+
+ //private static boolean hasXMLFileBeenRead = true;
+
+ // The following variable is used to hold the syntax from
+ // the suers custom file - if that file should be changed,
+ // then all entries in this variable should be removed from
+ // the word list, reread from the file and then reinserted.
+ private static ArrayList userdefsyntaxdata;
+
+ private static ArrayList syntaxdata;
+
+ public PHPSyntaxRdr() {
+ // see getSyntaxData()
+ syntaxdata = null;
+ store = WebUI.getDefault().getPreferenceStore();
+ }
+
+ public static void readInSyntax() {
+ try {
+// hasXMLFileBeenRead = true;
+ /*
+ * Attempt to read the syntax file from the metadata if this does
+ * not work, create metadata from default
+ */
+ /*File syntaxFile = getSyntaxFile();
+ if (syntaxFile.exists()) {
+ readFromFile(syntaxFile);
+ } else {*/
+ readFromStream(PHPSyntaxRdr.class
+ .getResourceAsStream(PHPSYNTAX_FILE));
+ //saveToFile(syntaxFile);
+ /*}*/
+ /* Read the user-defined syntax file if it exists */
+ // String buffer = new
+ // String(store.getString(PHPeclipsePlugin.PHP_USERDEF_XMLFILE));
+ /*if (store == null)
+ store = PHPeclipsePlugin.getDefault().getPreferenceStore();
+ String buffer = new String(store
+ .getString(IPreferenceConstants.PHP_USERDEF_XMLFILE));
+ if (!(buffer.equals("") || buffer == null)) {
+ readFromFile(buffer);
+ }*/
+ } catch (CoreException ce) {
+ ce.printStackTrace();
+ }
+ }
+
+ public static void readFromFile(String filename) {
+ try {
+ readFromFile(new File(filename));
+ } catch (CoreException e) {
+ }
+ }
+
+ public static void readFromFile(File file) throws CoreException {
+ InputStream stream = null;
+
+ if (file.exists()) {
+ try {
+ stream = new FileInputStream(file);
+ readFromStream(stream);
+ } catch (IOException e) {
+ throwReadException(e);
+ } finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ public static void readFromStream(InputStream stream) throws CoreException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder parser = factory.newDocumentBuilder();
+ Document document = parser.parse(new InputSource(stream));
+ // Read in the Standard PHPSyntax "stuff"
+ NodeList elements = document.getElementsByTagName(PHPSYNTAX_TAG);
+
+ int count = elements.getLength();
+ for (int i = 0; i != count; i++) {
+ Node node = elements.item(i);
+ NamedNodeMap attributes = node.getAttributes();
+
+ if (attributes == null)
+ continue;
+
+ String Keyword = getAttributeValue(attributes, KEYWORD_ATTR);
+ String Type = getAttributeValue(attributes, TYPE_ATTR);
+ String Function = getAttributeValue(attributes, FN_ATTR);
+ String Constant = getAttributeValue(attributes, CONSTANT_ATTR);
+ String usage = getAttributeValue(attributes, USAGE_ATTR);
+ // String Tokenval = getAttributeValue(attributes,
+ // TOKENVAL_ATTR);
+
+ StringBuffer buffer = new StringBuffer();
+ NodeList children = node.getChildNodes();
+ for (int j = 0; j != children.getLength(); j++) {
+ String value = children.item(j).getNodeValue();
+ if (value != null)
+ buffer.append(value);
+ }
+ String description = buffer.toString().trim();
+
+ if (Keyword == null && Type == null && Function == null
+ && Constant == null) {
+ // ignore as it is not a valid phpsyntax tag
+ } else {
+ if (Keyword != null) {
+ // syntaxdata.add(new PHPKeyword(Keyword, usage,
+ // Tokenval));
+ syntaxdata.add(new PHPKeyword(Keyword, usage));
+ } else if (Type != null) {
+ syntaxdata.add(new PHPType(Type, usage));
+ } else if (Function != null) {
+ syntaxdata.add(new PHPFunction(Function, usage,
+ description));
+ } else if (Constant != null) {
+ syntaxdata.add(new PHPConstant(Constant, null,
+ description));
+ }
+ }
+ }
+ } catch (ParserConfigurationException e) {
+ throwReadException(e);
+ } catch (IOException e) {
+ throwReadException(e);
+ } catch (SAXParseException e) {
+ System.out.println("SAXParseException in line:" + e.getLineNumber()
+ + " column:" + e.getColumnNumber());
+ throwReadException(e);
+ } catch (SAXException e) {
+ throwReadException(e);
+ }
+ }
+
+ public static ArrayList getSyntaxData() {
+ if (syntaxdata == null) {
+ syntaxdata = new ArrayList();
+ readInSyntax();
+ }
+ return syntaxdata;
+ }
+
+ public static void replaceUserDefFile() {
+ /* Replace the user-defined syntax file if it exists */
+ String buffer = new String(store
+ .getString(IPreferenceConstants.PHP_USERDEF_XMLFILE));
+ if (!buffer.equals("") || buffer == null) {
+ readFromFile(buffer);
+ }
+ }
+
+ public static ArrayList getUserSyntaxData() {
+ return userdefsyntaxdata;
+ }
+
+ private static File getSyntaxFile() {
+ IPath path = PHPeclipsePlugin.getDefault().getStateLocation();
+ path = path.append(PHPSYNTAX_FILE);
+ return path.toFile();
+ }
+
+ private static String getAttributeValue(NamedNodeMap attributes, String name) {
+ Node node = attributes.getNamedItem(name);
+ return node == null ? null : node.getNodeValue();
+ }
+
+ public static void saveToFile(File file) throws CoreException {
+ OutputStream stream = null;
+ try {
+ stream = new FileOutputStream(file);
+ saveToStream(stream);
+ } catch (IOException e) {
+ throwWriteException(e);
+ } finally {
+ try {
+ if (stream != null)
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public static void saveToStream(OutputStream stream) throws CoreException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document document = builder.newDocument();
+ Node root = document.createElement("PHPStandardSyntax"); // $NON-NLS-1$
+ // //$NON-NLS-1$
+ document.appendChild(root);
+ for (int i = 0; i != syntaxdata.size(); i++) {
+ Object bufferobj = (Object) syntaxdata.get(i);
+ Attr name = null;
+ Node node = document.createElement(PHPSYNTAX_TAG); // $NON-NLS-1$
+ // //$NON-NLS-1$
+ root.appendChild(node);
+ NamedNodeMap attributes = node.getAttributes();
+ if (bufferobj instanceof PHPType)
+ name = document.createAttribute(TYPE_ATTR);
+ if (bufferobj instanceof PHPKeyword)
+ name = document.createAttribute(KEYWORD_ATTR);
+ if (bufferobj instanceof PHPFunction)
+ name = document.createAttribute(FN_ATTR);
+ if (bufferobj instanceof PHPConstant)
+ name = document.createAttribute(CONSTANT_ATTR);
+ name.setValue(((PHPElement) bufferobj).getName());
+ attributes.setNamedItem(name);
+ Attr description = document.createAttribute(USAGE_ATTR);
+ description.setValue(((PHPElement) bufferobj).getUsage());
+ attributes.setNamedItem(description);
+ // if (bufferobj instanceof PHPKeyword) {
+ // Attr tokenval = document.createAttribute(TOKENVAL_ATTR);
+ // tokenval.setValue((new Integer(((PHPKeyword)
+ // bufferobj).gettokenval())).toString());
+ // attributes.setNamedItem(tokenval);
+ // }
+ if (bufferobj instanceof PHPFunction) {
+ // Attr usage = document.createAttribute(USAGE_ATTR);
+ Text usage = document
+ .createTextNode(((PHPFunction) bufferobj)
+ .getDescription());
+ node.appendChild(usage);
+ }
+ if (bufferobj instanceof PHPConstant) {
+ // Attr usage = document.createAttribute(USAGE_ATTR);
+ Text usage = document
+ .createTextNode(((PHPConstant) bufferobj)
+ .getDescription());
+ node.appendChild(usage);
+ }
+ }
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(stream);
+
+ transformer.transform(source, result);
+
+ } catch (ParserConfigurationException e) {
+ throwWriteException(e);
+ } catch (TransformerException e) {
+ throwWriteException(e);
+ }
+ // OutputFormat format = new OutputFormat();
+ // format.setPreserveSpace(true);
+ // try {
+ // Serializer serializer =
+ // SerializerFactory.getSerializerFactory("xml").makeSerializer(stream,
+ // format);
+ // serializer.asDOMSerializer().serialize(document);
+ // } catch (UnsupportedEncodingException e) {
+ // } catch (IOException e) {
+ // } //$NON-NLS-1$
+ // // Serializer serializer =
+ // SerializerFactory.getSerializer().makeSerializer(stream, format);
+ // //$NON-NLS-1$
+ // } catch (ParserConfigurationException e) {
+ // throwWriteException(e);
+ // }
+ }
+
+ private static void throwReadException(Throwable t) throws CoreException {
+ PHPeclipsePlugin.log(t);
+ }
+
+ private static void throwWriteException(Throwable t) throws CoreException {
+ PHPeclipsePlugin.log(t);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPTextHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPTextHover.java
new file mode 100644
index 0000000..9b2a03d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPTextHover.java
@@ -0,0 +1,152 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.corext.phpdoc.PHPDocUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPElement;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPFunction;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Implementation for an ITextHover
which hovers over PHP code.
+ */
+public class PHPTextHover implements ITextHover {
+ private static HashMap functionDescriptions = null;
+
+ private static HashMap identDescriptions = null;
+
+ /**
+ * The current project; maybe null
for preference pages
+ */
+ private IProject fProject;
+
+ public PHPTextHover(IProject project) {
+ fProject = project;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on ITextHover
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+ if (hoverRegion != null) {
+ try {
+ if (hoverRegion.getLength() > -1) {
+ String word = textViewer.getDocument().get(
+ hoverRegion.getOffset(), hoverRegion.getLength());
+ if (functionDescriptions == null) {
+ functionDescriptions = new HashMap();
+ identDescriptions = new HashMap();
+ ArrayList syntaxbuffer = PHPSyntaxRdr.getSyntaxData();
+ PHPElement elbuffer = null;
+ if (syntaxbuffer != null) {
+ for (int i = 0; i < syntaxbuffer.size(); i++) {
+ elbuffer = (PHPElement) syntaxbuffer.get(i);
+ if (elbuffer instanceof PHPFunction) {
+ functionDescriptions.put(
+ elbuffer.getName(), elbuffer
+ .getHoverText());
+ } else {
+ identDescriptions.put(elbuffer.getName(),
+ elbuffer.getHoverText());
+ }
+ }
+ }
+ //
+ // while ((syntaxbuffer != null)
+ // && (!syntaxbuffer.isEmpty() && ((elbuffer =
+ // (PHPElement)
+ // syntaxbuffer.remove(0)) != null))) {
+ // functionDescriptions.put(elbuffer.getName(),
+ // elbuffer.getHoverText());
+ // }
+ }
+ String hoverInfo = (String) identDescriptions.get(word);
+ if (hoverInfo == null & word.length() > 0) {
+ hoverInfo = (String) functionDescriptions.get(word
+ .toLowerCase());
+ }
+ if (hoverInfo == null && fProject != null) {
+ // get the possible PHPDoc information from the index
+ // file
+ IdentifierIndexManager indexManager = WebUI
+ .getDefault().getIndexManager(fProject);
+ List list = indexManager.getLocations(word);
+ if (list.size() > 0) {
+ try {
+ PHPIdentifierLocation location;
+ String filename;
+ StringBuffer hoverInfoBuffer = new StringBuffer();
+ String workspaceLocation;
+ if (fProject != null) {
+ workspaceLocation = fProject.getLocation()
+ .toString() + '/';
+ } else {
+ // should never happen?
+ workspaceLocation = PHPeclipsePlugin
+ .getWorkspace().getRoot()
+ .getLocation().toString();
+ }
+ // boolean foundPHPdoc = false;
+ for (int i = 0; i < list.size(); i++) {
+ location = (PHPIdentifierLocation) list
+ .get(i);
+ filename = workspaceLocation
+ + location.getFilename();
+ PHPDocUtil.appendPHPDoc(hoverInfoBuffer,
+ filename, location);
+ }
+ hoverInfo = hoverInfoBuffer.toString();
+ } catch (Throwable e) {
+ // ignore exceptions
+ // e.printStackTrace();
+ }
+ }
+ }
+ return hoverInfo;
+ }
+ // } catch (BadLocationException x) {
+ } catch (Exception x) {
+ }
+ }
+ return null;
+ // don't show this annoying text
+ // return "empty selection";
+ }
+
+ /*
+ * (non-Javadoc) Method declared on ITextHover
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ Point selection = PHPWordExtractor.findWord(textViewer.getDocument(),
+ offset);
+ // show the extracted word as a tooltip
+ if (selection != null && selection.x <= offset
+ && offset < selection.x + selection.y)
+ return new Region(selection.x, selection.y);
+ return new Region(offset, 0);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPUnitEditor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPUnitEditor.java
new file mode 100644
index 0000000..e0e5151
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PHPUnitEditor.java
@@ -0,0 +1,2766 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.dom.CompilationUnit;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+import net.sourceforge.phpdt.internal.ui.actions.AddBlockCommentAction;
+import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
+import net.sourceforge.phpdt.internal.ui.actions.IndentAction;
+import net.sourceforge.phpdt.internal.ui.actions.RemoveBlockCommentAction;
+import net.sourceforge.phpdt.internal.ui.text.ContentAssistPreference;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner;
+import net.sourceforge.phpdt.internal.ui.text.JavaIndenter;
+import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
+import net.sourceforge.phpdt.internal.ui.text.SmartBackspaceManager;
+import net.sourceforge.phpdt.internal.ui.text.SmartSemicolonAutoEditStrategy;
+import net.sourceforge.phpdt.internal.ui.text.comment.CommentFormattingContext;
+import net.sourceforge.phpdt.internal.ui.text.java.IJavaReconcilingListener;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI.ExitFlags;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.actions.RTrimAction;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.editor.ShowExternalPreviewAction;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+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.Preferences;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.IWidgetTokenKeeper;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.formatter.FormattingContextProperties;
+import org.eclipse.jface.text.formatter.IFormattingContext;
+import org.eclipse.jface.text.source.IOverviewRuler;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.VerifyKeyListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionContext;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.ui.editors.text.IStorageDocumentProvider;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.TextOperationAction;
+
+/*******************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Common Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - Initial implementation
+ * www.phpeclipse.de
+ ******************************************************************************/
+/**
+ * PHP specific text editor.
+ */
+public class PHPUnitEditor extends PHPEditor { // implements
+ // IJavaReconcilingListener {
+ interface ITextConverter {
+ void customizeDocumentCommand(IDocument document,
+ DocumentCommand command);
+ };
+
+ // class AdaptedSourceViewer extends JavaSourceViewer {
+ // private List fTextConverters;
+ //
+ // private boolean fIgnoreTextConverters = false;
+ //
+ // // private JavaCorrectionAssistant fCorrectionAssistant;
+ // public AdaptedSourceViewer(Composite parent, IVerticalRuler
+ // verticalRuler,
+ // IOverviewRuler overviewRuler, boolean showAnnotationsOverview,
+ // int styles, IPreferenceStore store) {
+ // super(parent, verticalRuler, overviewRuler, showAnnotationsOverview,
+ // styles, store);
+ // }
+ //
+ // // public AdaptedSourceViewer(Composite parent,
+ // // IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
+ // // boolean showAnnotationsOverview, int styles) {
+ // // super(parent, verticalRuler, overviewRuler,
+ // // showAnnotationsOverview, styles);
+ // // }
+ // public IContentAssistant getContentAssistant() {
+ // return fContentAssistant;
+ // }
+ //
+ // /*
+ // * @see ITextOperationTarget#doOperation(int)
+ // */
+ // public void doOperation(int operation) {
+ // if (getTextWidget() == null)
+ // return;
+ // switch (operation) {
+ // case CONTENTASSIST_PROPOSALS:
+ // String msg = fContentAssistant.showPossibleCompletions();
+ // setStatusLineErrorMessage(msg);
+ // return;
+ // // case CORRECTIONASSIST_PROPOSALS:
+ // // fCorrectionAssistant.showPossibleCompletions();
+ // // return;
+ // case UNDO:
+ // fIgnoreTextConverters = true;
+ // break;
+ // case REDO:
+ // fIgnoreTextConverters = true;
+ // break;
+ // }
+ // super.doOperation(operation);
+ // }
+ //
+ // /*
+ // * @see ITextOperationTarget#canDoOperation(int)
+ // */
+ // public boolean canDoOperation(int operation) {
+ // // if (operation == CORRECTIONASSIST_PROPOSALS)
+ // // return isEditable();
+ // return super.canDoOperation(operation);
+ // }
+ //
+ // /*
+ // * @see TextViewer#handleDispose()
+ // */
+ // protected void handleDispose() {
+ // // if (fCorrectionAssistant != null) {
+ // // fCorrectionAssistant.uninstall();
+ // // fCorrectionAssistant= null;
+ // // }
+ // super.handleDispose();
+ // }
+ //
+ // public void insertTextConverter(ITextConverter textConverter, int index)
+ // {
+ // throw new UnsupportedOperationException();
+ // }
+ //
+ // public void addTextConverter(ITextConverter textConverter) {
+ // if (fTextConverters == null) {
+ // fTextConverters = new ArrayList(1);
+ // fTextConverters.add(textConverter);
+ // } else if (!fTextConverters.contains(textConverter))
+ // fTextConverters.add(textConverter);
+ // }
+ //
+ // public void removeTextConverter(ITextConverter textConverter) {
+ // if (fTextConverters != null) {
+ // fTextConverters.remove(textConverter);
+ // if (fTextConverters.size() == 0)
+ // fTextConverters = null;
+ // }
+ // }
+ //
+ // /*
+ // * @see TextViewer#customizeDocumentCommand(DocumentCommand)
+ // */
+ // protected void customizeDocumentCommand(DocumentCommand command) {
+ // super.customizeDocumentCommand(command);
+ // if (!fIgnoreTextConverters && fTextConverters != null) {
+ // for (Iterator e = fTextConverters.iterator(); e.hasNext();)
+ // ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(),
+ // command);
+ // }
+ // fIgnoreTextConverters = false;
+ // }
+ //
+ // // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
+ // public void updateIndentationPrefixes() {
+ // SourceViewerConfiguration configuration = getSourceViewerConfiguration();
+ // String[] types = configuration.getConfiguredContentTypes(this);
+ // for (int i = 0; i < types.length; i++) {
+ // String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
+ // if (prefixes != null && prefixes.length > 0)
+ // setIndentPrefixes(prefixes, types[i]);
+ // }
+ // }
+ //
+ // /*
+ // * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
+ // */
+ // public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
+ // if (WorkbenchHelp.isContextHelpDisplayed())
+ // return false;
+ // return super.requestWidgetToken(requester);
+ // }
+ //
+ // // /*
+ // // * @see
+ // org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
+ // // */
+ // // public void configure(SourceViewerConfiguration configuration) {
+ // // super.configure(configuration);
+ // // // fCorrectionAssistant= new
+ // // // JavaCorrectionAssistant(CompilationUnitEditor.this);
+ // // // fCorrectionAssistant.install(this);
+ // // //TODO install SmartBracesAutoEditStrategy
+ // // // prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this),
+ // // // IDocument.DEFAULT_CONTENT_TYPE);
+ // // }
+ // public void configure(SourceViewerConfiguration configuration) {
+ // super.configure(configuration);
+ // // fCorrectionAssistant= new
+ // JavaCorrectionAssistant(CompilationUnitEditor.this);
+ // // fCorrectionAssistant.install(this);
+ // IAutoEditStrategy smartSemi= new
+ // SmartSemicolonAutoEditStrategy(IPHPPartitions.PHP_PARTITIONING);
+ // prependAutoEditStrategy(smartSemi, IDocument.DEFAULT_CONTENT_TYPE);
+ // prependAutoEditStrategy(smartSemi, IPHPPartitions.PHP_STRING_DQ);
+ // prependAutoEditStrategy(smartSemi, IPHPPartitions.PHP_STRING_SQ);
+ // // prependAutoEditStrategy(smartSemi, IPHPPartitions.JAVA_CHARACTER);
+ // }
+ // };
+ class AdaptedSourceViewer extends JavaSourceViewer {
+
+ private List fTextConverters;
+
+ private boolean fIgnoreTextConverters = false;
+
+ // private JavaCorrectionAssistant fCorrectionAssistant;
+
+ public AdaptedSourceViewer(Composite parent,
+ IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
+ boolean showAnnotationsOverview, int styles,
+ IPreferenceStore store) {
+ super(parent, verticalRuler, overviewRuler,
+ showAnnotationsOverview, styles, store);
+ }
+
+ public IContentAssistant getContentAssistant() {
+ return fContentAssistant;
+ }
+
+ /*
+ * @see ITextOperationTarget#doOperation(int)
+ */
+ public void doOperation(int operation) {
+
+ if (getTextWidget() == null)
+ return;
+
+ switch (operation) {
+ case CONTENTASSIST_PROPOSALS:
+ String msg = fContentAssistant.showPossibleCompletions();
+ setStatusLineErrorMessage(msg);
+ return;
+ // case CORRECTIONASSIST_PROPOSALS:
+ // msg = fCorrectionAssistant.showPossibleCompletions();
+ // setStatusLineErrorMessage(msg);
+ // return;
+ case UNDO:
+ fIgnoreTextConverters = true;
+ super.doOperation(operation);
+ fIgnoreTextConverters = false;
+ return;
+ case REDO:
+ fIgnoreTextConverters = true;
+ super.doOperation(operation);
+ fIgnoreTextConverters = false;
+ return;
+ }
+
+ super.doOperation(operation);
+ }
+
+ /*
+ * @see ITextOperationTarget#canDoOperation(int)
+ */
+ public boolean canDoOperation(int operation) {
+ // if (operation == CORRECTIONASSIST_PROPOSALS)
+ // return isEditable();
+
+ return super.canDoOperation(operation);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.ISourceViewerExtension2#unconfigure()
+ * @since 3.0
+ */
+ public void unconfigure() {
+ // if (fCorrectionAssistant != null) {
+ // fCorrectionAssistant.uninstall();
+ // fCorrectionAssistant = null;
+ // }
+ super.unconfigure();
+ }
+
+ public void insertTextConverter(ITextConverter textConverter, int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addTextConverter(ITextConverter textConverter) {
+ if (fTextConverters == null) {
+ fTextConverters = new ArrayList(1);
+ fTextConverters.add(textConverter);
+ } else if (!fTextConverters.contains(textConverter))
+ fTextConverters.add(textConverter);
+ }
+
+ public void removeTextConverter(ITextConverter textConverter) {
+ if (fTextConverters != null) {
+ fTextConverters.remove(textConverter);
+ if (fTextConverters.size() == 0)
+ fTextConverters = null;
+ }
+ }
+
+ /*
+ * @see TextViewer#customizeDocumentCommand(DocumentCommand)
+ */
+ protected void customizeDocumentCommand(DocumentCommand command) {
+ super.customizeDocumentCommand(command);
+ if (!fIgnoreTextConverters && fTextConverters != null) {
+ for (Iterator e = fTextConverters.iterator(); e.hasNext();)
+ ((ITextConverter) e.next()).customizeDocumentCommand(
+ getDocument(), command);
+ }
+ }
+
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
+ public void updateIndentationPrefixes() {
+ SourceViewerConfiguration configuration = getSourceViewerConfiguration();
+ String[] types = configuration.getConfiguredContentTypes(this);
+ for (int i = 0; i < types.length; i++) {
+ String[] prefixes = configuration.getIndentPrefixes(this,
+ types[i]);
+ if (prefixes != null && prefixes.length > 0)
+ setIndentPrefixes(prefixes, types[i]);
+ }
+ }
+
+ /*
+ * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
+ */
+ public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
+ if (PlatformUI.getWorkbench().getHelpSystem()
+ .isContextHelpDisplayed())
+ return false;
+ return super.requestWidgetToken(requester);
+ }
+
+ /*
+ * @see IWidgetTokenOwnerExtension#requestWidgetToken(IWidgetTokenKeeper,
+ * int)
+ * @since 3.0
+ */
+ public boolean requestWidgetToken(IWidgetTokenKeeper requester,
+ int priority) {
+ if (PlatformUI.getWorkbench().getHelpSystem()
+ .isContextHelpDisplayed())
+ return false;
+ return super.requestWidgetToken(requester, priority);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
+ */
+ public void configure(SourceViewerConfiguration configuration) {
+ super.configure(configuration);
+ // fCorrectionAssistant = new
+ // JavaCorrectionAssistant(CompilationUnitEditor.this);
+ // fCorrectionAssistant.install(this);
+ IAutoEditStrategy smartSemi = new SmartSemicolonAutoEditStrategy(
+ IPHPPartitions.PHP_PARTITIONING);
+ prependAutoEditStrategy(smartSemi, IDocument.DEFAULT_CONTENT_TYPE);
+ prependAutoEditStrategy(smartSemi, IPHPPartitions.PHP_STRING_DQ);
+ prependAutoEditStrategy(smartSemi, IPHPPartitions.PHP_STRING_SQ);
+ prependAutoEditStrategy(smartSemi,
+ IPHPPartitions.PHP_STRING_HEREDOC);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewer#createFormattingContext()
+ * @since 3.0
+ */
+ public IFormattingContext createFormattingContext() {
+ IFormattingContext context = new CommentFormattingContext();
+
+ Map preferences;
+ IJavaElement inputJavaElement = getInputJavaElement();
+ IJavaProject javaProject = inputJavaElement != null ? inputJavaElement
+ .getJavaProject()
+ : null;
+ if (javaProject == null)
+ preferences = new HashMap(JavaCore.getOptions());
+ else
+ preferences = new HashMap(javaProject.getOptions(true));
+
+ context.storeToMap(PreferenceConstants.getPreferenceStore(),
+ preferences, false);
+ context.setProperty(
+ FormattingContextProperties.CONTEXT_PREFERENCES,
+ preferences);
+
+ return context;
+ }
+ }
+
+ /**
+ * Remembers data related to the current selection to be able to restore it
+ * later.
+ *
+ * @since 3.0
+ */
+ private class RememberedSelection {
+ /** The remembered selection start. */
+ private RememberedOffset fStartOffset = new RememberedOffset();
+
+ /** The remembered selection end. */
+ private RememberedOffset fEndOffset = new RememberedOffset();
+
+ /**
+ * Remember current selection.
+ */
+ public void remember() {
+ /*
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=52257 This method
+ * may be called inside an async call posted to the UI thread, so
+ * protect against intermediate disposal of the editor.
+ */
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer != null) {
+ IRegion selection = getSignedSelection(viewer);
+ int startOffset = selection.getOffset();
+ int endOffset = startOffset + selection.getLength();
+
+ fStartOffset.setOffset(startOffset);
+ fEndOffset.setOffset(endOffset);
+ }
+ }
+
+ /**
+ * Restore remembered selection.
+ */
+ public void restore() {
+ /*
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=52257 This method
+ * may be called inside an async call posted to the UI thread, so
+ * protect against intermediate disposal of the editor.
+ */
+ if (getSourceViewer() == null)
+ return;
+
+ try {
+
+ int startOffset, endOffset;
+ int revealStartOffset, revealEndOffset;
+ if (showsHighlightRangeOnly()) {
+ IJavaElement newStartElement = fStartOffset.getElement();
+ startOffset = fStartOffset
+ .getRememberedOffset(newStartElement);
+ revealStartOffset = fStartOffset.getRevealOffset(
+ newStartElement, startOffset);
+ if (revealStartOffset == -1)
+ startOffset = -1;
+
+ IJavaElement newEndElement = fEndOffset.getElement();
+ endOffset = fEndOffset.getRememberedOffset(newEndElement);
+ revealEndOffset = fEndOffset.getRevealOffset(newEndElement,
+ endOffset);
+ if (revealEndOffset == -1)
+ endOffset = -1;
+ } else {
+ startOffset = fStartOffset.getOffset();
+ revealStartOffset = startOffset;
+ endOffset = fEndOffset.getOffset();
+ revealEndOffset = endOffset;
+ }
+
+ if (startOffset == -1) {
+ startOffset = endOffset; // fallback to caret offset
+ revealStartOffset = revealEndOffset;
+ }
+
+ if (endOffset == -1) {
+ endOffset = startOffset; // fallback to other offset
+ revealEndOffset = revealStartOffset;
+ }
+
+ IJavaElement element;
+ if (endOffset == -1) {
+ // fallback to element selection
+ element = fEndOffset.getElement();
+ if (element == null)
+ element = fStartOffset.getElement();
+ if (element != null)
+ setSelection(element);
+ return;
+ }
+
+ if (isValidSelection(revealStartOffset, revealEndOffset
+ - revealStartOffset)
+ && isValidSelection(startOffset, endOffset
+ - startOffset))
+ selectAndReveal(startOffset, endOffset - startOffset,
+ revealStartOffset, revealEndOffset
+ - revealStartOffset);
+ } finally {
+ fStartOffset.clear();
+ fEndOffset.clear();
+ }
+ }
+
+ private boolean isValidSelection(int offset, int length) {
+ IDocumentProvider provider = getDocumentProvider();
+ if (provider != null) {
+ IDocument document = provider.getDocument(getEditorInput());
+ if (document != null) {
+ int end = offset + length;
+ int documentLength = document.getLength();
+ return 0 <= offset && offset <= documentLength && 0 <= end
+ && end <= documentLength;
+ }
+ }
+ return false;
+ }
+
+ }
+
+ /**
+ * Remembers additional data for a given offset to be able restore it later.
+ *
+ * @since 3.0
+ */
+ private class RememberedOffset {
+ /** Remembered line for the given offset */
+ private int fLine;
+
+ /** Remembered column for the given offset */
+ private int fColumn;
+
+ /** Remembered Java element for the given offset */
+ private IJavaElement fElement;
+
+ /** Remembered Java element line for the given offset */
+ private int fElementLine;
+
+ /**
+ * Store visual properties of the given offset.
+ *
+ * @param offset
+ * Offset in the document
+ */
+ public void setOffset(int offset) {
+ try {
+ IDocument document = getSourceViewer().getDocument();
+ fLine = document.getLineOfOffset(offset);
+ fColumn = offset - document.getLineOffset(fLine);
+ fElement = getElementAt(offset, true);
+
+ fElementLine = -1;
+ if (fElement instanceof IMember) {
+ ISourceRange range = ((IMember) fElement).getNameRange();
+ if (range != null)
+ fElementLine = document.getLineOfOffset(range
+ .getOffset());
+ }
+ if (fElementLine == -1)
+ fElementLine = document
+ .getLineOfOffset(getOffset(fElement));
+ } catch (BadLocationException e) {
+ // should not happen
+ PHPeclipsePlugin.log(e);
+ clear();
+ } catch (JavaModelException e) {
+ // should not happen
+ PHPeclipsePlugin.log(e.getStatus());
+ clear();
+ }
+ }
+
+ /**
+ * Return offset recomputed from stored visual properties.
+ *
+ * @return Offset in the document
+ */
+ public int getOffset() {
+ IJavaElement newElement = getElement();
+
+ int offset = getRememberedOffset(newElement);
+
+ if (offset != -1 && !containsOffset(newElement, offset)
+ && (offset == 0 || !containsOffset(newElement, offset - 1)))
+ return -1;
+
+ return offset;
+ }
+
+ /**
+ * Return offset recomputed from stored visual properties.
+ *
+ * @param newElement
+ * Enclosing element
+ * @return Offset in the document
+ */
+ public int getRememberedOffset(IJavaElement newElement) {
+ try {
+ if (newElement == null)
+ return -1;
+
+ IDocument document = getSourceViewer().getDocument();
+ int newElementLine = -1;
+ if (newElement instanceof IMember) {
+ ISourceRange range = ((IMember) newElement).getNameRange();
+ if (range != null)
+ newElementLine = document.getLineOfOffset(range
+ .getOffset());
+ }
+ if (newElementLine == -1)
+ newElementLine = document
+ .getLineOfOffset(getOffset(newElement));
+ if (newElementLine == -1)
+ return -1;
+
+ int newLine = fLine + newElementLine - fElementLine;
+ if (newLine < 0 || newLine >= document.getNumberOfLines())
+ return -1;
+ int maxColumn = document.getLineLength(newLine);
+ String lineDelimiter = document.getLineDelimiter(newLine);
+ if (lineDelimiter != null)
+ maxColumn = maxColumn - lineDelimiter.length();
+ int offset;
+ if (fColumn > maxColumn)
+ offset = document.getLineOffset(newLine) + maxColumn;
+ else
+ offset = document.getLineOffset(newLine) + fColumn;
+
+ return offset;
+ } catch (BadLocationException e) {
+ // should not happen
+ PHPeclipsePlugin.log(e);
+ return -1;
+ } catch (JavaModelException e) {
+ // should not happen
+ PHPeclipsePlugin.log(e.getStatus());
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the offset used to reveal the given element based on the
+ * given selection offset.
+ *
+ * @param element
+ * the element
+ * @param offset
+ * the selection offset
+ * @return the offset to reveal the given element based on the given
+ * selection offset
+ */
+ public int getRevealOffset(IJavaElement element, int offset) {
+ if (element == null || offset == -1)
+ return -1;
+
+ if (containsOffset(element, offset)) {
+ if (offset > 0) {
+ IJavaElement alternateElement = getElementAt(offset, false);
+ if (element.getHandleIdentifier().equals(
+ alternateElement.getParent().getHandleIdentifier()))
+ return offset - 1; // Solves test case 2 from
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=47727#c3
+ }
+ return offset;
+ } else if (offset > 0 && containsOffset(element, offset - 1))
+ return offset - 1; // Solves test case 1 from
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=47727#c3
+
+ return -1;
+ }
+
+ /**
+ * Return Java element recomputed from stored visual properties.
+ *
+ * @return Java element
+ */
+ public IJavaElement getElement() {
+ if (fElement == null)
+ return null;
+
+ return findElement(fElement);
+ }
+
+ /**
+ * Clears the stored position
+ */
+ public void clear() {
+ fLine = -1;
+ fColumn = -1;
+ fElement = null;
+ fElementLine = -1;
+ }
+
+ /**
+ * Does the given Java element contain the given offset?
+ *
+ * @param element
+ * Java element
+ * @param offset
+ * Offset
+ * @return true
iff the Java element contains the offset
+ */
+ private boolean containsOffset(IJavaElement element, int offset) {
+ int elementOffset = getOffset(element);
+ int elementLength = getLength(element);
+ return (elementOffset > -1 && elementLength > -1) ? (offset >= elementOffset && offset < elementOffset
+ + elementLength)
+ : false;
+ }
+
+ /**
+ * Returns the offset of the given Java element.
+ *
+ * @param element
+ * Java element
+ * @return Offset of the given Java element
+ */
+ private int getOffset(IJavaElement element) {
+ if (element instanceof ISourceReference) {
+ ISourceReference sr = (ISourceReference) element;
+ try {
+ ISourceRange srcRange = sr.getSourceRange();
+ if (srcRange != null)
+ return srcRange.getOffset();
+ } catch (JavaModelException e) {
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the length of the given Java element.
+ *
+ * @param element
+ * Java element
+ * @return Length of the given Java element
+ */
+ private int getLength(IJavaElement element) {
+ if (element instanceof ISourceReference) {
+ ISourceReference sr = (ISourceReference) element;
+ try {
+ ISourceRange srcRange = sr.getSourceRange();
+ if (srcRange != null)
+ return srcRange.getLength();
+ } catch (JavaModelException e) {
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the updated java element for the old java element.
+ *
+ * @param element
+ * Old Java element
+ * @return Updated Java element
+ */
+ private IJavaElement findElement(IJavaElement element) {
+
+ if (element == null)
+ return null;
+
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
+
+ if (unit != null) {
+ try {
+
+ synchronized (unit) {
+ // unit.reconcile(ICompilationUnit.NO_AST, false, null,
+ // null);
+ unit.reconcile();
+ }
+ IJavaElement[] findings = unit.findElements(element);
+ if (findings != null && findings.length > 0)
+ return findings[0];
+
+ } catch (JavaModelException x) {
+ PHPeclipsePlugin.log(x.getStatus());
+ // nothing found, be tolerant and go on
+ }
+ }
+
+ return null;
+ }
+
+ }
+
+ static class TabConverter implements ITextConverter {
+ private int fTabRatio;
+
+ private ILineTracker fLineTracker;
+
+ public TabConverter() {
+ }
+
+ public void setNumberOfSpacesPerTab(int ratio) {
+ fTabRatio = ratio;
+ }
+
+ public void setLineTracker(ILineTracker lineTracker) {
+ fLineTracker = lineTracker;
+ }
+
+ private int insertTabString(StringBuffer buffer, int offsetInLine) {
+ if (fTabRatio == 0)
+ return 0;
+ int remainder = offsetInLine % fTabRatio;
+ remainder = fTabRatio - remainder;
+ for (int i = 0; i < remainder; i++)
+ buffer.append(' ');
+ return remainder;
+ }
+
+ public void customizeDocumentCommand(IDocument document,
+ DocumentCommand command) {
+ String text = command.text;
+ if (text == null)
+ return;
+ int index = text.indexOf('\t');
+ if (index > -1) {
+ StringBuffer buffer = new StringBuffer();
+ fLineTracker.set(command.text);
+ int lines = fLineTracker.getNumberOfLines();
+ try {
+ for (int i = 0; i < lines; i++) {
+ int offset = fLineTracker.getLineOffset(i);
+ int endOffset = offset + fLineTracker.getLineLength(i);
+ String line = text.substring(offset, endOffset);
+ int position = 0;
+ if (i == 0) {
+ IRegion firstLine = document
+ .getLineInformationOfOffset(command.offset);
+ position = command.offset - firstLine.getOffset();
+ }
+ int length = line.length();
+ for (int j = 0; j < length; j++) {
+ char c = line.charAt(j);
+ if (c == '\t') {
+ position += insertTabString(buffer, position);
+ } else {
+ buffer.append(c);
+ ++position;
+ }
+ }
+ }
+ command.text = buffer.toString();
+ } catch (BadLocationException x) {
+ }
+ }
+ }
+ };
+
+ private static class ExitPolicy implements LinkedPositionUI.ExitPolicy {
+ final char fExitCharacter;
+
+ public ExitPolicy(char exitCharacter) {
+ fExitCharacter = exitCharacter;
+ }
+
+ /*
+ * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionManager,
+ * org.eclipse.swt.events.VerifyEvent, int, int)
+ */
+ public ExitFlags doExit(LinkedPositionManager manager,
+ VerifyEvent event, int offset, int length) {
+ if (event.character == fExitCharacter) {
+ if (manager.anyPositionIncludes(offset, length))
+ return new ExitFlags(LinkedPositionUI.COMMIT
+ | LinkedPositionUI.UPDATE_CARET, false);
+ else
+ return new ExitFlags(LinkedPositionUI.COMMIT, true);
+ }
+ // Fix for #1380415 (toshihiro) start
+ switch (event.keyCode) {
+ case SWT.ARROW_UP:
+ case SWT.ARROW_DOWN:
+ return new ExitFlags(LinkedPositionUI.COMMIT, true);
+ case SWT.ARROW_LEFT:
+ case SWT.ARROW_RIGHT:
+ if (!manager.anyPositionIncludes(offset, length))
+ return new ExitFlags(LinkedPositionUI.COMMIT, true);
+ break;
+ }
+ // #1380415 end
+ switch (event.character) {
+ case '\b':
+ if (manager.getFirstPosition().length == 0)
+ return new ExitFlags(0, false);
+ else
+ return null;
+ case '\n':
+ case '\r':
+ return new ExitFlags(LinkedPositionUI.COMMIT, true);
+ default:
+ return null;
+ }
+ }
+ }
+
+ private static class BracketLevel {
+ int fOffset;
+
+ int fLength;
+
+ LinkedPositionManager fManager;
+
+ LinkedPositionUI fEditor;
+ };
+
+ private class BracketInserter implements VerifyKeyListener,
+ LinkedPositionUI.ExitListener {
+ private boolean fCloseBracketsPHP = true;
+
+ private boolean fCloseStringsPHPDQ = true;
+
+ private boolean fCloseStringsPHPSQ = true;
+
+ private int fOffset;
+
+ private int fLength;
+
+ public void setCloseBracketsPHPEnabled(boolean enabled) {
+ fCloseBracketsPHP = enabled;
+ }
+
+ public void setCloseStringsPHPDQEnabled(boolean enabled) {
+ fCloseStringsPHPDQ = enabled;
+ }
+
+ public void setCloseStringsPHPSQEnabled(boolean enabled) {
+ fCloseStringsPHPSQ = enabled;
+ }
+
+ private boolean hasIdentifierToTheRight(IDocument document, int offset) {
+ try {
+ int end = offset;
+ IRegion endLine = document.getLineInformationOfOffset(end);
+ int maxEnd = endLine.getOffset() + endLine.getLength();
+ while (end != maxEnd
+ && Character.isWhitespace(document.getChar(end)))
+ ++end;
+ return end != maxEnd
+ && Scanner.isPHPIdentifierPart(document.getChar(end));
+ } catch (BadLocationException e) {
+ // be conservative
+ return true;
+ }
+ }
+
+ private boolean hasIdentifierToTheLeft(IDocument document, int offset) {
+ try {
+ int start = offset;
+ IRegion startLine = document.getLineInformationOfOffset(start);
+ int minStart = startLine.getOffset();
+ while (start != minStart
+ && Character.isWhitespace(document.getChar(start - 1)))
+ --start;
+ return start != minStart
+ && Scanner.isPHPIdentifierPart(document
+ .getChar(start - 1));
+ } catch (BadLocationException e) {
+ return true;
+ }
+ }
+
+ private boolean hasCharacterToTheLeft(IDocument document, int offset,
+ char character) {
+ try {
+ int start = offset;
+ IRegion startLine = document.getLineInformationOfOffset(start);
+ int minStart = startLine.getOffset();
+ while (start != minStart
+ && Character.isWhitespace(document.getChar(start - 1)))
+ --start;
+ return start != minStart
+ && document.getChar(start - 1) == character;
+ } catch (BadLocationException e) {
+ return false;
+ }
+ }
+
+ private boolean hasCharacterToTheRight(IDocument document, int offset,
+ char character) {
+ try {
+ int end = offset;
+ IRegion endLine = document.getLineInformationOfOffset(end);
+ int maxEnd = endLine.getOffset() + endLine.getLength();
+ while (end != maxEnd
+ && Character.isWhitespace(document.getChar(end)))
+ ++end;
+ return end != maxEnd && document.getChar(end) == character;
+ } catch (BadLocationException e) {
+ // be conservative
+ return true;
+ }
+ }
+
+ /*
+ * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
+ */
+ public void verifyKey(VerifyEvent event) {
+ if (!event.doit)
+ return;
+ final ISourceViewer sourceViewer = getSourceViewer();
+ IDocument document = sourceViewer.getDocument();
+ final Point selection = sourceViewer.getSelectedRange();
+ final int offset = selection.x;
+ final int length = selection.y;
+ try {
+ ITypedRegion partition = document.getPartition(offset);
+ String type = partition.getType();
+ if (type.equals(IPHPPartitions.PHP_PARTITIONING)
+ || type.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
+ // you will get IDocument.DEFAULT_CONTENT_TYPE for both PHP
+ // and HTML area
+ switch (event.character) {
+ case '(':
+ if (hasCharacterToTheRight(document, offset + length,
+ '('))
+ return;
+ // fall through
+ case '[':
+ if (!fCloseBracketsPHP)
+ return;
+ if (hasIdentifierToTheRight(document, offset + length))
+ return;
+ // fall through
+ case '{':
+ if (!fCloseBracketsPHP)
+ return;
+ if (hasIdentifierToTheRight(document, offset + length))
+ return;
+ // fall through
+ case '"':
+ if (event.character == '"') {
+ if (!fCloseStringsPHPDQ)
+ return;
+ // changed for statements like echo "" print ""
+ // if (hasIdentifierToTheLeft(document, offset)
+ // ||
+ // hasIdentifierToTheRight(document, offset +
+ // length))
+ if (hasIdentifierToTheRight(document, offset
+ + length))
+ return;
+ }
+ // ITypedRegion partition=
+ // document.getPartition(offset);
+ // if (!
+ // IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
+ // &&
+ // (partition.getOffset() != offset))
+ // return;
+ final char characterDQ = event.character;
+ final char closingCharacterDQ = getPeerCharacter(characterDQ);
+ final StringBuffer bufferDQ = new StringBuffer();
+ bufferDQ.append(characterDQ);
+ bufferDQ.append(closingCharacterDQ);
+ document.replace(offset, length, bufferDQ.toString());
+ LinkedPositionManager managerDQ = new LinkedPositionManager(
+ document);
+ managerDQ.addPosition(offset + 1, 0);
+ fOffset = offset;
+ fLength = 2;
+ LinkedPositionUI editorDQ = new LinkedPositionUI(
+ sourceViewer, managerDQ);
+ editorDQ.setCancelListener(this);
+ editorDQ.setExitPolicy(new ExitPolicy(
+ closingCharacterDQ));
+ editorDQ.setFinalCaretOffset(offset + 2);
+ editorDQ.enter();
+ IRegion newSelectionDQ = editorDQ.getSelectedRegion();
+ sourceViewer.setSelectedRange(newSelectionDQ
+ .getOffset(), newSelectionDQ.getLength());
+ event.doit = false;
+ break;
+ case '\'':
+ if (event.character == '\'') {
+ if (!fCloseStringsPHPSQ)
+ return;
+ // changed for statements like echo "" print ""
+ // if (hasIdentifierToTheLeft(document, offset)
+ // ||
+ // hasIdentifierToTheRight(document, offset +
+ // length))
+ if (hasIdentifierToTheRight(document, offset
+ + length))
+ return;
+ }
+ // ITypedRegion partition=
+ // document.getPartition(offset);
+ // if (!
+ // IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
+ // &&
+ // (partition.getOffset() != offset))
+ // return;
+ final char characterSQ = event.character;
+ final char closingCharacterSQ = getPeerCharacter(characterSQ);
+ final StringBuffer bufferSQ = new StringBuffer();
+ bufferSQ.append(characterSQ);
+ bufferSQ.append(closingCharacterSQ);
+ document.replace(offset, length, bufferSQ.toString());
+ LinkedPositionManager managerSQ = new LinkedPositionManager(
+ document);
+ managerSQ.addPosition(offset + 1, 0);
+ fOffset = offset;
+ fLength = 2;
+ LinkedPositionUI editorSQ = new LinkedPositionUI(
+ sourceViewer, managerSQ);
+ editorSQ.setCancelListener(this);
+ editorSQ.setExitPolicy(new ExitPolicy(
+ closingCharacterSQ));
+ editorSQ.setFinalCaretOffset(offset + 2);
+ editorSQ.enter();
+ IRegion newSelectionSQ = editorSQ.getSelectedRegion();
+ sourceViewer.setSelectedRange(newSelectionSQ
+ .getOffset(), newSelectionSQ.getLength());
+ event.doit = false;
+ case '\r': { // insert linebreaks and new closing brace
+ // after brace and return
+ if (!fCloseBracketsPHP) {
+ return;
+ }
+ if (hasCharacterToTheLeft(document, offset, '{')
+ && hasCharacterToTheRight(document, offset, '}')) {
+ String lineDelimiter = StubUtility
+ .getLineDelimiterFor(document);
+ int caretPos = sourceViewer.getTextWidget()
+ .getCaretOffset();
+ final StringBuffer buffer = new StringBuffer(
+ lineDelimiter);
+ // get indentation
+ IRegion line = document
+ .getLineInformationOfOffset(offset);
+ String currentLine = document.get(line.getOffset(),
+ line.getLength());
+ int index = 0;
+ int max = currentLine.length();
+ StringBuffer indent = new StringBuffer();
+ while (index < max
+ && Character.isWhitespace(currentLine
+ .charAt(index))) {
+ indent.append(currentLine.charAt(index));
+ index++;
+ }
+ buffer.append(indent);
+ JavaHeuristicScanner scanner = new JavaHeuristicScanner(
+ document);
+ JavaIndenter indenter = new JavaIndenter(document,
+ scanner);
+ buffer.append(indenter.createIndent(1));
+ int cursorPos = buffer.length();
+ buffer.append(lineDelimiter);
+ buffer.append(indent);
+ document.replace(offset, length, buffer.toString());
+ sourceViewer.getTextWidget().setCaretOffset(
+ caretPos + cursorPos);
+ event.doit = false;
+ }
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ }
+ }
+
+ /*
+ * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitListener#exit(boolean)
+ */
+ public void exit(boolean accept) {
+ if (accept)
+ return;
+ // remove brackets
+ try {
+ final ISourceViewer sourceViewer = getSourceViewer();
+ IDocument document = sourceViewer.getDocument();
+ document.replace(fOffset, fLength, null);
+ } catch (BadLocationException e) {
+ }
+ }
+ }
+
+ /** The editor's save policy */
+ protected ISavePolicy fSavePolicy;
+
+ /**
+ * Listener to annotation model changes that updates the error tick in the
+ * tab image
+ */
+ private JavaEditorErrorTickUpdater fJavaEditorErrorTickUpdater;
+
+ /** The editor's paint manager */
+ // private PaintManager fPaintManager;
+ /** The editor's bracket painter */
+ // private BracketPainter fBracketPainter;
+ /** The editor's bracket matcher */
+ private PHPPairMatcher fBracketMatcher;
+
+ /** The editor's line painter */
+ // private LinePainter fLinePainter;
+ /** The editor's print margin ruler painter */
+ // private PrintMarginPainter fPrintMarginPainter;
+ /** The editor's problem painter */
+ // private ProblemPainter fProblemPainter;
+ /** The editor's tab converter */
+ private TabConverter fTabConverter;
+
+ /** History for structure select action */
+ // private SelectionHistory fSelectionHistory;
+ /** The preference property change listener for php core. */
+ // private IPropertyChangeListener fPropertyChangeListener = new
+ // PropertyChangeListener();
+ /** The remembered java element */
+ private IJavaElement fRememberedElement;
+
+ /**
+ * The remembered selection.
+ *
+ * @since 3.0
+ */
+ private RememberedSelection fRememberedSelection = new RememberedSelection();
+
+ /** The remembered php element offset */
+ private int fRememberedElementOffset;
+
+ /** The bracket inserter. */
+ private BracketInserter fBracketInserter = new BracketInserter();
+
+ /** The standard action groups added to the menu */
+ private GenerateActionGroup fGenerateActionGroup;
+
+ private CompositeActionGroup fContextMenuGroup;
+
+ // private class PropertyChangeListener implements IPropertyChangeListener {
+ // /*
+ // * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ // */
+ // public void
+ // propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent
+ // event) {
+ // handlePreferencePropertyChanged(event);
+ // }
+ // }
+ /* Preference key for code formatter tab size */
+ private final static String CODE_FORMATTER_TAB_SIZE = JavaCore.FORMATTER_TAB_SIZE;
+
+ /** Preference key for matching brackets */
+ // private final static String MATCHING_BRACKETS =
+ // PreferenceConstants.EDITOR_MATCHING_BRACKETS;
+ /** Preference key for matching brackets color */
+ // private final static String MATCHING_BRACKETS_COLOR =
+ // PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
+ /** Preference key for highlighting current line */
+ // private final static String CURRENT_LINE =
+ // PreferenceConstants.EDITOR_CURRENT_LINE;
+ /** Preference key for highlight color of current line */
+ // private final static String CURRENT_LINE_COLOR =
+ // PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
+ /** Preference key for showing print marging ruler */
+ // private final static String PRINT_MARGIN =
+ // PreferenceConstants.EDITOR_PRINT_MARGIN;
+ /** Preference key for print margin ruler color */
+ // private final static String PRINT_MARGIN_COLOR =
+ // PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
+ /** Preference key for print margin ruler column */
+ // private final static String PRINT_MARGIN_COLUMN =
+ // PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
+ /** Preference key for inserting spaces rather than tabs */
+ private final static String SPACES_FOR_TABS = PreferenceConstants.EDITOR_SPACES_FOR_TABS;
+
+ /** Preference key for error indication */
+ // private final static String ERROR_INDICATION =
+ // PreferenceConstants.EDITOR_PROBLEM_INDICATION;
+ /** Preference key for error color */
+ // private final static String ERROR_INDICATION_COLOR =
+ // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
+ /** Preference key for warning indication */
+ // private final static String WARNING_INDICATION =
+ // PreferenceConstants.EDITOR_WARNING_INDICATION;
+ /** Preference key for warning color */
+ // private final static String WARNING_INDICATION_COLOR =
+ // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
+ /** Preference key for task indication */
+ private final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
+
+ /** Preference key for task color */
+ private final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
+
+ /** Preference key for bookmark indication */
+ private final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
+
+ /** Preference key for bookmark color */
+ private final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
+
+ /** Preference key for search result indication */
+ private final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
+
+ /** Preference key for search result color */
+ private final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
+
+ /** Preference key for unknown annotation indication */
+ private final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
+
+ /** Preference key for unknown annotation color */
+ private final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
+
+ /** Preference key for linked position color */
+ private final static String LINKED_POSITION_COLOR = PreferenceConstants.EDITOR_LINKED_POSITION_COLOR;
+
+ /** Preference key for shwoing the overview ruler */
+ private final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
+
+ /** Preference key for error indication in overview ruler */
+ private final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for warning indication in overview ruler */
+ private final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for task indication in overview ruler */
+ private final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for bookmark indication in overview ruler */
+ private final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for search result indication in overview ruler */
+ private final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for unknown annotation indication in overview ruler */
+ private final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
+
+ /** Preference key for automatically closing double quoted strings */
+ private final static String CLOSE_STRINGS_DQ_PHP = PreferenceConstants.EDITOR_CLOSE_STRINGS_DQ_PHP;
+
+ /** Preference key for automatically closing single quoted strings */
+ private final static String CLOSE_STRINGS_SQ_PHP = PreferenceConstants.EDITOR_CLOSE_STRINGS_SQ_PHP;
+
+ /** Preference key for automatically wrapping Java strings */
+ // private final static String WRAP_STRINGS =
+ // PreferenceConstants.EDITOR_WRAP_STRINGS_DQ;
+ /** Preference key for automatically closing brackets and parenthesis */
+ private final static String CLOSE_BRACKETS_PHP = PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP;
+
+ /** Preference key for automatically closing phpdocs and comments */
+ private final static String CLOSE_JAVADOCS = PreferenceConstants.EDITOR_CLOSE_JAVADOCS;
+
+ /** Preference key for automatically adding phpdoc tags */
+ private final static String ADD_JAVADOC_TAGS = PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS;
+
+ /** Preference key for automatically formatting phpdocs */
+ // private final static String FORMAT_JAVADOCS =
+ // PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
+ /** Preference key for automatically closing strings */
+ private final static String CLOSE_STRINGS_HTML = PreferenceConstants.EDITOR_CLOSE_STRINGS_HTML;
+
+ /** Preference key for automatically closing brackets and parenthesis */
+ private final static String CLOSE_BRACKETS_HTML = PreferenceConstants.EDITOR_CLOSE_BRACKETS_HTML;
+
+ /** Preference key for smart paste */
+ private final static String SMART_PASTE = PreferenceConstants.EDITOR_SMART_PASTE;
+
+ // private final static class AnnotationInfo {
+ // public String fColorPreference;
+ // public String fOverviewRulerPreference;
+ // public String fEditorPreference;
+ // };
+ // private final static Map ANNOTATION_MAP;
+ // static {
+ //
+ // AnnotationInfo info;
+ // ANNOTATION_MAP = new HashMap();
+ //
+ // info = new AnnotationInfo();
+ // info.fColorPreference = TASK_INDICATION_COLOR;
+ // info.fOverviewRulerPreference = TASK_INDICATION_IN_OVERVIEW_RULER;
+ // info.fEditorPreference = TASK_INDICATION;
+ // ANNOTATION_MAP.put(AnnotationType.TASK, info);
+ //
+ // info = new AnnotationInfo();
+ // info.fColorPreference = ERROR_INDICATION_COLOR;
+ // info.fOverviewRulerPreference = ERROR_INDICATION_IN_OVERVIEW_RULER;
+ // info.fEditorPreference = ERROR_INDICATION;
+ // ANNOTATION_MAP.put(AnnotationType.ERROR, info);
+ //
+ // info = new AnnotationInfo();
+ // info.fColorPreference = WARNING_INDICATION_COLOR;
+ // info.fOverviewRulerPreference = WARNING_INDICATION_IN_OVERVIEW_RULER;
+ // info.fEditorPreference = WARNING_INDICATION;
+ // ANNOTATION_MAP.put(AnnotationType.WARNING, info);
+ //
+ // info = new AnnotationInfo();
+ // info.fColorPreference = BOOKMARK_INDICATION_COLOR;
+ // info.fOverviewRulerPreference = BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
+ // info.fEditorPreference = BOOKMARK_INDICATION;
+ // ANNOTATION_MAP.put(AnnotationType.BOOKMARK, info);
+ //
+ // info = new AnnotationInfo();
+ // info.fColorPreference = SEARCH_RESULT_INDICATION_COLOR;
+ // info.fOverviewRulerPreference =
+ // SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
+ // info.fEditorPreference = SEARCH_RESULT_INDICATION;
+ // ANNOTATION_MAP.put(AnnotationType.SEARCH, info);
+ //
+ // info = new AnnotationInfo();
+ // info.fColorPreference = UNKNOWN_INDICATION_COLOR;
+ // info.fOverviewRulerPreference = UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
+ // info.fEditorPreference = UNKNOWN_INDICATION;
+ // ANNOTATION_MAP.put(AnnotationType.UNKNOWN, info);
+ // };
+ //
+ // private final static AnnotationType[] ANNOTATION_LAYERS =
+ // new AnnotationType[] {
+ // AnnotationType.UNKNOWN,
+ // AnnotationType.BOOKMARK,
+ // AnnotationType.TASK,
+ // AnnotationType.SEARCH,
+ // AnnotationType.WARNING,
+ // AnnotationType.ERROR };
+ /**
+ * Creates a new php unit editor.
+ */
+
+ /**
+ * Reconciling listeners.
+ *
+ * @since 3.0
+ */
+ private ListenerList fReconcilingListeners = new ListenerList();
+
+ /**
+ * Mutex for the reconciler. See
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898 for a description of
+ * the problem.
+ *
+ * TODO remove once the underlying problem is solved.
+ *
+ */
+ private final Object fReconcilerLock = new Object();
+
+ public PHPUnitEditor() {
+ super();
+ setDocumentProvider(WebUI.getDefault()
+ .getCompilationUnitDocumentProvider());
+ setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
+ setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
+ setOutlinerContextMenuId("#PHPOutlinerContext"); //$NON-NLS-1$
+ // don't set help contextId, we install our own help context
+ fSavePolicy = null;
+ fJavaEditorErrorTickUpdater = new JavaEditorErrorTickUpdater(this);
+ }
+
+ /*
+ * @see AbstractTextEditor#createActions()
+ */
+ protected void createActions() {
+ super.createActions();
+ Action action;
+ // Action action= new
+ // TextOperationAction(PHPEditorMessages.getResourceBundle(),
+ // "CorrectionAssistProposal.", this, CORRECTIONASSIST_PROPOSALS);
+ // //$NON-NLS-1$
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.CORRECTION_ASSIST_PROPOSALS);
+ // setAction("CorrectionAssistProposal", action); //$NON-NLS-1$
+ // markAsStateDependentAction("CorrectionAssistProposal", true);
+ // //$NON-NLS-1$
+ // // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.QUICK_FIX_ACTION);
+ action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(),
+ "ContentAssistProposal.", this); //$NON-NLS-1$
+ action
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ setAction("ContentAssistProposal", action); //$NON-NLS-1$
+ markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.CONTENT_ASSIST_ACTION);
+ // action = new
+ // TextOperationAction(PHPEditorMessages.getResourceBundle(),
+ // "ContentAssistContextInformation.", this,
+ // ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
+ // action
+ // .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
+ // setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
+ // markAsStateDependentAction("ContentAssistContextInformation", true);
+ // //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.PARAMETER_HINTS_ACTION);
+ // action= new
+ // TextOperationAction(PHPEditorMessages.getResourceBundle(),
+ // "ContentAssistCompletePrefix.", this, CONTENTASSIST_COMPLETE_PREFIX);
+ // //$NON-NLS-1$
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_COMPLETE_PREFIX);
+ // setAction("ContentAssistCompletePrefix", action); //$NON-NLS-1$
+ // markAsStateDependentAction("ContentAssistCompletePrefix", true);
+ // //$NON-NLS-1$
+ // // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.PARAMETER_HINTS_ACTION);
+ action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
+ "Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$
+ action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
+ setAction("Comment", action); //$NON-NLS-1$
+ markAsStateDependentAction("Comment", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.COMMENT_ACTION);
+ action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
+ "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
+ action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
+ setAction("Uncomment", action); //$NON-NLS-1$
+ markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.UNCOMMENT_ACTION);
+
+ action = new ToggleCommentAction(PHPEditorMessages.getResourceBundle(),
+ "ToggleComment.", this); //$NON-NLS-1$
+ action
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.TOGGLE_COMMENT);
+ setAction("ToggleComment", action); //$NON-NLS-1$
+ markAsStateDependentAction("ToggleComment", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.TOGGLE_COMMENT_ACTION);
+ configureToggleCommentAction();
+
+ action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
+ "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$
+ action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT);
+ setAction("Format", action); //$NON-NLS-1$
+ markAsStateDependentAction("Format", true); //$NON-NLS-1$
+ markAsSelectionDependentAction("Format", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.FORMAT_ACTION);
+
+ // action = new
+ // AddBlockCommentAction(PHPEditorMessages.getResourceBundle(),
+ // "AddBlockComment.", this); //$NON-NLS-1$
+ // action
+ // .setActionDefinitionId(PHPEditorActionDefinitionIds.ADD_BLOCK_COMMENT);
+ // setAction("AddBlockComment", action); //$NON-NLS-1$
+ // markAsStateDependentAction("AddBlockComment", true); //$NON-NLS-1$
+ // markAsSelectionDependentAction("AddBlockComment", true);
+ // //$NON-NLS-1$
+ // // WorkbenchHelp.setHelp(action,
+ // // IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
+ // action = new RemoveBlockCommentAction(
+ // PHPEditorMessages.getResourceBundle(), "RemoveBlockComment.", this);
+ // //$NON-NLS-1$
+ // action
+ // .setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_BLOCK_COMMENT);
+ // setAction("RemoveBlockComment", action); //$NON-NLS-1$
+ // markAsStateDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
+ // markAsSelectionDependentAction("RemoveBlockComment", true);
+ // //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
+ action = new IndentAction(PHPEditorMessages.getResourceBundle(),
+ "Indent.", this, false); //$NON-NLS-1$
+ action.setActionDefinitionId(PHPEditorActionDefinitionIds.INDENT);
+ setAction("Indent", action); //$NON-NLS-1$
+ markAsStateDependentAction("Indent", true); //$NON-NLS-1$
+ markAsSelectionDependentAction("Indent", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.INDENT_ACTION);
+ //
+ // action= new IndentAction(PHPEditorMessages.getResourceBundle(),
+ // "Indent.", this, true); //$NON-NLS-1$
+ // setAction("IndentOnTab", action); //$NON-NLS-1$
+ // markAsStateDependentAction("IndentOnTab", true); //$NON-NLS-1$
+ // markAsSelectionDependentAction("IndentOnTab", true); //$NON-NLS-1$
+ //
+
+ action = new AddBlockCommentAction(PHPEditorMessages
+ .getResourceBundle(), "AddBlockComment.", this); //$NON-NLS-1$
+ action
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.ADD_BLOCK_COMMENT);
+ setAction("AddBlockComment", action); //$NON-NLS-1$
+ markAsStateDependentAction("AddBlockComment", true); //$NON-NLS-1$
+ markAsSelectionDependentAction("AddBlockComment", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
+
+ action = new RemoveBlockCommentAction(PHPEditorMessages
+ .getResourceBundle(), "RemoveBlockComment.", this); //$NON-NLS-1$
+ action
+ .setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_BLOCK_COMMENT);
+ setAction("RemoveBlockComment", action); //$NON-NLS-1$
+ markAsStateDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
+ markAsSelectionDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
+ // WorkbenchHelp.setHelp(action,
+ // IJavaHelpContextIds.REMOVE_BLOCK_COMMENT_ACTION);
+
+ // action= new IndentAction(PHPEditorMessages.getResourceBundle(),
+ // "Indent.", this, false); //$NON-NLS-1$
+ // action.setActionDefinitionId(PHPEditorActionDefinitionIds.INDENT);
+ // setAction("Indent", action); //$NON-NLS-1$
+ // markAsStateDependentAction("Indent", true); //$NON-NLS-1$
+ // markAsSelectionDependentAction("Indent", true); //$NON-NLS-1$
+ // // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.INDENT_ACTION);
+ //
+ action = new IndentAction(PHPEditorMessages.getResourceBundle(),
+ "Indent.", this, true); //$NON-NLS-1$
+ setAction("IndentOnTab", action); //$NON-NLS-1$
+ markAsStateDependentAction("IndentOnTab", true); //$NON-NLS-1$
+ markAsSelectionDependentAction("IndentOnTab", true); //$NON-NLS-1$
+
+ if (getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_SMART_TAB)) {
+ // don't replace Shift Right - have to make sure their enablement is
+ // mutually exclusive
+ // removeActionActivationCode(ITextEditorActionConstants.SHIFT_RIGHT);
+ setActionActivationCode("IndentOnTab", '\t', -1, SWT.NONE); //$NON-NLS-1$
+ }
+ fGenerateActionGroup = new GenerateActionGroup(this,
+ ITextEditorActionConstants.GROUP_EDIT);
+ // ActionGroup rg= new RefactorActionGroup(this,
+ // ITextEditorActionConstants.GROUP_EDIT);
+
+ // fActionGroups.addGroup(rg);
+ fActionGroups.addGroup(fGenerateActionGroup);
+
+ // We have to keep the context menu group separate to have better
+ // control over positioning
+ fContextMenuGroup = new CompositeActionGroup(
+ new ActionGroup[] { fGenerateActionGroup
+ // rg,
+ // new LocalHistoryActionGroup(this,
+ // ITextEditorActionConstants.GROUP_EDIT)
+ });
+
+ }
+
+ /*
+ * @see JavaEditor#getElementAt(int)
+ */
+ protected IJavaElement getElementAt(int offset) {
+ return getElementAt(offset, true);
+ }
+
+ /**
+ * Returns the most narrow element including the given offset. If
+ * reconcile
is true
the editor's input
+ * element is reconciled in advance. If it is false
this
+ * method only returns a result if the editor's input element does not need
+ * to be reconciled.
+ *
+ * @param offset
+ * the offset included by the retrieved element
+ * @param reconcile
+ * true
if working copy should be reconciled
+ */
+ protected IJavaElement getElementAt(int offset, boolean reconcile) {
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
+ if (unit != null) {
+ try {
+ if (reconcile) {
+ synchronized (unit) {
+ unit.reconcile();
+ }
+ return unit.getElementAt(offset);
+ } else if (unit.isConsistent())
+ return unit.getElementAt(offset);
+ } catch (JavaModelException x) {
+ PHPeclipsePlugin.log(x.getStatus());
+ // nothing found, be tolerant and go on
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see JavaEditor#getCorrespondingElement(IJavaElement)
+ */
+ protected IJavaElement getCorrespondingElement(IJavaElement element) {
+ try {
+ return EditorUtility.getWorkingCopy(element, true);
+ } catch (JavaModelException x) {
+ PHPeclipsePlugin.log(x.getStatus());
+ // nothing found, be tolerant and go on
+ }
+ return null;
+ }
+
+ public void createPartControl(Composite parent) {
+ super.createPartControl(parent);
+ // fPaintManager = new PaintManager(getSourceViewer());
+ LinePainter linePainter;
+ linePainter = new LinePainter(getSourceViewer());
+ linePainter.setHighlightColor(new Color(Display.getCurrent(), 225, 235,
+ 224));
+ // fPaintManager.addPainter(linePainter);
+ // if (isBracketHighlightingEnabled())
+ // startBracketHighlighting();
+ // if (isLineHighlightingEnabled())
+ // startLineHighlighting();
+ // if (isPrintMarginVisible())
+ // showPrintMargin();
+ // Iterator e = ANNOTATION_MAP.keySet().iterator();
+ // while (e.hasNext()) {
+ // AnnotationType type = (AnnotationType) e.next();
+ // if (isAnnotationIndicationEnabled(type))
+ // startAnnotationIndication(type);
+ // }
+ if (isTabConversionEnabled())
+ startTabConversion();
+ // if (isOverviewRulerVisible())
+ // showOverviewRuler();
+ //
+ // Preferences preferences =
+ // PHPeclipsePlugin.getDefault().getPluginPreferences();
+ // preferences.addPropertyChangeListener(fPropertyChangeListener);
+ IPreferenceStore preferenceStore = getPreferenceStore();
+ boolean closeBracketsPHP = preferenceStore
+ .getBoolean(CLOSE_BRACKETS_PHP);
+ boolean closeStringsPHPDQ = preferenceStore
+ .getBoolean(CLOSE_STRINGS_DQ_PHP);
+ boolean closeStringsPHPSQ = preferenceStore
+ .getBoolean(CLOSE_STRINGS_SQ_PHP);
+ fBracketInserter.setCloseBracketsPHPEnabled(closeBracketsPHP);
+ fBracketInserter.setCloseStringsPHPDQEnabled(closeStringsPHPDQ);
+ fBracketInserter.setCloseStringsPHPSQEnabled(closeStringsPHPSQ);
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer instanceof ITextViewerExtension)
+ ((ITextViewerExtension) sourceViewer)
+ .prependVerifyKeyListener(fBracketInserter);
+ }
+
+ private static char getPeerCharacter(char character) {
+ switch (character) {
+ case '(':
+ return ')';
+ case ')':
+ return '(';
+ case '[':
+ return ']';
+ case ']':
+ return '[';
+ case '"':
+ return character;
+ case '\'':
+ return character;
+ case '{':
+ return '}';
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ // private void startBracketHighlighting() {
+ // if (fBracketPainter == null) {
+ // ISourceViewer sourceViewer = getSourceViewer();
+ // fBracketPainter = new BracketPainter(sourceViewer);
+ // fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
+ // // fPaintManager.addPainter(fBracketPainter);
+ // }
+ // }
+ //
+ // private void stopBracketHighlighting() {
+ // if (fBracketPainter != null) {
+ // // fPaintManager.removePainter(fBracketPainter);
+ // fBracketPainter.deactivate(true);
+ // fBracketPainter.dispose();
+ // fBracketPainter = null;
+ // }
+ // }
+
+ // private boolean isBracketHighlightingEnabled() {
+ // IPreferenceStore store = getPreferenceStore();
+ // return store.getBoolean(MATCHING_BRACKETS);
+ // }
+
+ // private void startLineHighlighting() {
+ // if (fLinePainter == null) {
+ // ISourceViewer sourceViewer = getSourceViewer();
+ // fLinePainter = new LinePainter(sourceViewer);
+ // fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR));
+ // // fPaintManager.addPainter(fLinePainter);
+ // }
+ // }
+
+ // private void stopLineHighlighting() {
+ // if (fLinePainter != null) {
+ // // fPaintManager.removePainter(fLinePainter);
+ // fLinePainter.deactivate(true);
+ // fLinePainter.dispose();
+ // fLinePainter = null;
+ // }
+ // }
+
+ // private boolean isLineHighlightingEnabled() {
+ // IPreferenceStore store = getPreferenceStore();
+ // return store.getBoolean(CURRENT_LINE);
+ // }
+
+ // private void showPrintMargin() {
+ // if (fPrintMarginPainter == null) {
+ // fPrintMarginPainter = new PrintMarginPainter(getSourceViewer());
+ // fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
+ // fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
+ // // fPaintManager.addPainter(fPrintMarginPainter);
+ // }
+ // }
+
+ // private void hidePrintMargin() {
+ // if (fPrintMarginPainter != null) {
+ // // fPaintManager.removePainter(fPrintMarginPainter);
+ // fPrintMarginPainter.deactivate(true);
+ // fPrintMarginPainter.dispose();
+ // fPrintMarginPainter = null;
+ // }
+ // }
+
+ // private boolean isPrintMarginVisible() {
+ // IPreferenceStore store = getPreferenceStore();
+ // return store.getBoolean(PRINT_MARGIN);
+ // }
+
+ private int getTabSize() {
+ Preferences preferences = PHPeclipsePlugin.getDefault()
+ .getPluginPreferences();
+ return preferences.getInt(CODE_FORMATTER_TAB_SIZE);
+ }
+
+ private boolean isTabConversionEnabled() {
+ IPreferenceStore store = getPreferenceStore();
+ return store.getBoolean(SPACES_FOR_TABS);
+ }
+
+ private Color getColor(String key) {
+ RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
+ return getColor(rgb);
+ }
+
+ private Color getColor(RGB rgb) {
+ JavaTextTools textTools = WebUI.getDefault()
+ .getJavaTextTools();
+ return textTools.getColorManager().getColor(rgb);
+ }
+
+ // private Color getColor(AnnotationType annotationType) {
+ // AnnotationInfo info = (AnnotationInfo)
+ // ANNOTATION_MAP.get(annotationType);
+ // if (info != null)
+ // return getColor(info.fColorPreference);
+ // return null;
+ // }
+ public void dispose() {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer instanceof ITextViewerExtension)
+ ((ITextViewerExtension) sourceViewer)
+ .removeVerifyKeyListener(fBracketInserter);
+ // if (fPropertyChangeListener != null) {
+ // Preferences preferences =
+ // PHPeclipsePlugin.getDefault().getPluginPreferences();
+ // preferences.removePropertyChangeListener(fPropertyChangeListener);
+ // fPropertyChangeListener = null;
+ // }
+ if (fJavaEditorErrorTickUpdater != null) {
+ fJavaEditorErrorTickUpdater.dispose();
+ fJavaEditorErrorTickUpdater = null;
+ }
+ // if (fSelectionHistory != null)
+ // fSelectionHistory.dispose();
+ // if (fPaintManager != null) {
+ // fPaintManager.dispose();
+ // fPaintManager = null;
+ // }
+ if (fActionGroups != null) {
+ fActionGroups.dispose();
+ fActionGroups = null;
+ }
+ super.dispose();
+ }
+
+ // protected AnnotationType getAnnotationType(String preferenceKey) {
+ // Iterator e = ANNOTATION_MAP.keySet().iterator();
+ // while (e.hasNext()) {
+ // AnnotationType type = (AnnotationType) e.next();
+ // AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(type);
+ // if (info != null) {
+ // if (preferenceKey.equals(info.fColorPreference)
+ // || preferenceKey.equals(info.fEditorPreference)
+ // || preferenceKey.equals(info.fOverviewRulerPreference))
+ // return type;
+ // }
+ // }
+ // return null;
+ // }
+ /*
+ * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
+ */
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ try {
+ AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
+ if (asv != null) {
+ String p = event.getProperty();
+ if (CLOSE_BRACKETS_PHP.equals(p)) {
+ fBracketInserter
+ .setCloseBracketsPHPEnabled(getPreferenceStore()
+ .getBoolean(p));
+ return;
+ }
+ if (CLOSE_STRINGS_DQ_PHP.equals(p)) {
+ fBracketInserter
+ .setCloseStringsPHPDQEnabled(getPreferenceStore()
+ .getBoolean(p));
+ return;
+ }
+ if (CLOSE_STRINGS_SQ_PHP.equals(p)) {
+ fBracketInserter
+ .setCloseStringsPHPSQEnabled(getPreferenceStore()
+ .getBoolean(p));
+ return;
+ }
+ if (SPACES_FOR_TABS.equals(p)) {
+ if (isTabConversionEnabled())
+ startTabConversion();
+ else
+ stopTabConversion();
+ return;
+ }
+ // if (MATCHING_BRACKETS.equals(p)) {
+ // if (isBracketHighlightingEnabled())
+ // startBracketHighlighting();
+ // else
+ // stopBracketHighlighting();
+ // return;
+ // }
+ // if (MATCHING_BRACKETS_COLOR.equals(p)) {
+ // if (fBracketPainter != null)
+ // fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
+ // return;
+ // }
+ // if (CURRENT_LINE.equals(p)) {
+ // if (isLineHighlightingEnabled())
+ // startLineHighlighting();
+ // else
+ // stopLineHighlighting();
+ // return;
+ // }
+ // if (CURRENT_LINE_COLOR.equals(p)) {
+ // if (fLinePainter != null) {
+ // stopLineHighlighting();
+ // startLineHighlighting();
+ // }
+ // return;
+ // }
+ // if (PRINT_MARGIN.equals(p)) {
+ // if (isPrintMarginVisible())
+ // showPrintMargin();
+ // else
+ // hidePrintMargin();
+ // return;
+ // }
+ // if (PRINT_MARGIN_COLOR.equals(p)) {
+ // if (fPrintMarginPainter != null)
+ // fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
+ // return;
+ // }
+ // if (PRINT_MARGIN_COLUMN.equals(p)) {
+ // if (fPrintMarginPainter != null)
+ // fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
+ // return;
+ // }
+ // if (OVERVIEW_RULER.equals(p)) {
+ // if (isOverviewRulerVisible())
+ // showOverviewRuler();
+ // else
+ // hideOverviewRuler();
+ // return;
+ // }
+ // AnnotationType type = getAnnotationType(p);
+ // if (type != null) {
+ //
+ // AnnotationInfo info = (AnnotationInfo)
+ // ANNOTATION_MAP.get(type);
+ // if (info.fColorPreference.equals(p)) {
+ // Color color = getColor(type);
+ // if (fProblemPainter != null) {
+ // fProblemPainter.setColor(type, color);
+ // fProblemPainter.paint(IPainter.CONFIGURATION);
+ // }
+ // setColorInOverviewRuler(type, color);
+ // return;
+ // }
+ //
+ // if (info.fEditorPreference.equals(p)) {
+ // if (isAnnotationIndicationEnabled(type))
+ // startAnnotationIndication(type);
+ // else
+ // stopAnnotationIndication(type);
+ // return;
+ // }
+ //
+ // if (info.fOverviewRulerPreference.equals(p)) {
+ // if (isAnnotationIndicationInOverviewRulerEnabled(type))
+ // showAnnotationIndicationInOverviewRuler(type, true);
+ // else
+ // showAnnotationIndicationInOverviewRuler(type, false);
+ // return;
+ // }
+ // }
+ IContentAssistant c = asv.getContentAssistant();
+ if (c instanceof ContentAssistant)
+ ContentAssistPreference.changeConfiguration(
+ (ContentAssistant) c, getPreferenceStore(), event);
+ }
+ } finally {
+ super.handlePreferenceStoreChanged(event);
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor#handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
+ */
+ protected void handlePreferencePropertyChanged(
+ org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
+ AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
+ if (asv != null) {
+ String p = event.getProperty();
+ if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
+ asv.updateIndentationPrefixes();
+ if (fTabConverter != null)
+ fTabConverter.setNumberOfSpacesPerTab(getTabSize());
+ }
+ }
+ super.handlePreferencePropertyChanged(event);
+ }
+
+ /**
+ * Handles a property change event describing a change of the php core's
+ * preferences and updates the preference related editor properties.
+ *
+ * @param event
+ * the property change event
+ */
+ // protected void
+ // handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent
+ // event) {
+ // AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
+ // if (asv != null) {
+ // String p = event.getProperty();
+ // if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
+ // asv.updateIndentationPrefixes();
+ // if (fTabConverter != null)
+ // fTabConverter.setNumberOfSpacesPerTab(getTabSize());
+ // }
+ // }
+ // }
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor#createJavaSourceViewer(org.eclipse.swt.widgets.Composite,
+ * org.eclipse.jface.text.source.IVerticalRuler,
+ * org.eclipse.jface.text.source.IOverviewRuler, boolean, int)
+ */
+ protected ISourceViewer createJavaSourceViewer(Composite parent,
+ IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
+ boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
+ return new AdaptedSourceViewer(parent, verticalRuler, overviewRuler,
+ isOverviewRulerVisible, styles, store);
+ }
+
+ // protected ISourceViewer createJavaSourceViewer(Composite parent,
+ // IVerticalRuler ruler, int styles) {
+ // return new AdaptedSourceViewer(parent, ruler, styles);
+ // }
+ private boolean isValidSelection(int offset, int length) {
+ IDocumentProvider provider = getDocumentProvider();
+ if (provider != null) {
+ IDocument document = provider.getDocument(getEditorInput());
+ if (document != null) {
+ int end = offset + length;
+ int documentLength = document.getLength();
+ return 0 <= offset && offset <= documentLength && 0 <= end
+ && end <= documentLength;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor#getInputElement()
+ */
+ protected IJavaElement getInputJavaElement() {
+ return WebUI.getDefault().getWorkingCopyManager()
+ .getWorkingCopy(getEditorInput());
+ }
+
+ /*
+ * @see AbstractTextEditor#editorContextMenuAboutToShow(IMenuManager)
+ */
+ public void editorContextMenuAboutToShow(IMenuManager menu) {
+ super.editorContextMenuAboutToShow(menu);
+ ActionContext context = new ActionContext(getSelectionProvider()
+ .getSelection());
+ fContextMenuGroup.setContext(context);
+ fContextMenuGroup.fillContextMenu(menu);
+ fContextMenuGroup.setContext(null);
+ }
+
+ /*
+ * @see JavaEditor#setOutlinePageInput(JavaOutlinePage, IEditorInput)
+ */
+ protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input) {
+ if (page != null) {
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ page.setInput(manager.getWorkingCopy(input));
+ }
+ }
+
+ /*
+ * @see AbstractTextEditor#performSaveOperation(WorkspaceModifyOperation,
+ * IProgressMonitor)
+ */
+ // protected void performSaveOperation(WorkspaceModifyOperation operation,
+ // IProgressMonitor progressMonitor) {
+ // IDocumentProvider p = getDocumentProvider();
+ // if (p instanceof PHPDocumentProvider) {
+ // PHPDocumentProvider cp = (PHPDocumentProvider) p;
+ // cp.setSavePolicy(fSavePolicy);
+ // }
+ //
+ // try {
+ // super.performSaveOperation(operation, progressMonitor);
+ // } finally {
+ // if (p instanceof PHPDocumentProvider) {
+ // PHPDocumentProvider cp = (PHPDocumentProvider) p;
+ // cp.setSavePolicy(null);
+ // }
+ // }
+ // }
+ /*
+ * @see AbstractTextEditor#doSave(IProgressMonitor)
+ */
+ public void doSave(IProgressMonitor progressMonitor) {
+
+ IDocumentProvider p = getDocumentProvider();
+ if (p == null) {
+ // editor has been closed
+ return;
+ }
+
+ if (p.isDeleted(getEditorInput())) {
+
+ if (isSaveAsAllowed()) {
+
+ /*
+ * 1GEUSSR: ITPUI:ALL - User should never loose changes made in
+ * the editors. Changed Behavior to make sure that if called
+ * inside a regular save (because of deletion of input element)
+ * there is a way to report back to the caller.
+ */
+ performSaveAs(progressMonitor);
+
+ } else {
+
+ /*
+ * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still
+ * there Missing resources.
+ */
+ Shell shell = getSite().getShell();
+ MessageDialog
+ .openError(
+ shell,
+ PHPEditorMessages
+ .getString("PHPUnitEditor.error.saving.title1"), PHPEditorMessages.getString("PHPUnitEditor.error.saving.message1")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ } else {
+ if (getPreferenceStore().getBoolean(
+ PreferenceConstants.EDITOR_P_RTRIM_ON_SAVE)) {
+ RTrimAction trimAction = new RTrimAction();
+ trimAction.setActiveEditor(null, getSite().getPage()
+ .getActiveEditor());
+ trimAction.run(null);
+ }
+
+ setStatusLineErrorMessage(null);
+
+ updateState(getEditorInput());
+ validateState(getEditorInput());
+
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
+
+ if (unit != null) {
+ synchronized (unit) {
+ performSave(false, progressMonitor);
+ }
+ } else
+ performSave(false, progressMonitor);
+ }
+ }
+
+ public boolean isSaveAsAllowed() {
+ return true;
+ }
+
+ /**
+ * The compilation unit editor implementation of this
+ * AbstractTextEditor
method asks the user for the workspace
+ * path of a file resource and saves the document there. See
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=6295
+ *
+ * @param progressMonitor
+ * the progress monitor
+ */
+ protected void performSaveAs(IProgressMonitor progressMonitor) {
+
+ Shell shell = getSite().getShell();
+ IEditorInput input = getEditorInput();
+
+ SaveAsDialog dialog = new SaveAsDialog(shell);
+
+ IFile original = (input instanceof IFileEditorInput) ? ((IFileEditorInput) input)
+ .getFile()
+ : null;
+ if (original != null)
+ dialog.setOriginalFile(original);
+
+ dialog.create();
+
+ IDocumentProvider provider = getDocumentProvider();
+ if (provider == null) {
+ // editor has been programmatically closed while the dialog was open
+ return;
+ }
+
+ if (provider.isDeleted(input) && original != null) {
+ String message = PHPEditorMessages
+ .getFormattedString(
+ "CompilationUnitEditor.warning.save.delete", new Object[] { original.getName() }); //$NON-NLS-1$
+ dialog.setErrorMessage(null);
+ dialog.setMessage(message, IMessageProvider.WARNING);
+ }
+
+ if (dialog.open() == Window.CANCEL) {
+ if (progressMonitor != null)
+ progressMonitor.setCanceled(true);
+ return;
+ }
+
+ IPath filePath = dialog.getResult();
+ if (filePath == null) {
+ if (progressMonitor != null)
+ progressMonitor.setCanceled(true);
+ return;
+ }
+
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IFile file = workspaceRoot.getFile(filePath);
+ final IEditorInput newInput = new FileEditorInput(file);
+
+ boolean success = false;
+ try {
+
+ provider.aboutToChange(newInput);
+ getDocumentProvider().saveDocument(progressMonitor, newInput,
+ getDocumentProvider().getDocument(getEditorInput()), true);
+ success = true;
+
+ } catch (CoreException x) {
+ IStatus status = x.getStatus();
+ if (status == null || status.getSeverity() != IStatus.CANCEL)
+ ErrorDialog
+ .openError(
+ shell,
+ PHPEditorMessages
+ .getString("CompilationUnitEditor.error.saving.title2"), PHPEditorMessages.getString("CompilationUnitEditor.error.saving.message2"), x.getStatus()); //$NON-NLS-1$ //$NON-NLS-2$
+ } finally {
+ provider.changed(newInput);
+ if (success)
+ setInput(newInput);
+ }
+
+ if (progressMonitor != null)
+ progressMonitor.setCanceled(!success);
+ }
+
+ /*
+ * @see AbstractTextEditor#doSetInput(IEditorInput)
+ */
+ protected void doSetInput(IEditorInput input) throws CoreException {
+ super.doSetInput(input);
+ configureTabConverter();
+ configureToggleCommentAction();
+ }
+
+ // /*
+ // * @see
+ // net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor#installOverrideIndicator(boolean)
+ // * @since 3.0
+ // */
+ // protected void installOverrideIndicator(boolean waitForReconcilation) {
+ // IAnnotationModel model=
+ // getDocumentProvider().getAnnotationModel(getEditorInput());
+ // if (!waitForReconcilation)
+ // super.installOverrideIndicator(false);
+ // else {
+ // uninstallOverrideIndicator();
+ // IJavaElement inputElement= getInputJavaElement();
+ // if (model == null || inputElement == null)
+ // return;
+ //
+ // fOverrideIndicatorManager= new OverrideIndicatorManager(model,
+ // inputElement, null);
+ // addReconcileListener(fOverrideIndicatorManager);
+ // }
+ // }
+ //
+ // /*
+ // * @see
+ // net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor#uninstallOverrideIndicator()
+ // * @since 3.0
+ // */
+ // protected void uninstallOverrideIndicator() {
+ // if (fOverrideIndicatorManager != null)
+ // removeReconcileListener(fOverrideIndicatorManager);
+ // super.uninstallOverrideIndicator();
+ // }
+
+ /**
+ * Configures the toggle comment action
+ *
+ * @since 3.0
+ */
+ private void configureToggleCommentAction() {
+ IAction action = getAction("ToggleComment"); //$NON-NLS-1$
+ if (action instanceof ToggleCommentAction) {
+ ISourceViewer sourceViewer = getSourceViewer();
+ SourceViewerConfiguration configuration = getSourceViewerConfiguration();
+ ((ToggleCommentAction) action).configure(sourceViewer,
+ configuration);
+ }
+ }
+
+ // private void configureTabConverter() {
+ // if (fTabConverter != null) {
+ // IDocumentProvider provider = getDocumentProvider();
+ // if (provider instanceof PHPDocumentProvider) {
+ // PHPDocumentProvider cup = (PHPDocumentProvider) provider;
+ // fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
+ // }
+ // }
+ // }
+ private void configureTabConverter() {
+ if (fTabConverter != null) {
+ IDocumentProvider provider = getDocumentProvider();
+ if (provider instanceof ICompilationUnitDocumentProvider) {
+ ICompilationUnitDocumentProvider cup = (ICompilationUnitDocumentProvider) provider;
+ fTabConverter.setLineTracker(cup
+ .createLineTracker(getEditorInput()));
+ }
+ }
+ }
+
+ private void startTabConversion() {
+ if (fTabConverter == null) {
+ fTabConverter = new TabConverter();
+ configureTabConverter();
+ fTabConverter.setNumberOfSpacesPerTab(getTabSize());
+ AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
+ asv.addTextConverter(fTabConverter);
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
+ asv.updateIndentationPrefixes();
+ }
+ }
+
+ private void stopTabConversion() {
+ if (fTabConverter != null) {
+ AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
+ asv.removeTextConverter(fTabConverter);
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
+ asv.updateIndentationPrefixes();
+ fTabConverter = null;
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#performSave(boolean,
+ * org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void performSave(boolean overwrite,
+ IProgressMonitor progressMonitor) {
+ // IDocumentProvider p = getDocumentProvider();
+ // if (p instanceof PHPDocumentProvider) {
+ // PHPDocumentProvider cp = (PHPDocumentProvider) p;
+ // cp.setSavePolicy(fSavePolicy);
+ // }
+ // try {
+ // super.performSave(overwrite, progressMonitor);
+ // } finally {
+ // if (p instanceof PHPDocumentProvider) {
+ // PHPDocumentProvider cp = (PHPDocumentProvider) p;
+ // cp.setSavePolicy(null);
+ // }
+ // }
+
+ IDocumentProvider p = getDocumentProvider();
+ if (p instanceof ICompilationUnitDocumentProvider) {
+ ICompilationUnitDocumentProvider cp = (ICompilationUnitDocumentProvider) p;
+ cp.setSavePolicy(fSavePolicy);
+ }
+ try {
+ super.performSave(overwrite, progressMonitor);
+ } finally {
+ if (p instanceof ICompilationUnitDocumentProvider) {
+ ICompilationUnitDocumentProvider cp = (ICompilationUnitDocumentProvider) p;
+ cp.setSavePolicy(null);
+ }
+ }
+ }
+
+ /*
+ * @see AbstractTextEditor#doSaveAs
+ */
+ public void doSaveAs() {
+ if (askIfNonWorkbenchEncodingIsOk()) {
+ super.doSaveAs();
+ }
+ }
+
+ /**
+ * Asks the user if it is ok to store in non-workbench encoding.
+ *
+ * @return if the user wants to continue
+ */
+ private boolean askIfNonWorkbenchEncodingIsOk() {
+ IDocumentProvider provider = getDocumentProvider();
+ if (provider instanceof IStorageDocumentProvider) {
+ IEditorInput input = getEditorInput();
+ IStorageDocumentProvider storageProvider = (IStorageDocumentProvider) provider;
+ String encoding = storageProvider.getEncoding(input);
+ String defaultEncoding = storageProvider.getDefaultEncoding();
+ if (encoding != null && !encoding.equals(defaultEncoding)) {
+ Shell shell = getSite().getShell();
+ String title = PHPEditorMessages
+ .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.title"); //$NON-NLS-1$
+ String msg;
+ if (input != null)
+ msg = MessageFormat
+ .format(
+ PHPEditorMessages
+ .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message1"),
+ new String[] { input.getName(), encoding }); //$NON-NLS-1$
+ else
+ msg = MessageFormat
+ .format(
+ PHPEditorMessages
+ .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message2"),
+ new String[] { encoding }); //$NON-NLS-1$
+ return MessageDialog.openQuestion(shell, title, msg);
+ }
+ }
+ return true;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.java.IJavaReconcilingListener#aboutToBeReconciled()
+ * @since 3.0
+ */
+ public void aboutToBeReconciled() {
+
+ // Notify AST provider
+ // PHPeclipsePlugin.getDefault().getASTProvider().aboutToBeReconciled(getInputJavaElement());
+
+ // Notify listeners
+ Object[] listeners = fReconcilingListeners.getListeners();
+ for (int i = 0, length = listeners.length; i < length; ++i)
+ ((IJavaReconcilingListener) listeners[i]).aboutToBeReconciled();
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit,
+ * boolean, IProgressMonitor)
+ * @since 3.0
+ */
+ public void reconciled(CompilationUnit ast, boolean forced,
+ IProgressMonitor progressMonitor) {
+
+ // Always notify AST provider
+ // PHPeclipsePlugin.getDefault().getASTProvider().reconciled(ast,
+ // getInputJavaElement());
+
+ // Notify listeners
+ // Object[] listeners = fReconcilingListeners.getListeners();
+ // for (int i = 0, length= listeners.length; i < length; ++i)
+ // ((IJavaReconcilingListener)listeners[i]).reconciled(ast, forced,
+ // progressMonitor);
+
+ // Update Java Outline page selection
+ if (!forced && !progressMonitor.isCanceled()) {
+ Shell shell = getSite().getShell();
+ if (shell != null && !shell.isDisposed()) {
+ shell.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ selectionChanged();
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Returns the updated java element for the old java element.
+ */
+ private IJavaElement findElement(IJavaElement element) {
+ if (element == null)
+ return null;
+ IWorkingCopyManager manager = WebUI.getDefault()
+ .getWorkingCopyManager();
+ ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
+ if (unit != null) {
+ try {
+ synchronized (unit) {
+ unit.reconcile();
+ }
+ IJavaElement[] findings = unit.findElements(element);
+ if (findings != null && findings.length > 0)
+ return findings[0];
+ } catch (JavaModelException x) {
+ PHPeclipsePlugin.log(x.getStatus());
+ // nothing found, be tolerant and go on
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the offset of the given Java element.
+ */
+ private int getOffset(IJavaElement element) {
+ if (element instanceof ISourceReference) {
+ ISourceReference sr = (ISourceReference) element;
+ try {
+ ISourceRange srcRange = sr.getSourceRange();
+ if (srcRange != null)
+ return srcRange.getOffset();
+ } catch (JavaModelException e) {
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * @see AbstractTextEditor#restoreSelection()
+ */
+ // protected void restoreSelection() {
+ // try {
+ // if (getSourceViewer() == null || fRememberedSelection == null)
+ // return;
+ // IJavaElement newElement = findElement(fRememberedElement);
+ // int newOffset = getOffset(newElement);
+ // int delta = (newOffset > -1 && fRememberedElementOffset > -1) ? newOffset
+ // - fRememberedElementOffset : 0;
+ // if (isValidSelection(delta + fRememberedSelection.getOffset(),
+ // fRememberedSelection.getLength()))
+ // selectAndReveal(delta + fRememberedSelection.getOffset(),
+ // fRememberedSelection.getLength());
+ // } finally {
+ // fRememberedSelection = null;
+ // fRememberedElement = null;
+ // fRememberedElementOffset = -1;
+ // }
+ // }
+ /**
+ * Tells whether this is the active editor in the active page.
+ *
+ * @return true
if this is the active editor in the active
+ * page
+ * @see IWorkbenchPage#getActiveEditor();
+ */
+ protected final boolean isActiveEditor() {
+ IWorkbenchWindow window = getSite().getWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ if (page == null)
+ return false;
+ IEditorPart activeEditor = page.getActiveEditor();
+ return activeEditor != null && activeEditor.equals(this);
+ }
+
+ /**
+ * Adds the given listener. Has no effect if an identical listener was not
+ * already registered.
+ *
+ * @param listener
+ * The reconcile listener to be added
+ * @since 3.0
+ */
+ final void addReconcileListener(IJavaReconcilingListener listener) {
+ synchronized (fReconcilingListeners) {
+ fReconcilingListeners.add(listener);
+ }
+ }
+
+ /**
+ * Removes the given listener. Has no effect if an identical listener was
+ * not already registered.
+ *
+ * @param listener
+ * the reconcile listener to be removed
+ * @since 3.0
+ */
+ final void removeReconcileListener(IJavaReconcilingListener listener) {
+ synchronized (fReconcilingListeners) {
+ fReconcilingListeners.remove(listener);
+ }
+ }
+
+ protected void updateStateDependentActions() {
+ super.updateStateDependentActions();
+ fGenerateActionGroup.editorStateChanged();
+ }
+
+ /*
+ * @see AbstractTextEditor#rememberSelection()
+ */
+ protected void rememberSelection() {
+ fRememberedSelection.remember();
+ }
+
+ /*
+ * @see AbstractTextEditor#restoreSelection()
+ */
+ protected void restoreSelection() {
+ fRememberedSelection.restore();
+ }
+
+ /*
+ * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
+ */
+ protected boolean canHandleMove(IEditorInput originalElement,
+ IEditorInput movedElement) {
+
+ String oldExtension = ""; //$NON-NLS-1$
+ if (originalElement instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput) originalElement).getFile();
+ if (file != null) {
+ String ext = file.getFileExtension();
+ if (ext != null)
+ oldExtension = ext;
+ }
+ }
+
+ String newExtension = ""; //$NON-NLS-1$
+ if (movedElement instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput) movedElement).getFile();
+ if (file != null)
+ newExtension = file.getFileExtension();
+ }
+
+ return oldExtension.equals(newExtension);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#isPrefQuickDiffAlwaysOn()
+ */
+ protected boolean isPrefQuickDiffAlwaysOn() {
+ // reestablishes the behaviour from AbstractDecoratedTextEditor which
+ // was hacked by JavaEditor
+ // to disable the change bar for the class file (attached source) java
+ // editor.
+ IPreferenceStore store = getPreferenceStore();
+ return store
+ .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class required) {
+ if (SmartBackspaceManager.class.equals(required)) {
+ if (getSourceViewer() instanceof JavaSourceViewer) {
+ return ((JavaSourceViewer) getSourceViewer())
+ .getBackspaceManager();
+ }
+ }
+
+ return super.getAdapter(required);
+ }
+
+ /**
+ * Returns the mutex for the reconciler. See
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898 for a description of
+ * the problem.
+ *
+ * TODO remove once the underlying problem is solved.
+ *
+ *
+ * @return the lock reconcilers may use to synchronize on
+ */
+ public Object getReconcilerLock() {
+ return fReconcilerLock;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorSaved()
+ */
+ protected void editorSaved() {
+ super.editorSaved();
+ ShowExternalPreviewAction a = ShowExternalPreviewAction.getInstance();
+ if (a != null) {
+ //a.refresh(ShowExternalPreviewAction.PHP_TYPE);
+ a.doRun(ShowExternalPreviewAction.PHP_TYPE);
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PaintManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PaintManager.java
new file mode 100644
index 0000000..9e880b4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PaintManager.java
@@ -0,0 +1,290 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultPositionUpdater;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextEvent;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.widgets.Control;
+
+public final class PaintManager implements KeyListener, MouseListener,
+ ISelectionChangedListener, ITextListener, ITextInputListener {
+
+ static class PaintPositionUpdater extends DefaultPositionUpdater {
+
+ /**
+ * Creates the position updater.
+ */
+ protected PaintPositionUpdater(String category) {
+ super(category);
+ }
+
+ /**
+ * If an insertion happens at a position's offset, the position is
+ * extended rather than shifted. Also, if something is added right
+ * behind the end of the position, the position is extended rather than
+ * kept stable.
+ */
+ protected void adaptToInsert() {
+
+ int myStart = fPosition.offset;
+ int myEnd = fPosition.offset + fPosition.length;
+ myEnd = Math.max(myStart, myEnd);
+
+ int yoursStart = fOffset;
+ int yoursEnd = fOffset + fReplaceLength;// - 1;
+ yoursEnd = Math.max(yoursStart, yoursEnd);
+
+ if (myEnd < yoursStart)
+ return;
+
+ if (myStart <= yoursStart)
+ fPosition.length += fReplaceLength;
+ else
+ fPosition.offset += fReplaceLength;
+ }
+ };
+
+ static class PositionManager implements IPositionManager {
+
+ private IDocument fDocument;
+
+ private IPositionUpdater fPositionUpdater;
+
+ private String fCategory;
+
+ public PositionManager() {
+ fCategory = getClass().getName() + hashCode();
+ fPositionUpdater = new PaintPositionUpdater(fCategory);
+ }
+
+ public void install(IDocument document) {
+ fDocument = document;
+ fDocument.addPositionCategory(fCategory);
+ fDocument.addPositionUpdater(fPositionUpdater);
+ }
+
+ public void dispose() {
+ uninstall(fDocument);
+ }
+
+ public void uninstall(IDocument document) {
+ if (document == fDocument && document != null) {
+ try {
+ fDocument.removePositionUpdater(fPositionUpdater);
+ fDocument.removePositionCategory(fCategory);
+ } catch (BadPositionCategoryException x) {
+ // should not happen
+ }
+ fDocument = null;
+ }
+ }
+
+ /*
+ * @see IPositionManager#addManagedPosition(Position)
+ */
+ public void addManagedPosition(Position position) {
+ try {
+ fDocument.addPosition(fCategory, position);
+ } catch (BadPositionCategoryException x) {
+ // should not happen
+ } catch (BadLocationException x) {
+ // should not happen
+ }
+ }
+
+ /*
+ * @see IPositionManager#removeManagedPosition(Position)
+ */
+ public void removeManagedPosition(Position position) {
+ try {
+ fDocument.removePosition(fCategory, position);
+ } catch (BadPositionCategoryException x) {
+ // should not happen
+ }
+ }
+ };
+
+ private List fPainters = new ArrayList(2);
+
+ private PositionManager fManager;
+
+ private ISourceViewer fSourceViewer;
+
+ private boolean fTextChanged = false;
+
+ private boolean fAutoRepeat = false;
+
+ public PaintManager(ISourceViewer sourceViewer) {
+ fSourceViewer = sourceViewer;
+ }
+
+ public void addPainter(IPainter painter) {
+ if (!fPainters.contains(painter)) {
+ fPainters.add(painter);
+ if (fPainters.size() == 1)
+ install();
+ painter.setPositionManager(fManager);
+ painter.paint(IPainter.INTERNAL);
+ }
+ }
+
+ public void removePainter(IPainter painter) {
+ if (fPainters.remove(painter))
+ painter.setPositionManager(null);
+ if (fPainters.size() == 0)
+ dispose();
+ }
+
+ private void install() {
+
+ fManager = new PositionManager();
+ fManager.install(fSourceViewer.getDocument());
+
+ fSourceViewer.addTextInputListener(this);
+
+ ISelectionProvider provider = fSourceViewer.getSelectionProvider();
+ provider.addSelectionChangedListener(this);
+
+ fSourceViewer.addTextListener(this);
+
+ StyledText text = fSourceViewer.getTextWidget();
+ text.addKeyListener(this);
+ text.addMouseListener(this);
+ }
+
+ public void dispose() {
+
+ if (fManager != null) {
+ fManager.dispose();
+ fManager = null;
+ }
+
+ for (Iterator e = fPainters.iterator(); e.hasNext();)
+ ((IPainter) e.next()).dispose();
+ fPainters.clear();
+
+ fSourceViewer.removeTextInputListener(this);
+
+ ISelectionProvider provider = fSourceViewer.getSelectionProvider();
+ if (provider != null)
+ provider.removeSelectionChangedListener(this);
+
+ fSourceViewer.removeTextListener(this);
+
+ StyledText text = fSourceViewer.getTextWidget();
+ if (text != null && !text.isDisposed()) {
+ text.removeKeyListener(this);
+ text.removeMouseListener(this);
+ }
+ }
+
+ private void paint(int reason) {
+ for (Iterator e = fPainters.iterator(); e.hasNext();)
+ ((IPainter) e.next()).paint(reason);
+ }
+
+ /*
+ * @see KeyListener#keyPressed(KeyEvent)
+ */
+ public void keyPressed(KeyEvent e) {
+ paint(IPainter.KEY_STROKE);
+ }
+
+ /*
+ * @see KeyListener#keyReleased(KeyEvent)
+ */
+ public void keyReleased(KeyEvent e) {
+ }
+
+ /*
+ * @see MouseListener#mouseDoubleClick(MouseEvent)
+ */
+ public void mouseDoubleClick(MouseEvent e) {
+ }
+
+ /*
+ * @see MouseListener#mouseDown(MouseEvent)
+ */
+ public void mouseDown(MouseEvent e) {
+ paint(IPainter.MOUSE_BUTTON);
+ }
+
+ /*
+ * @see MouseListener#mouseUp(MouseEvent)
+ */
+ public void mouseUp(MouseEvent e) {
+ }
+
+ /*
+ * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ paint(IPainter.SELECTION);
+ }
+
+ /*
+ * @see ITextListener#textChanged(TextEvent)
+ */
+ public void textChanged(TextEvent event) {
+
+ if (!event.getViewerRedrawState())
+ return;
+
+ fTextChanged = true;
+ Control control = fSourceViewer.getTextWidget();
+ if (control != null) {
+ control.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (fTextChanged && fSourceViewer != null)
+ paint(IPainter.TEXT_CHANGE);
+ }
+ });
+ }
+ }
+
+ /*
+ * @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument,
+ * IDocument)
+ */
+ public void inputDocumentAboutToBeChanged(IDocument oldInput,
+ IDocument newInput) {
+ if (oldInput != null) {
+ for (Iterator e = fPainters.iterator(); e.hasNext();)
+ ((IPainter) e.next()).deactivate(false);
+ fManager.uninstall(oldInput);
+ }
+ }
+
+ /*
+ * @see ITextInputListener#inputDocumentChanged(IDocument, IDocument)
+ */
+ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+ if (newInput != null) {
+ fManager.install(newInput);
+ paint(IPainter.TEXT_CHANGE);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PartiallySynchronizedDocument.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PartiallySynchronizedDocument.java
new file mode 100644
index 0000000..7dfb207
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PartiallySynchronizedDocument.java
@@ -0,0 +1,138 @@
+/**********************************************************************
+ Copyright (c) 2000, 2003 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.ISynchronizable;
+import org.eclipse.jface.text.Position;
+
+/**
+ * Document that can also be used by a background reconciler.
+ */
+public class PartiallySynchronizedDocument extends Document implements
+ ISynchronizable {
+
+ private final Object fInternalLockObject = new Object();
+
+ private Object fLockObject;
+
+ /*
+ * @see org.eclipse.jface.text.ISynchronizable#setLockObject(java.lang.Object)
+ */
+ public void setLockObject(Object lockObject) {
+ fLockObject = lockObject;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ISynchronizable#getLockObject()
+ */
+ public Object getLockObject() {
+ return fLockObject == null ? fInternalLockObject : fLockObject;
+ }
+
+ /*
+ * @see IDocumentExtension#startSequentialRewrite(boolean)
+ */
+ public void startSequentialRewrite(boolean normalized) {
+ synchronized (getLockObject()) {
+ super.startSequentialRewrite(normalized);
+ }
+ }
+
+ /*
+ * @see IDocumentExtension#stopSequentialRewrite()
+ */
+ public void stopSequentialRewrite() {
+ synchronized (getLockObject()) {
+ super.stopSequentialRewrite();
+ }
+ }
+
+ /*
+ * @see IDocument#get()
+ */
+ public String get() {
+ synchronized (getLockObject()) {
+ return super.get();
+ }
+ }
+
+ /*
+ * @see IDocument#get(int, int)
+ */
+ public String get(int offset, int length) throws BadLocationException {
+ synchronized (getLockObject()) {
+ return super.get(offset, length);
+ }
+ }
+
+ /*
+ * @see IDocument#getChar(int)
+ */
+ public char getChar(int offset) throws BadLocationException {
+ synchronized (getLockObject()) {
+ return super.getChar(offset);
+ }
+ }
+
+ /*
+ * @see IDocument#replace(int, int, String)
+ */
+ public void replace(int offset, int length, String text)
+ throws BadLocationException {
+ synchronized (getLockObject()) {
+ super.replace(offset, length, text);
+ }
+ }
+
+ /*
+ * @see IDocument#set(String)
+ */
+ public void set(String text) {
+ synchronized (getLockObject()) {
+ super.set(text);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractDocument#addPosition(java.lang.String,
+ * org.eclipse.jface.text.Position)
+ */
+ public void addPosition(String category, Position position)
+ throws BadLocationException, BadPositionCategoryException {
+ synchronized (getLockObject()) {
+ super.addPosition(category, position);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractDocument#removePosition(java.lang.String,
+ * org.eclipse.jface.text.Position)
+ */
+ public void removePosition(String category, Position position)
+ throws BadPositionCategoryException {
+ synchronized (getLockObject()) {
+ super.removePosition(category, position);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractDocument#getPositions(java.lang.String)
+ */
+ public Position[] getPositions(String category)
+ throws BadPositionCategoryException {
+ synchronized (getLockObject()) {
+ return super.getPositions(category);
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PresentationAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PresentationAction.java
new file mode 100644
index 0000000..a2ad6dd
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PresentationAction.java
@@ -0,0 +1,54 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * A toolbar action which toggles the presentation model of the connected text
+ * editor. The editor shows either the highlight range only or always the whole
+ * document.
+ */
+public class PresentationAction extends TextEditorAction {
+
+ /**
+ * Constructs and updates the action.
+ */
+ public PresentationAction() {
+ super(PHPEditorMessages.getResourceBundle(),
+ "TogglePresentation.", null); //$NON-NLS-1$
+ update();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IAction
+ */
+ public void run() {
+
+ ITextEditor editor = getTextEditor();
+
+ editor.resetHighlightRange();
+ boolean show = editor.showsHighlightRangeOnly();
+ setChecked(!show);
+ editor.showHighlightRangeOnly(!show);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on TextEditorAction
+ */
+ public void update() {
+ setChecked(getTextEditor() != null
+ && getTextEditor().showsHighlightRangeOnly());
+ setEnabled(true);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PrintMarginPainter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PrintMarginPainter.java
new file mode 100644
index 0000000..c941e15
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/PrintMarginPainter.java
@@ -0,0 +1,126 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+
+public class PrintMarginPainter implements IPainter, PaintListener {
+
+ private StyledText fTextWidget;
+
+ private int fMarginWidth = 80;
+
+ private Color fColor;
+
+ private int fLineStyle = SWT.LINE_SOLID;
+
+ private int fLineWidth = 1;
+
+ private int fCachedWidgetX = -1;
+
+ private boolean fIsActive = false;
+
+ public PrintMarginPainter(ISourceViewer sourceViewer) {
+ fTextWidget = sourceViewer.getTextWidget();
+ }
+
+ public void setMarginRulerColumn(int width) {
+ fMarginWidth = width;
+ intialize();
+ }
+
+ public void setMarginRulerStyle(int lineStyle) {
+ fLineStyle = lineStyle;
+ }
+
+ public void setMarginRulerWidth(int lineWidth) {
+ fLineWidth = lineWidth;
+ }
+
+ /**
+ * Must be called before paint
is called the first time.
+ */
+ public void setMarginRulerColor(Color color) {
+ fColor = color;
+ }
+
+ /**
+ * Must be called explicitly when font of text widget changes.
+ */
+ public void intialize() {
+ computeWidgetX();
+ fTextWidget.redraw();
+ }
+
+ private void computeWidgetX() {
+ GC gc = new GC(fTextWidget);
+ int pixels = gc.getFontMetrics().getAverageCharWidth();
+ gc.dispose();
+
+ fCachedWidgetX = pixels * fMarginWidth;
+ }
+
+ /*
+ * @see IPainter#deactivate(boolean)
+ */
+ public void deactivate(boolean redraw) {
+ if (fIsActive) {
+ fIsActive = false;
+ fTextWidget.removePaintListener(this);
+ if (redraw)
+ fTextWidget.redraw();
+ }
+ }
+
+ /*
+ * @see IPainter#dispose()
+ */
+ public void dispose() {
+ fTextWidget = null;
+ }
+
+ /*
+ * @see IPainter#paint(int)
+ */
+ public void paint(int reason) {
+ if (!fIsActive) {
+ fIsActive = true;
+ fTextWidget.addPaintListener(this);
+ if (fCachedWidgetX == -1)
+ computeWidgetX();
+ fTextWidget.redraw();
+ }
+ }
+
+ /*
+ * @see IPainter#setPositionManager(IPositionManager)
+ */
+ public void setPositionManager(IPositionManager manager) {
+ }
+
+ /*
+ * @see PaintListener#paintControl(PaintEvent)
+ */
+ public void paintControl(PaintEvent e) {
+ if (fTextWidget != null) {
+ int x = fCachedWidgetX - fTextWidget.getHorizontalPixel();
+ if (x >= 0) {
+ Rectangle area = fTextWidget.getClientArea();
+ e.gc.setForeground(fColor);
+ e.gc.setLineStyle(fLineStyle);
+ e.gc.setLineWidth(fLineWidth);
+ e.gc.drawLine(x, 0, x, area.height);
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ProblemAnnotationIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ProblemAnnotationIterator.java
new file mode 100644
index 0000000..7895116
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ProblemAnnotationIterator.java
@@ -0,0 +1,73 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.util.Iterator;
+
+import org.eclipse.jface.text.source.IAnnotationModel;
+
+/**
+ * Filters problems based on their types.
+ */
+public class ProblemAnnotationIterator implements Iterator {
+
+ private Iterator fIterator;
+
+ private IProblemAnnotation fNext;
+
+ private boolean fSkipIrrelevants;
+
+ public ProblemAnnotationIterator(IAnnotationModel model,
+ boolean skipIrrelevants) {
+ fIterator = model.getAnnotationIterator();
+ fSkipIrrelevants = skipIrrelevants;
+ skip();
+ }
+
+ private void skip() {
+ while (fIterator.hasNext()) {
+ Object next = fIterator.next();
+ if (next instanceof IProblemAnnotation) {
+ IProblemAnnotation a = (IProblemAnnotation) next;
+ if (fSkipIrrelevants) {
+ if (a.isRelevant()) {
+ fNext = a;
+ return;
+ }
+ } else {
+ fNext = a;
+ return;
+ }
+ }
+ }
+ fNext = null;
+ }
+
+ /*
+ * @see Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return fNext != null;
+ }
+
+ /*
+ * @see Iterator#next()
+ */
+ public Object next() {
+ try {
+ return fNext;
+ } finally {
+ skip();
+ }
+ }
+
+ /*
+ * @see Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ProblemPainter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ProblemPainter.java
new file mode 100644
index 0000000..f125eea
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ProblemPainter.java
@@ -0,0 +1,406 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelListener;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Highlights the temporary problems.
+ */
+public class ProblemPainter implements IPainter, PaintListener,
+ IAnnotationModelListener {
+
+ private static class ProblemPosition {
+ Position fPosition;
+
+ Color fColor;
+
+ boolean fMultiLine;
+ };
+
+ private boolean fIsActive = false;
+
+ private boolean fIsPainting = false;
+
+ private boolean fIsSettingModel = false;
+
+ private ITextEditor fTextEditor;
+
+ private ISourceViewer fSourceViewer;
+
+ private StyledText fTextWidget;
+
+ private IAnnotationModel fModel;
+
+ private List fProblemPositions = new ArrayList();
+
+ private Map fColorTable = new HashMap();
+
+ private Set fAnnotationSet = new HashSet();
+
+ public ProblemPainter(ITextEditor textEditor, ISourceViewer sourceViewer) {
+ fTextEditor = textEditor;
+ fSourceViewer = sourceViewer;
+ fTextWidget = sourceViewer.getTextWidget();
+ }
+
+ private boolean hasProblems() {
+ return !fProblemPositions.isEmpty();
+ }
+
+ private void enablePainting() {
+ if (!fIsPainting && hasProblems()) {
+ fIsPainting = true;
+ fTextWidget.addPaintListener(this);
+ handleDrawRequest(null);
+ }
+ }
+
+ private void disablePainting(boolean redraw) {
+ if (fIsPainting) {
+ fIsPainting = false;
+ fTextWidget.removePaintListener(this);
+ if (redraw && hasProblems())
+ handleDrawRequest(null);
+ }
+ }
+
+ private void setModel(IAnnotationModel model) {
+ if (fModel != model) {
+ if (fModel != null)
+ fModel.removeAnnotationModelListener(this);
+ fModel = model;
+ if (fModel != null) {
+ try {
+ fIsSettingModel = true;
+ fModel.addAnnotationModelListener(this);
+ } finally {
+ fIsSettingModel = false;
+ }
+ }
+ }
+ }
+
+ private void catchupWithModel() {
+ if (fProblemPositions != null) {
+ fProblemPositions.clear();
+ if (fModel != null) {
+
+ Iterator e = new ProblemAnnotationIterator(fModel, true);
+ while (e.hasNext()) {
+ IProblemAnnotation pa = (IProblemAnnotation) e.next();
+ Annotation a = (Annotation) pa;
+
+ Color color = null;
+ AnnotationType type = pa.getAnnotationType();
+ if (fAnnotationSet.contains(type))
+ color = (Color) fColorTable.get(type);
+
+ if (color != null) {
+ ProblemPosition pp = new ProblemPosition();
+ pp.fPosition = fModel.getPosition(a);
+ pp.fColor = color;
+ pp.fMultiLine = true;
+ fProblemPositions.add(pp);
+ }
+ }
+ }
+ }
+ }
+
+ private void updatePainting() {
+ disablePainting(true);
+ catchupWithModel();
+ enablePainting();
+ }
+
+ /*
+ * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
+ */
+ public void modelChanged(final IAnnotationModel model) {
+ if (fTextWidget != null && !fTextWidget.isDisposed()) {
+ if (fIsSettingModel) {
+ // inside the ui thread -> no need for posting
+ updatePainting();
+ } else {
+ Display d = fTextWidget.getDisplay();
+ if (d != null) {
+ d.asyncExec(new Runnable() {
+ public void run() {
+ if (fTextWidget != null
+ && !fTextWidget.isDisposed())
+ updatePainting();
+ }
+ });
+ }
+ }
+ }
+ }
+
+ public void setColor(AnnotationType annotationType, Color color) {
+ if (color != null)
+ fColorTable.put(annotationType, color);
+ else
+ fColorTable.remove(annotationType);
+ }
+
+ public void paintAnnotations(AnnotationType annotationType, boolean paint) {
+ if (paint)
+ fAnnotationSet.add(annotationType);
+ else
+ fAnnotationSet.remove(annotationType);
+ }
+
+ public boolean isPaintingAnnotations() {
+ return !fAnnotationSet.isEmpty();
+ }
+
+ /*
+ * @see IPainter#dispose()
+ */
+ public void dispose() {
+
+ if (fColorTable != null)
+ fColorTable.clear();
+ fColorTable = null;
+
+ if (fAnnotationSet != null)
+ fAnnotationSet.clear();
+ fAnnotationSet = null;
+
+ fTextWidget = null;
+ fModel = null;
+ fProblemPositions = null;
+ }
+
+ /*
+ * Returns the document offset of the upper left corner of the widgets
+ * viewport, possibly including partially visible lines.
+ */
+ private int getInclusiveTopIndexStartOffset() {
+
+ if (fTextWidget != null && !fTextWidget.isDisposed()) {
+ int top = fSourceViewer.getTopIndex();
+ if ((fTextWidget.getTopPixel() % fTextWidget.getLineHeight()) != 0)
+ top--;
+ try {
+ IDocument document = fSourceViewer.getDocument();
+ return document.getLineOffset(top);
+ } catch (BadLocationException ex) {
+ }
+ }
+
+ return -1;
+ }
+
+ /*
+ * @see PaintListener#paintControl(PaintEvent)
+ */
+ public void paintControl(PaintEvent event) {
+ if (fTextWidget != null)
+ handleDrawRequest(event.gc);
+ }
+
+ private void handleDrawRequest(GC gc) {
+
+ int vOffset = getInclusiveTopIndexStartOffset();
+ // http://bugs.eclipse.org/bugs/show_bug.cgi?id=17147
+ int vLength = fSourceViewer.getBottomIndexEndOffset() + 1;
+
+ for (Iterator e = fProblemPositions.iterator(); e.hasNext();) {
+ ProblemPosition pp = (ProblemPosition) e.next();
+ Position p = pp.fPosition;
+ if (p.overlapsWith(vOffset, vLength)) {
+
+ if (!pp.fMultiLine) {
+
+ IRegion widgetRange = getWidgetRange(p);
+ if (widgetRange != null)
+ draw(gc, widgetRange.getOffset(), widgetRange
+ .getLength(), pp.fColor);
+
+ } else {
+
+ IDocument document = fSourceViewer.getDocument();
+ try {
+
+ int startLine = document.getLineOfOffset(p.getOffset());
+ int lastInclusive = Math.max(p.getOffset(), p
+ .getOffset()
+ + p.getLength() - 1);
+ int endLine = document.getLineOfOffset(lastInclusive);
+
+ for (int i = startLine; i <= endLine; i++) {
+ IRegion line = document.getLineInformation(i);
+ int paintStart = Math.max(line.getOffset(), p
+ .getOffset());
+ int paintEnd = Math.min(line.getOffset()
+ + line.getLength(), p.getOffset()
+ + p.getLength());
+ if (paintEnd > paintStart) {
+ // otherwise inside a line delimiter
+ IRegion widgetRange = getWidgetRange(new Position(
+ paintStart, paintEnd - paintStart));
+ if (widgetRange != null)
+ draw(gc, widgetRange.getOffset(),
+ widgetRange.getLength(), pp.fColor);
+ }
+ }
+
+ } catch (BadLocationException x) {
+ }
+ }
+ }
+ }
+ }
+
+ private IRegion getWidgetRange(Position p) {
+ if (fSourceViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension = (ITextViewerExtension5) fSourceViewer;
+ return extension.modelRange2WidgetRange(new Region(p.getOffset(), p
+ .getLength()));
+
+ } else {
+
+ IRegion region = fSourceViewer.getVisibleRegion();
+ int offset = region.getOffset();
+ int length = region.getLength();
+
+ if (p.overlapsWith(offset, length)) {
+ int p1 = Math.max(offset, p.getOffset());
+ int p2 = Math.min(offset + length, p.getOffset()
+ + p.getLength());
+ return new Region(p1 - offset, p2 - p1);
+ }
+ }
+
+ return null;
+ }
+
+ private int[] computePolyline(Point left, Point right, int height) {
+
+ final int WIDTH = 4; // must be even
+ final int HEIGHT = 2; // can be any number
+ // final int MINPEEKS= 2; // minimal number of peeks
+
+ int peeks = (right.x - left.x) / WIDTH;
+ // if (peeks < MINPEEKS) {
+ // int missing= (MINPEEKS - peeks) * WIDTH;
+ // left.x= Math.max(0, left.x - missing/2);
+ // peeks= MINPEEKS;
+ // }
+
+ int leftX = left.x;
+
+ // compute (number of point) * 2
+ int length = ((2 * peeks) + 1) * 2;
+ if (length < 0)
+ return new int[0];
+
+ int[] coordinates = new int[length];
+
+ // cache peeks' y-coordinates
+ int bottom = left.y + height - 1;
+ int top = bottom - HEIGHT;
+
+ // populate array with peek coordinates
+ for (int i = 0; i < peeks; i++) {
+ int index = 4 * i;
+ coordinates[index] = leftX + (WIDTH * i);
+ coordinates[index + 1] = bottom;
+ coordinates[index + 2] = coordinates[index] + WIDTH / 2;
+ coordinates[index + 3] = top;
+ }
+
+ // the last down flank is missing
+ coordinates[length - 2] = left.x + (WIDTH * peeks);
+ coordinates[length - 1] = bottom;
+
+ return coordinates;
+ }
+
+ private void draw(GC gc, int offset, int length, Color color) {
+ if (gc != null) {
+
+ Point left = fTextWidget.getLocationAtOffset(offset);
+ Point right = fTextWidget.getLocationAtOffset(offset + length);
+
+ gc.setForeground(color);
+ int[] polyline = computePolyline(left, right, gc.getFontMetrics()
+ .getHeight());
+ gc.drawPolyline(polyline);
+
+ } else {
+ fTextWidget.redrawRange(offset, length, true);
+ }
+ }
+
+ /*
+ * @see IPainter#deactivate(boolean)
+ */
+ public void deactivate(boolean redraw) {
+ if (fIsActive) {
+ fIsActive = false;
+ disablePainting(redraw);
+ setModel(null);
+ catchupWithModel();
+ }
+ }
+
+ /*
+ * @see IPainter#paint(int)
+ */
+ public void paint(int reason) {
+ if (!fIsActive) {
+ fIsActive = true;
+ IDocumentProvider provider = WebUI.getDefault()
+ .getCompilationUnitDocumentProvider();
+ setModel(provider.getAnnotationModel(fTextEditor.getEditorInput()));
+ } else if (CONFIGURATION == reason || INTERNAL == reason)
+ updatePainting();
+ }
+
+ /*
+ * @see IPainter#setPositionManager(IPositionManager)
+ */
+ public void setPositionManager(IPositionManager manager) {
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/SmartyDocumentSetupParticipant.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/SmartyDocumentSetupParticipant.java
new file mode 100644
index 0000000..4847d20
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/SmartyDocumentSetupParticipant.java
@@ -0,0 +1,39 @@
+/**********************************************************************
+ Copyright (c) 2000, 2003 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * The document setup participant for PHPDT.
+ */
+public class SmartyDocumentSetupParticipant implements
+ IDocumentSetupParticipant {
+
+ public SmartyDocumentSetupParticipant() {
+ }
+
+ /*
+ * @see org.eclipse.core.filebuffers.IDocumentSetupParticipant#setup(org.eclipse.jface.text.IDocument)
+ */
+ public void setup(IDocument document) {
+ JavaTextTools tools = WebUI.getDefault().getJavaTextTools();
+ tools.setupSmartyDocumentPartitioner(document,
+ IPHPPartitions.PHP_PARTITIONING, null); // IPHPPartitions.PHP_PARTITIONING,
+ // null);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ToggleCommentAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ToggleCommentAction.java
new file mode 100644
index 0000000..ada76ed
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/ToggleCommentAction.java
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ResourceAction;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * An action which toggles comment prefixes on the selected lines.
+ *
+ * @since 3.0
+ */
+public final class ToggleCommentAction extends TextEditorAction {
+
+ /** The text operation target */
+ private ITextOperationTarget fOperationTarget;
+
+ /** The document partitioning */
+ private String fDocumentPartitioning;
+
+ /** The comment prefixes */
+ private Map fPrefixesMap;
+
+ /**
+ * Creates and initializes the action for the given text editor. The action
+ * configures its visual representation from the given resource bundle.
+ *
+ * @param bundle
+ * the resource bundle
+ * @param prefix
+ * a prefix to be prepended to the various resource keys
+ * (described in ResourceAction
constructor), or
+ * null
if none
+ * @param editor
+ * the text editor
+ * @see ResourceAction#ResourceAction(ResourceBundle, String, int)
+ */
+ public ToggleCommentAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ /**
+ * Implementation of the IAction
prototype. Checks if the
+ * selected lines are all commented or not and uncomments/comments them
+ * respectively.
+ */
+ public void run() {
+ if (fOperationTarget == null || fDocumentPartitioning == null
+ || fPrefixesMap == null)
+ return;
+
+ ITextEditor editor = getTextEditor();
+ if (editor == null)
+ return;
+
+ if (!validateEditorInputState())
+ return;
+
+ final int operationCode;
+ if (isSelectionCommented(editor.getSelectionProvider().getSelection()))
+ operationCode = ITextOperationTarget.STRIP_PREFIX;
+ else
+ operationCode = ITextOperationTarget.PREFIX;
+
+ Shell shell = editor.getSite().getShell();
+ if (!fOperationTarget.canDoOperation(operationCode)) {
+ if (shell != null)
+ MessageDialog
+ .openError(
+ shell,
+ PHPEditorMessages
+ .getString("ToggleComment.error.title"), PHPEditorMessages.getString("ToggleComment.error.message")); //$NON-NLS-1$ //$NON-NLS-2$
+ return;
+ }
+
+ Display display = null;
+ if (shell != null && !shell.isDisposed())
+ display = shell.getDisplay();
+
+ BusyIndicator.showWhile(display, new Runnable() {
+ public void run() {
+ fOperationTarget.doOperation(operationCode);
+ }
+ });
+ }
+
+ /**
+ * Is the given selection single-line commented?
+ *
+ * @param selection
+ * Selection to check
+ * @return true
iff all selected lines are commented
+ */
+ private boolean isSelectionCommented(ISelection selection) {
+ if (!(selection instanceof ITextSelection))
+ return false;
+
+ ITextSelection textSelection = (ITextSelection) selection;
+ if (textSelection.getStartLine() < 0 || textSelection.getEndLine() < 0)
+ return false;
+
+ IDocument document = getTextEditor().getDocumentProvider().getDocument(
+ getTextEditor().getEditorInput());
+
+ try {
+
+ IRegion block = getTextBlockFromSelection(textSelection, document);
+ ITypedRegion[] regions = TextUtilities.computePartitioning(
+ document, fDocumentPartitioning, block.getOffset(), block
+ .getLength(), false);
+
+ int lineCount = 0;
+ int[] lines = new int[regions.length * 2]; // [startline, endline,
+ // startline, endline,
+ // ...]
+ for (int i = 0, j = 0; i < regions.length; i++, j += 2) {
+ // start line of region
+ lines[j] = getFirstCompleteLineOfRegion(regions[i], document);
+ // end line of region
+ int length = regions[i].getLength();
+ int offset = regions[i].getOffset() + length;
+ if (length > 0)
+ offset--;
+ lines[j + 1] = (lines[j] == -1 ? -1 : document
+ .getLineOfOffset(offset));
+ lineCount += lines[j + 1] - lines[j] + 1;
+ }
+
+ // Perform the check
+ for (int i = 0, j = 0; i < regions.length; i++, j += 2) {
+ String[] prefixes = (String[]) fPrefixesMap.get(regions[i]
+ .getType());
+ if (prefixes != null && prefixes.length > 0 && lines[j] >= 0
+ && lines[j + 1] >= 0)
+ if (!isBlockCommented(lines[j], lines[j + 1], prefixes,
+ document))
+ return false;
+ }
+
+ return true;
+
+ } catch (BadLocationException x) {
+ // should not happen
+ PHPeclipsePlugin.log(x);
+ }
+
+ return false;
+ }
+
+ /**
+ * Creates a region describing the text block (something that starts at the
+ * beginning of a line) completely containing the current selection.
+ *
+ * @param selection
+ * The selection to use
+ * @param document
+ * The document
+ * @return the region describing the text block comprising the given
+ * selection
+ */
+ private IRegion getTextBlockFromSelection(ITextSelection selection,
+ IDocument document) {
+
+ try {
+ IRegion line = document.getLineInformationOfOffset(selection
+ .getOffset());
+ int length = selection.getLength() == 0 ? line.getLength()
+ : selection.getLength()
+ + (selection.getOffset() - line.getOffset());
+ return new Region(line.getOffset(), length);
+
+ } catch (BadLocationException x) {
+ // should not happen
+ PHPeclipsePlugin.log(x);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the index of the first line whose start offset is in the given
+ * text range.
+ *
+ * @param region
+ * the text range in characters where to find the line
+ * @param document
+ * The document
+ * @return the first line whose start index is in the given range, -1 if
+ * there is no such line
+ */
+ private int getFirstCompleteLineOfRegion(IRegion region, IDocument document) {
+
+ try {
+
+ int startLine = document.getLineOfOffset(region.getOffset());
+
+ int offset = document.getLineOffset(startLine);
+ if (offset >= region.getOffset())
+ return startLine;
+
+ offset = document.getLineOffset(startLine + 1);
+ return (offset > region.getOffset() + region.getLength() ? -1
+ : startLine + 1);
+
+ } catch (BadLocationException x) {
+ // should not happen
+ PHPeclipsePlugin.log(x);
+ }
+
+ return -1;
+ }
+
+ /**
+ * Determines whether each line is prefixed by one of the prefixes.
+ *
+ * @param startLine
+ * Start line in document
+ * @param endLine
+ * End line in document
+ * @param prefixes
+ * Possible comment prefixes
+ * @param document
+ * The document
+ * @return true
iff each line from startLine
+ * to and including endLine
is prepended by one of
+ * the prefixes
, ignoring whitespace at the begin of
+ * line
+ */
+ private boolean isBlockCommented(int startLine, int endLine,
+ String[] prefixes, IDocument document) {
+
+ try {
+
+ // check for occurrences of prefixes in the given lines
+ for (int i = startLine; i <= endLine; i++) {
+
+ IRegion line = document.getLineInformation(i);
+ String text = document.get(line.getOffset(), line.getLength());
+
+ int[] found = TextUtilities.indexOf(prefixes, text, 0);
+
+ if (found[0] == -1)
+ // found a line which is not commented
+ return false;
+
+ String s = document.get(line.getOffset(), found[0]);
+ s = s.trim();
+ if (s.length() != 0)
+ // found a line which is not commented
+ return false;
+
+ }
+
+ return true;
+
+ } catch (BadLocationException x) {
+ // should not happen
+ PHPeclipsePlugin.log(x);
+ }
+
+ return false;
+ }
+
+ /**
+ * Implementation of the IUpdate
prototype method discovers
+ * the operation through the current editor's
+ * ITextOperationTarget
adapter, and sets the enabled state
+ * accordingly.
+ */
+ public void update() {
+ super.update();
+
+ if (!canModifyEditor()) {
+ setEnabled(false);
+ return;
+ }
+
+ ITextEditor editor = getTextEditor();
+ if (fOperationTarget == null && editor != null)
+ fOperationTarget = (ITextOperationTarget) editor
+ .getAdapter(ITextOperationTarget.class);
+
+ boolean isEnabled = (fOperationTarget != null
+ && fOperationTarget.canDoOperation(ITextOperationTarget.PREFIX) && fOperationTarget
+ .canDoOperation(ITextOperationTarget.STRIP_PREFIX));
+ setEnabled(isEnabled);
+ }
+
+ /*
+ * @see TextEditorAction#setEditor(ITextEditor)
+ */
+ public void setEditor(ITextEditor editor) {
+ super.setEditor(editor);
+ fOperationTarget = null;
+ }
+
+ public void configure(ISourceViewer sourceViewer,
+ SourceViewerConfiguration configuration) {
+ fPrefixesMap = null;
+
+ String[] types = configuration.getConfiguredContentTypes(sourceViewer);
+ Map prefixesMap = new HashMap(types.length);
+ for (int i = 0; i < types.length; i++) {
+ String type = types[i];
+ String[] prefixes = configuration.getDefaultPrefixes(sourceViewer,
+ type);
+ if (prefixes != null && prefixes.length > 0) {
+ int emptyPrefixes = 0;
+ for (int j = 0; j < prefixes.length; j++)
+ if (prefixes[j].length() == 0)
+ emptyPrefixes++;
+
+ if (emptyPrefixes > 0) {
+ String[] nonemptyPrefixes = new String[prefixes.length
+ - emptyPrefixes];
+ for (int j = 0, k = 0; j < prefixes.length; j++) {
+ String prefix = prefixes[j];
+ if (prefix.length() != 0) {
+ nonemptyPrefixes[k] = prefix;
+ k++;
+ }
+ }
+ prefixes = nonemptyPrefixes;
+ }
+
+ prefixesMap.put(type, prefixes);
+ }
+ }
+ fDocumentPartitioning = configuration
+ .getConfiguredDocumentPartitioning(sourceViewer);
+ fPrefixesMap = prefixesMap;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/TogglePresentationAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/TogglePresentationAction.java
new file mode 100644
index 0000000..b46e1c4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/TogglePresentationAction.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * A toolbar action which toggles the presentation model of the connected text
+ * editor. The editor shows either the highlight range only or always the whole
+ * document.
+ */
+public class TogglePresentationAction extends TextEditorAction implements
+ IPropertyChangeListener {
+
+ private IPreferenceStore fStore;
+
+ /**
+ * Constructs and updates the action.
+ */
+ public TogglePresentationAction() {
+ super(PHPEditorMessages.getResourceBundle(),
+ "TogglePresentation.", null); //$NON-NLS-1$
+ PHPUiImages.setToolImageDescriptors(this, "segment_edit.gif"); //$NON-NLS-1$
+ setToolTipText(PHPEditorMessages
+ .getString("TogglePresentation.tooltip")); //$NON-NLS-1$
+ setActionDefinitionId(PHPEditorActionDefinitionIds.TOGGLE_PRESENTATION);
+ // WorkbenchHelp.setHelp(this,
+ // IJavaHelpContextIds.TOGGLE_PRESENTATION_ACTION);
+ update();
+ }
+
+ /*
+ * @see IAction#actionPerformed
+ */
+ public void run() {
+
+ ITextEditor editor = getTextEditor();
+ if (editor == null)
+ return;
+
+ IRegion remembered = editor.getHighlightRange();
+ editor.resetHighlightRange();
+
+ boolean showAll = !editor.showsHighlightRangeOnly();
+ setChecked(showAll);
+
+ editor.showHighlightRangeOnly(showAll);
+ if (remembered != null)
+ editor.setHighlightRange(remembered.getOffset(), remembered
+ .getLength(), true);
+
+ fStore.removePropertyChangeListener(this);
+ fStore.setValue(PreferenceConstants.EDITOR_SHOW_SEGMENTS, showAll);
+ fStore.addPropertyChangeListener(this);
+ }
+
+ /*
+ * @see TextEditorAction#update
+ */
+ public void update() {
+ ITextEditor editor = getTextEditor();
+ boolean checked = (editor != null && editor.showsHighlightRangeOnly());
+ setChecked(checked);
+ setEnabled(editor != null);
+ }
+
+ /*
+ * @see TextEditorAction#setEditor(ITextEditor)
+ */
+ public void setEditor(ITextEditor editor) {
+
+ super.setEditor(editor);
+
+ if (editor != null) {
+
+ if (fStore == null) {
+ fStore = WebUI.getDefault().getPreferenceStore();
+ fStore.addPropertyChangeListener(this);
+ }
+ synchronizeWithPreference(editor);
+
+ } else if (fStore != null) {
+ fStore.removePropertyChangeListener(this);
+ fStore = null;
+ }
+
+ update();
+ }
+
+ /**
+ * Synchronizes the appearance of the editor with what the preference store
+ * tells him.
+ */
+ private void synchronizeWithPreference(ITextEditor editor) {
+
+ if (editor == null)
+ return;
+
+ boolean showSegments = fStore
+ .getBoolean(PreferenceConstants.EDITOR_SHOW_SEGMENTS);
+ setChecked(showSegments);
+
+ if (editor.showsHighlightRangeOnly() != showSegments) {
+ IRegion remembered = editor.getHighlightRange();
+ editor.resetHighlightRange();
+ editor.showHighlightRangeOnly(showSegments);
+ if (remembered != null)
+ editor.setHighlightRange(remembered.getOffset(), remembered
+ .getLength(), true);
+ }
+ }
+
+ /*
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (event.getProperty()
+ .equals(PreferenceConstants.EDITOR_SHOW_SEGMENTS))
+ synchronizeWithPreference(getTextEditor());
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/WorkingCopyManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/WorkingCopyManager.java
new file mode 100644
index 0000000..1f96fb2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/WorkingCopyManager.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpdt.ui.IWorkingCopyManagerExtension;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.ui.IEditorInput;
+
+/**
+ * This working copy manager works together with a given compilation unit
+ * document provider and additionally offers to "overwrite" the working copy
+ * provided by this document provider.
+ */
+public class WorkingCopyManager implements IWorkingCopyManager,
+ IWorkingCopyManagerExtension {
+
+ private ICompilationUnitDocumentProvider fDocumentProvider;
+
+ private Map fMap;
+
+ private boolean fIsShuttingDown;
+
+ /**
+ * Creates a new working copy manager that co-operates with the given
+ * compilation unit document provider.
+ *
+ * @param provider
+ * the provider
+ */
+ public WorkingCopyManager(ICompilationUnitDocumentProvider provider) {
+ Assert.isNotNull(provider);
+ fDocumentProvider = provider;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.IWorkingCopyManager#connect(org.eclipse.ui.IEditorInput)
+ */
+ public void connect(IEditorInput input) throws CoreException {
+ fDocumentProvider.connect(input);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.IWorkingCopyManager#disconnect(org.eclipse.ui.IEditorInput)
+ */
+ public void disconnect(IEditorInput input) {
+ fDocumentProvider.disconnect(input);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.IWorkingCopyManager#shutdown()
+ */
+ public void shutdown() {
+ if (!fIsShuttingDown) {
+ fIsShuttingDown = true;
+ try {
+ if (fMap != null) {
+ fMap.clear();
+ fMap = null;
+ }
+ fDocumentProvider.shutdown();
+ } finally {
+ fIsShuttingDown = false;
+ }
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.ui.IWorkingCopyManager#getWorkingCopy(org.eclipse.ui.IEditorInput)
+ */
+ public ICompilationUnit getWorkingCopy(IEditorInput input) {
+ ICompilationUnit unit = fMap == null ? null : (ICompilationUnit) fMap
+ .get(input);
+ return unit != null ? unit : fDocumentProvider.getWorkingCopy(input);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.IWorkingCopyManagerExtension#setWorkingCopy(org.eclipse.ui.IEditorInput,
+ * net.sourceforge.phpdt.core.ICompilationUnit)
+ */
+ public void setWorkingCopy(IEditorInput input, ICompilationUnit workingCopy) {
+ if (fDocumentProvider.getDocument(input) != null) {
+ if (fMap == null)
+ fMap = new HashMap();
+ fMap.put(input, workingCopy);
+ }
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.javaeditor.IWorkingCopyManagerExtension#removeWorkingCopy(org.eclipse.ui.IEditorInput)
+ */
+ public void removeWorkingCopy(IEditorInput input) {
+ fMap.remove(input);
+ if (fMap.isEmpty())
+ fMap = null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/actions/RTrimAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/actions/RTrimAction.java
new file mode 100644
index 0000000..a014e9e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/actions/RTrimAction.java
@@ -0,0 +1,153 @@
+/*
+ * Created on Oct 15, 2004
+ *
+ * The MIT License
+ * Copyright (c) 2004 Stephen Milligan
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software
+ * is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package net.sourceforge.phpeclipse.phpeditor.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * @author Stephen Milligan
+ */
+public class RTrimAction implements IEditorActionDelegate {
+
+ ITextEditor editor = null;
+
+ /**
+ *
+ */
+ public RTrimAction() {
+ super();
+ }
+
+ public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+
+ if (targetEditor instanceof ITextEditor) {
+ editor = (ITextEditor) targetEditor;
+ }
+ }
+
+ /**
+ * this gets called for every action
+ */
+ public void run(IAction action) {
+ IDocument doc = editor.getDocumentProvider().getDocument(
+ editor.getEditorInput());
+ ITextSelection sel = (ITextSelection) editor.getSelectionProvider()
+ .getSelection();
+
+ int currentLine = 0;
+ int originalCursorOffset = sel.getOffset();
+ int cursorOffset = originalCursorOffset;
+ int originalSelectionLength = sel.getLength();
+ int selectionLength = originalSelectionLength;
+ String oldText;
+ int lineEnd;
+
+ try {
+
+ while (currentLine < doc.getNumberOfLines()) {
+ int offset = doc.getLineOffset(currentLine);
+ int length = doc.getLineLength(currentLine);
+ oldText = doc.get(offset, length);
+ String lineDelimiter = doc.getLineDelimiter(currentLine);
+ if (lineDelimiter == null) lineDelimiter = "";
+
+ // -- Starts at the end of the line, looking for the first
+ // non-first 'white space'
+ // -- it then breaks out. No point in carrying on, as we have
+ // found our true line end
+ for (lineEnd = oldText.length() - lineDelimiter.length(); lineEnd > 0; --lineEnd) {
+ if (oldText.charAt(lineEnd - 1) != '\t'
+ && oldText.charAt(lineEnd - 1) != ' ') {
+ break;
+ }
+ }
+
+ // -- Only replace the line if the lengths are different
+ if (lineEnd != oldText.length() - lineDelimiter.length()) {
+ String newText = oldText.substring(0, lineEnd) + lineDelimiter;
+ doc.replace(offset, length, newText);
+
+// if (offset + length <= cursorOffset) {
+// if (oldText.length() != newText.length()) {
+// cursorOffset -= oldText.length() - newText.length();
+// }
+// } else if (offset <= cursorOffset + selectionLength
+// && selectionLength > 0) {
+// selectionLength -= oldText.length() - newText.length();
+// } else if (offset + length == cursorOffset + 2) {
+// // Check if the cursor is at the end of the line.
+// cursorOffset -= 2;
+// }
+
+ int oldEndOffset = offset + length - lineDelimiter.length();
+ int newEndOffset = offset + lineEnd;
+
+ if (cursorOffset >= oldEndOffset) {
+ cursorOffset -= oldText.length() - newText.length();
+ } else if (cursorOffset >= newEndOffset) {
+ cursorOffset = newEndOffset;
+ }
+ if (selectionLength > 0) {
+ int selectionEndOffset = cursorOffset + selectionLength;
+ if (selectionEndOffset >= oldEndOffset) {
+ if (cursorOffset <= newEndOffset) {
+ // full overlap
+ selectionLength -= oldText.length() - newText.length();
+ } else {
+ // starts inside
+ selectionLength -= oldEndOffset - cursorOffset;
+ }
+ } else if (selectionEndOffset >= newEndOffset) {
+ if (cursorOffset <= newEndOffset) {
+ // ends inside
+ selectionLength -= selectionEndOffset - newEndOffset;
+ } else {
+ // full inside
+ selectionLength = 0;
+ }
+ }
+ }
+ }
+ currentLine++;
+ }
+
+ TextSelection selection = new TextSelection(doc, cursorOffset,
+ selectionLength);
+ editor.getSelectionProvider().setSelection(selection);
+ } catch (Exception blx) {
+ blx.printStackTrace();
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/java.gif b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/java.gif
new file mode 100644
index 0000000..83de817
Binary files /dev/null and b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/java.gif differ
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLCodeScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLCodeScanner.java
new file mode 100644
index 0000000..64501fd
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLCodeScanner.java
@@ -0,0 +1,195 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.phpeditor.util.HTMLWordDetector;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPWhitespaceDetector;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+
+/**
+ * A HTML code scanner.
+ */
+public class HTMLCodeScanner extends AbstractJavaScanner {
+
+ // private static String[] fgKeywords = {
+ // };
+ //
+ // private static String[] fgTypes = {
+ // };
+
+ // private IToken keyword;
+ private static String[] fgTokenProperties = {
+ IPreferenceConstants.PHP_MULTILINE_COMMENT,
+ IPreferenceConstants.PHP_SINGLELINE_COMMENT,
+ IPreferenceConstants.PHP_TAG, IPreferenceConstants.PHP_KEYWORD,
+ IPreferenceConstants.PHP_FUNCTIONNAME,
+ IPreferenceConstants.PHP_VARIABLE,
+ IPreferenceConstants.PHP_VARIABLE_DOLLAR,
+ IPreferenceConstants.PHP_STRING_DQ,
+ IPreferenceConstants.PHP_STRING_SQ, IPreferenceConstants.PHP_TYPE,
+ IPreferenceConstants.PHP_CONSTANT,
+ IPreferenceConstants.PHP_DEFAULT,
+ IPreferenceConstants.PHP_OPERATOR,
+ IPreferenceConstants.PHP_BRACE_OPERATOR,
+ IPreferenceConstants.PHP_KEYWORD_RETURN };
+
+ /*
+ * @see AbstractJavaScanner#getTokenProperties()
+ */
+ protected String[] getTokenProperties() {
+ return fgTokenProperties;
+ }
+
+ private class HTMLWordRule extends WordRule {
+ private StringBuffer fBuffer = new StringBuffer();
+
+ public HTMLWordRule(IWordDetector detector) {
+ super(detector, Token.UNDEFINED);
+ }
+
+ public HTMLWordRule(IWordDetector detector, IToken defaultToken) {
+ super(detector, defaultToken);
+ }
+
+ public IToken evaluate(ICharacterScanner scanner) {
+ int c = scanner.read();
+ boolean tagBegin = false;
+ if (fDetector.isWordStart((char) c)) {
+ if (c == '<') {
+ tagBegin = true;
+ }
+ if (fColumn == UNDEFINED
+ || (fColumn == scanner.getColumn() - 1)) {
+
+ fBuffer.setLength(0);
+ do {
+ fBuffer.append((char) c);
+ c = scanner.read();
+ if (c == '>') {
+ fBuffer.append((char) c);
+ c = scanner.read();
+ break;
+ }
+ if (c == '/' && (fBuffer.length() > 2)) {
+ break;
+ }
+ } while (c != ICharacterScanner.EOF
+ && fDetector.isWordPart((char) c));
+ scanner.unread();
+
+ if (tagBegin) {
+ return getToken(IPreferenceConstants.PHP_KEYWORD);
+ }
+ IToken token = (IToken) fWords.get(fBuffer.toString());
+ if (token != null)
+ return token;
+
+ if (fDefaultToken.isUndefined())
+ unreadBuffer(scanner);
+
+ return fDefaultToken;
+ }
+ }
+
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+ }
+
+ // private static String[] fgConstants = { "__LINE__", "__FILE__", "true",
+ // "false" };
+ private TextAttribute fComment;
+
+ private TextAttribute fKeyword;
+
+ private TextAttribute fType;
+
+ private TextAttribute fString;
+
+ private PHPColorProvider fColorProvider;
+
+ /**
+ * Creates a Java code scanner
+ */
+ public HTMLCodeScanner(IColorManager manager, IPreferenceStore store) {
+ super(manager, store);
+ initialize();
+ }
+
+ /*
+ * @see AbstractJavaScanner#createRules()
+ */
+ protected List createRules() {
+ List rules = new ArrayList();
+
+ // keyword = new Token(new
+ // TextAttribute(provider.getColor(PHPColorProvider.KEYWORD)));
+ // IToken type = new Token(new
+ // TextAttribute(provider.getColor(PHPColorProvider.FUNCTION_NAME)));
+ // IToken string = new Token(new
+ // TextAttribute(provider.getColor(PHPColorProvider.STRING_DQ)));
+ // IToken comment = new Token(new
+ // TextAttribute(provider.getColor(PHPColorProvider.SINGLE_LINE_COMMENT)));
+ // IToken multi_comment = new Token(new
+ // TextAttribute(provider.getColor(PHPColorProvider.MULTI_LINE_COMMENT)));
+ // IToken other = new Token(new
+ // TextAttribute(provider.getColor(PHPColorProvider.DEFAULT)));
+
+ // variable = new Token(new
+ // TextAttribute(provider.getColor(PHPColorProvider.VARIABLE)));
+
+ // Add rule for single line comments.
+ // rules.add(new EndOfLineRule("//", comment)); //$NON-NLS-1$
+ // rules.add(new EndOfLineRule("#", comment));
+
+ // Add rule for strings and character constants.
+ rules.add(new SingleLineRule(
+ "\"", "\"", getToken(IPreferenceConstants.PHP_STRING_DQ))); //$NON-NLS-2$ //$NON-NLS-1$
+ // rules.add(new SingleLineRule("'", "'", string, '\\')); //$NON-NLS-2$
+ // //$NON-NLS-1$
+
+ // rules.add(new SingleLineRule("//", "//", php_comment));
+ // rules.add(new MultiLineRule("/*", "*/", multi_comment));
+
+ // Add generic whitespace rule.
+ rules.add(new WhitespaceRule(new PHPWhitespaceDetector()));
+
+ // Add word rule for keywords, types, and constants.
+ HTMLWordRule wordRule = new HTMLWordRule(new HTMLWordDetector(),
+ getToken(IPreferenceConstants.PHP_DEFAULT));
+ // for (int i = 0; i < fgKeywords.length; i++)
+ // wordRule.addWord(fgKeywords[i], keyword);
+ // for (int i = 0; i < fgTypes.length; i++)
+ // wordRule.addWord(fgTypes[i], type);
+ rules.add(wordRule);
+
+ setDefaultReturnToken(getToken(IPreferenceConstants.PHP_DEFAULT));
+ return rules;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLCompletionProcessor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLCompletionProcessor.java
new file mode 100644
index 0000000..ac0a364
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLCompletionProcessor.java
@@ -0,0 +1,309 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpdt.internal.ui.text.java.PHPCompletionProposalComparator;
+import net.sourceforge.phpdt.internal.ui.text.template.contentassist.TemplateEngine;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.TextPresentation;
+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.IContextInformationExtension;
+import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * HTML completion processor.
+ */
+public class HTMLCompletionProcessor implements IContentAssistProcessor {
+
+ /**
+ * Simple content assist tip closer. The tip is valid in a range of 5
+ * characters around its popup location.
+ */
+ protected static class Validator implements IContextInformationValidator,
+ IContextInformationPresenter {
+
+ protected int fInstallOffset;
+
+ /*
+ * @see IContextInformationValidator#isContextInformationValid(int)
+ */
+ public boolean isContextInformationValid(int offset) {
+ return Math.abs(fInstallOffset - offset) < 5;
+ }
+
+ /*
+ * @see IContextInformationValidator#install(IContextInformation,
+ * ITextViewer, int)
+ */
+ public void install(IContextInformation info, ITextViewer viewer,
+ int offset) {
+ fInstallOffset = offset;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int,
+ * TextPresentation)
+ */
+ public boolean updatePresentation(int documentPosition,
+ TextPresentation presentation) {
+ return false;
+ }
+ };
+
+ private static class ContextInformationWrapper implements
+ IContextInformation, IContextInformationExtension {
+
+ private final IContextInformation fContextInformation;
+
+ private int fPosition;
+
+ public ContextInformationWrapper(IContextInformation contextInformation) {
+ fContextInformation = contextInformation;
+ }
+
+ /*
+ * @see IContextInformation#getContextDisplayString()
+ */
+ public String getContextDisplayString() {
+ return fContextInformation.getContextDisplayString();
+ }
+
+ /*
+ * @see IContextInformation#getImage()
+ */
+ public Image getImage() {
+ return fContextInformation.getImage();
+ }
+
+ /*
+ * @see IContextInformation#getInformationDisplayString()
+ */
+ public String getInformationDisplayString() {
+ return fContextInformation.getInformationDisplayString();
+ }
+
+ /*
+ * @see IContextInformationExtension#getContextInformationPosition()
+ */
+ public int getContextInformationPosition() {
+ return fPosition;
+ }
+
+ public void setContextInformationPosition(int position) {
+ fPosition = position;
+ }
+ };
+
+ protected IContextInformationValidator fValidator = new Validator();
+
+ private TemplateEngine fTemplateEngine;
+
+ private char[] fProposalAutoActivationSet;
+
+ private PHPCompletionProposalComparator fComparator;
+
+ private int fNumberOfComputedResults = 0;
+
+ private IEditorPart fEditor;
+
+ protected IWorkingCopyManager fManager;
+
+ public HTMLCompletionProcessor(IEditorPart editor) {
+ fEditor = editor;
+ fManager = WebUI.getDefault().getWorkingCopyManager();
+
+ TemplateContextType contextType = WebUI.getDefault()
+ .getTemplateContextRegistry().getContextType("html"); //$NON-NLS-1$
+ if (contextType != null)
+ fTemplateEngine = new TemplateEngine(contextType);
+
+ fComparator = new PHPCompletionProposalComparator();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
+ int documentOffset) {
+ int contextInformationPosition = guessContextInformationPosition(
+ viewer, documentOffset);
+ return internalComputeCompletionProposals(viewer, documentOffset,
+ contextInformationPosition);
+ }
+
+ private ICompletionProposal[] internalComputeCompletionProposals(
+ ITextViewer viewer, int offset, int contextOffset) {
+ IDocument document = viewer.getDocument();
+ ICompilationUnit unit = fManager.getWorkingCopy(fEditor
+ .getEditorInput());
+
+ if (fTemplateEngine != null) {
+ ICompletionProposal[] results;
+ // try {
+ fTemplateEngine.reset();
+ fTemplateEngine.complete(viewer, offset, unit);
+ // } catch (JavaModelException x) {
+ // Shell shell= viewer.getTextWidget().getShell();
+ // ErrorDialog.openError(shell,
+ // JavaTextMessages.getString("CompletionProcessor.error.accessing.title"),
+ // JavaTextMessages.getString("CompletionProcessor.error.accessing.message"),
+ // x.getStatus()); //$NON-NLS-2$ //$NON-NLS-1$
+ // }
+
+ IPHPCompletionProposal[] templateResults = fTemplateEngine
+ .getResults();
+
+ // concatenate arrays
+ IPHPCompletionProposal[] total;
+ total = new IPHPCompletionProposal[templateResults.length];
+ System.arraycopy(templateResults, 0, total, 0,
+ templateResults.length);
+ results = total;
+
+ fNumberOfComputedResults = (results == null ? 0 : results.length);
+ /*
+ * Order here and not in result collector to make sure that the
+ * order applies to all proposals and not just those of the
+ * compilation unit.
+ */
+ return order(results);
+ }
+ return new IPHPCompletionProposal[0];
+ }
+
+ private int guessContextInformationPosition(ITextViewer viewer, int offset) {
+ int contextPosition = offset;
+ IDocument document = viewer.getDocument();
+ return contextPosition;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ // public IContextInformation[] computeContextInformation(ITextViewer
+ // viewer, int documentOffset) {
+ // IContextInformation[] result = new IContextInformation[5];
+ // for (int i = 0; i < result.length; i++)
+ // result[i] = new
+ // ContextInformation(MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.ContextInfo.display.pattern"),
+ // new Object[] { new Integer(i), new Integer(documentOffset)}),
+ // //$NON-NLS-1$
+ // MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.ContextInfo.value.pattern"),
+ // new Object[] { new Integer(i), new Integer(documentOffset - 5), new
+ // Integer(documentOffset + 5)})); //$NON-NLS-1$
+ // return result;
+ // }
+ /**
+ * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
+ */
+ public IContextInformation[] computeContextInformation(ITextViewer viewer,
+ int offset) {
+ int contextInformationPosition = guessContextInformationPosition(
+ viewer, offset);
+ List result = addContextInformations(viewer, contextInformationPosition);
+ return (IContextInformation[]) result
+ .toArray(new IContextInformation[result.size()]);
+ }
+
+ private List addContextInformations(ITextViewer viewer, int offset) {
+ ICompletionProposal[] proposals = internalComputeCompletionProposals(
+ viewer, offset, -1);
+
+ List result = new ArrayList();
+ for (int i = 0; i < proposals.length; i++) {
+ IContextInformation contextInformation = proposals[i]
+ .getContextInformation();
+ if (contextInformation != null) {
+ ContextInformationWrapper wrapper = new ContextInformationWrapper(
+ contextInformation);
+ wrapper.setContextInformationPosition(offset);
+ result.add(wrapper);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Order the given proposals.
+ */
+ private ICompletionProposal[] order(ICompletionProposal[] proposals) {
+ Arrays.sort(proposals, fComparator);
+ return proposals;
+ }
+
+ /**
+ * Tells this processor to order the proposals alphabetically.
+ *
+ * @param order
+ * true
if proposals should be ordered.
+ */
+ public void orderProposalsAlphabetically(boolean order) {
+ fComparator.setOrderAlphabetically(order);
+ }
+
+ /**
+ * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
+ */
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return fProposalAutoActivationSet;
+ }
+
+ /**
+ * Sets this processor's set of characters triggering the activation of the
+ * completion proposal computation.
+ *
+ * @param activationSet
+ * the activation set
+ */
+ public void setCompletionProposalAutoActivationCharacters(
+ char[] activationSet) {
+ fProposalAutoActivationSet = activationSet;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public char[] getContextInformationAutoActivationCharacters() {
+ return new char[] {};
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ return fValidator;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public String getErrorMessage() {
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLPartitionScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLPartitionScanner.java
new file mode 100644
index 0000000..eab265e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLPartitionScanner.java
@@ -0,0 +1,472 @@
+/**
+ * This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * Created on 05.03.2003
+ *
+ * @author Stefan Langer (musk)
+ * @version $Revision: 1.3 $
+ */
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ *
+ */
+public class HTMLPartitionScanner implements IPartitionTokenScanner {
+ private static final boolean DEBUG = false;
+
+ private boolean fInString = false;
+
+ private boolean fInDoubString = false;
+
+ private IDocument fDocument = null;
+
+ private int fOffset = -1;
+
+ private String fContentType = IPHPPartitions.HTML;
+
+ private String fPrevContentType = IPHPPartitions.HTML;
+
+ private boolean partitionBorder = false;
+
+ private int fTokenOffset;
+
+ private int fEnd = -1;
+
+ private int fLength;
+
+ private int fCurrentLength;
+
+ private int fFileType;
+
+ private Map tokens = new HashMap();
+
+ public HTMLPartitionScanner() {
+ this(IPHPPartitions.PHP_FILE);
+ }
+
+ public HTMLPartitionScanner(int fileType) {
+ this.tokens.put(IPHPPartitions.HTML, new Token(IPHPPartitions.HTML));
+ this.tokens.put(IPHPPartitions.HTML_MULTILINE_COMMENT, new Token(
+ IPHPPartitions.HTML_MULTILINE_COMMENT));
+
+ this.tokens
+ .put(IPHPPartitions.SMARTY, new Token(IPHPPartitions.SMARTY));
+ this.tokens.put(IPHPPartitions.SMARTY_MULTILINE_COMMENT, new Token(
+ IPHPPartitions.SMARTY_MULTILINE_COMMENT));
+
+ this.tokens.put(IDocument.DEFAULT_CONTENT_TYPE, new Token(
+ IDocument.DEFAULT_CONTENT_TYPE));
+ fFileType = fileType;
+ }
+
+ private IToken getToken(String type) {
+ fLength = fCurrentLength;
+ if (DEBUG) {
+
+ try {
+ if (fLength <= 0) {
+ int line = fDocument.getLineOfOffset(fOffset);
+ System.err.println("Error at "
+ + line
+ + " offset:"
+ + String.valueOf(fOffset
+ - fDocument.getLineOffset(line)));
+ }
+ } catch (BadLocationException e) { // should never happen
+ // TODO Write stacktrace to log
+ e.printStackTrace();
+ }
+ }
+ Assert.isTrue(fLength > 0, "Partition length <= 0!");
+ fCurrentLength = 0;
+ // String can never cross partition borders so reset string detection
+ fInString = false;
+ fInDoubString = false;
+ IToken token = (IToken) this.tokens.get(type);
+ Assert.isNotNull(token, "Token for type \"" + type + "\" not found!");
+ if (DEBUG) {
+ System.out.println("Partition: fTokenOffset=" + fTokenOffset
+ + " fContentType=" + type + " fLength=" + fLength);
+ }
+ return token;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.rules.IPartitionTokenScanner#setPartialRange(org.eclipse.jface.text.IDocument,
+ * int, int, java.lang.String, int)
+ */
+ public void setPartialRange(IDocument document, int offset, int length,
+ String contentType, int partitionOffset) {
+ if (DEBUG) {
+ System.out.println("*****");
+ System.out.println("PartialRange: contentType=" + contentType
+ + " partitionOffset=" + partitionOffset);
+ }
+
+ try {
+ if (partitionOffset > -1) {
+ partitionBorder = false;
+ // because of strings we have to parse the whole partition
+ this.setRange(document, partitionOffset, offset
+ - partitionOffset + length);
+ // sometimes we get a wrong partition so we retrieve the
+ // partition
+ // directly from the document
+ fContentType = fDocument.getContentType(partitionOffset);
+ } else
+ this.setRange(document, offset, length);
+
+ } catch (BadLocationException e) {
+ // should never happen
+ // TODO print stack trace to log
+ // fall back just scan the whole document again
+ this.setRange(document, 0, fDocument.getLength());
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
+ */
+ public int getTokenLength() {
+ return fLength;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
+ */
+ public int getTokenOffset() {
+ return fTokenOffset;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
+ */
+ public IToken nextToken() {
+ int c;
+
+ // check if we are not allready at the end of the
+ // file
+ if ((c = read()) == ICharacterScanner.EOF) {
+ partitionBorder = false;
+ return Token.EOF;
+ } else
+ unread();
+
+ if (partitionBorder) {
+ fTokenOffset = fOffset;
+ partitionBorder = false;
+ }
+
+ while ((c = read()) != ICharacterScanner.EOF) {
+ switch (c) {
+ case '<':
+ if (checkPattern(new char[] { '!', '-', '-' })) { // return
+ // previouse
+ // partition
+ if (fContentType != IPHPPartitions.HTML_MULTILINE_COMMENT
+ && fCurrentLength > 4) {
+ unread(4);
+ IToken token = getToken(fContentType);
+ fContentType = IPHPPartitions.HTML_MULTILINE_COMMENT;
+ return token;
+ } else
+ fContentType = IPHPPartitions.HTML_MULTILINE_COMMENT;
+
+ fTokenOffset = fOffset - 4;
+ fCurrentLength = 4;
+ }
+ break;
+ case '-':
+ if (fContentType == IPHPPartitions.HTML_MULTILINE_COMMENT
+ && checkPattern(new char[] { '-', '>' })) {
+ fContentType = IPHPPartitions.HTML;
+ partitionBorder = true;
+ return getToken(IPHPPartitions.HTML_MULTILINE_COMMENT);
+ }
+ break;
+ case '{': // SMARTY code starts here ?
+ if (fFileType == IPHPPartitions.SMARTY_FILE) {
+ if ((c = read()) == '*') {
+ if (DEBUG) {
+ System.out.println("SMARTYDOC_TOKEN start "
+ + fTokenOffset + " fContentType="
+ + fContentType + " fLength=" + fLength
+ + " fOffset=" + fOffset
+ + " fCurrentLength=" + fCurrentLength);
+ }
+ if (fContentType != IPHPPartitions.SMARTY_MULTILINE_COMMENT
+ && fCurrentLength > 2) {
+ // SMARTY doc code starts here
+ unread(2);
+ IToken token = getToken(fContentType);
+ fContentType = IPHPPartitions.SMARTY_MULTILINE_COMMENT;
+ return token;
+ // } else if (fContentType ==
+ // IPHPPartitionScannerConstants.HTML && fOffset ==
+ // 2) {
+ // fContentType =
+ // IPHPPartitionScannerConstants.SMARTY_MULTILINE_COMMENT;
+ } else { // if (fContentType ==
+ // IPHPPartitionScannerConstants.SMARTY_MULTILINE_COMMENT)
+ // {
+ fContentType = IPHPPartitions.SMARTY_MULTILINE_COMMENT;
+ fTokenOffset = fOffset - 2;
+ fCurrentLength = 2;
+ }
+ break;
+ }
+ if (DEBUG) {
+ System.out.println("SMARTY_TOKEN start " + fTokenOffset
+ + " fContentType=" + fContentType + " fLength="
+ + fLength + " fOffset=" + fOffset);
+ }
+ if (c != ICharacterScanner.EOF) {
+ unread();
+ }
+ if (fContentType != IPHPPartitions.SMARTY
+ && fCurrentLength > 1) {
+ unread(1);
+ IToken token = getToken(fContentType);
+ fContentType = IPHPPartitions.SMARTY;
+ return token;
+ // } else if (fContentType ==
+ // IPHPPartitionScannerConstants.HTML && fOffset==1) {
+ // fContentType = IPHPPartitionScannerConstants.SMARTY;
+ } else {
+ fContentType = IPHPPartitions.SMARTY;
+ fTokenOffset = fOffset - 1;
+ fCurrentLength = 1;
+ }
+ }
+ break;
+ case '}': // SMARTY code ends here ?
+ if (fFileType == IPHPPartitions.SMARTY_FILE
+ && fContentType == IPHPPartitions.SMARTY) {
+ if (DEBUG) {
+ System.out.println("SMARTY_TOKEN end " + fTokenOffset
+ + " fContentType=" + fContentType + " fLength="
+ + fLength + " fOffset=" + fOffset);
+ }
+ fContentType = IPHPPartitions.HTML;
+ partitionBorder = true;
+ return getToken(IPHPPartitions.SMARTY);
+ }
+ break;
+ // case '/' :
+ // if (!isInString(IPHPPartitions.PHP_PARTITIONING) && (c = read())
+ // == '*') { // MULTINE COMMENT JAVASCRIPT, CSS, PHP
+ // if (fContentType == IPHPPartitions.PHP_PARTITIONING &&
+ // fCurrentLength > 2) {
+ // unread(2);
+ // IToken token = getToken(fContentType);
+ // fContentType = IPHPPartitions.PHP_PHPDOC_COMMENT;
+ // return token;
+ // } else if (fContentType == IPHPPartitions.PHP_PHPDOC_COMMENT) {
+ // fTokenOffset = fOffset - 2;
+ // fCurrentLength = 2;
+ // }
+ //
+ // } else if (!isInString(IPHPPartitions.PHP_PARTITIONING) && c !=
+ // ICharacterScanner.EOF)
+ // unread();
+ // break;
+ case '*':
+ if (fFileType == IPHPPartitions.SMARTY_FILE
+ && (c = read()) == '}') {
+ if (DEBUG) {
+ System.out.println("SMARTYDOC_TOKEN end "
+ + fTokenOffset + " fContentType="
+ + fContentType + " fLength=" + fLength
+ + " fOffset=" + fOffset);
+ }
+ if (fContentType == IPHPPartitions.SMARTY_MULTILINE_COMMENT) {
+ fContentType = IPHPPartitions.HTML;
+ partitionBorder = true;
+ return getToken(IPHPPartitions.SMARTY_MULTILINE_COMMENT);
+ }
+ }
+ break;
+ case '\'':
+ if (!fInDoubString)
+ fInString = !fInString;
+ break;
+ case '"':
+ // toggle String mode
+ if (!fInString)
+ fInDoubString = !fInDoubString;
+ break;
+ }
+ } // end of file reached but we have to return the
+ // last partition.
+ return getToken(fContentType);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(org.eclipse.jface.text.IDocument,
+ * int, int)
+ */
+ public void setRange(IDocument document, int offset, int length) {
+ if (DEBUG) {
+ System.out.println("SET RANGE: offset=" + offset + " length="
+ + length);
+ }
+
+ fDocument = document;
+ fOffset = offset;
+ fTokenOffset = offset;
+ fCurrentLength = 0;
+ fLength = 0;
+ fEnd = fOffset + length;
+ fInString = false;
+ fInDoubString = false;
+ fContentType = IPHPPartitions.HTML;
+ // String[] prev = getPartitionStack(offset);
+ }
+
+ private int read() {
+ try {
+ if (fOffset < fEnd) {
+ fCurrentLength++;
+ return fDocument.getChar(fOffset++);
+ }
+ return ICharacterScanner.EOF;
+ } catch (BadLocationException e) {
+ // should never happen
+ // TODO write stacktrace to log
+ fOffset = fEnd;
+ return ICharacterScanner.EOF;
+ }
+ }
+
+ private void unread() {
+ --fOffset;
+ --fCurrentLength;
+ }
+
+ private void unread(int num) {
+ fOffset -= num;
+ fCurrentLength -= num;
+ }
+
+ private boolean checkPattern(char[] pattern) {
+ return checkPattern(pattern, false);
+ }
+
+ /**
+ * Check if next character sequence read from document is equals to the
+ * provided pattern. Pattern is read from left to right until the first
+ * character read doesn't match. If this happens all read characters are
+ * unread.
+ *
+ * @param pattern
+ * The pattern to check.
+ * @return true
if pattern is equals else returns
+ * false
.
+ */
+ private boolean checkPattern(char[] pattern, boolean ignoreCase) {
+ int prevOffset = fOffset;
+ int prevLength = fCurrentLength;
+ for (int i = 0; i < pattern.length; i++) {
+ int c = read();
+
+ if (c == ICharacterScanner.EOF
+ || !letterEquals(c, pattern[i], ignoreCase)) {
+ fOffset = prevOffset;
+ fCurrentLength = prevLength;
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean letterEquals(int test, char letter, boolean ignoreCase) {
+ if (test == letter)
+ return true;
+ else if (ignoreCase && Character.isLowerCase(letter)
+ && test == Character.toUpperCase(letter))
+ return true;
+ else if (ignoreCase && Character.isUpperCase(letter)
+ && test == Character.toLowerCase(letter))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Checks wether the offset is in a String
and the specified
+ * contenttype is the current content type. Strings are delimited, mutual
+ * exclusive, by a " or by a '.
+ *
+ * @param contentType
+ * The contenttype to check.
+ * @return true
if the current offset is in a string else
+ * returns false.
+ */
+ private boolean isInString(String contentType) {
+ if (fContentType == contentType)
+ return (fInString || fInDoubString);
+ else
+ return false;
+ }
+
+ /**
+ * Returns the previouse partition stack for the given offset.
+ *
+ * @param offset
+ * The offset to return the previouse partitionstack for.
+ *
+ * @return The stack as a string array.
+ */
+ private String[] getPartitionStack(int offset) {
+ ArrayList types = new ArrayList();
+ int tmpOffset = 0;
+ try {
+ ITypedRegion region = fDocument.getPartition(offset);
+ tmpOffset = region.getOffset();
+ while (tmpOffset - 1 > 0) {
+ region = fDocument.getPartition(tmpOffset - 1);
+ tmpOffset = region.getOffset();
+ types.add(0, region.getType());
+ }
+ } catch (BadLocationException e) {
+ if (DEBUG) {
+ e.printStackTrace();
+ }
+ }
+
+ String[] retVal = new String[types.size()];
+
+ retVal = (String[]) types.toArray(retVal);
+ return retVal;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLWordExtractor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLWordExtractor.java
new file mode 100644
index 0000000..9968341
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/HTMLWordExtractor.java
@@ -0,0 +1,91 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Detects HTML words in documents.
+ */
+public class HTMLWordExtractor {
+
+ /**
+ * Find the location of the word at offset in document.
+ *
+ * @returns Point - x is the start position, y is the end position. Return
+ * null if it is not found.
+ * @param document
+ * the document being searched.
+ * @param offset -
+ * the position to start searching from.
+ */
+ public static Point findWord(IDocument document, int offset) {
+
+ int start = -1;
+ int end = -1;
+
+ try {
+
+ int position = offset;
+ char character = ' ';
+
+ while (position >= 0) {
+ character = document.getChar(position);
+ if (!Scanner.isPHPIdentifierPart(character))
+ break;
+ --position;
+ }
+ if ((position > 0) && (character == '<')) {
+ --position;
+ }
+ if ((position > 1) && (character == '/')) {
+ character = document.getChar(position - 1);
+ if (character == '<') {
+ --position;
+ --position;
+ }
+ }
+ if (position == offset) {
+ return null;
+ }
+
+ start = position;
+
+ position = offset;
+ int length = document.getLength();
+ character = ' ';
+
+ while (position < length) {
+ character = document.getChar(position);
+ if (!Scanner.isPHPIdentifierPart(character))
+ break;
+ ++position;
+ }
+ if ((position < length) && (character == '>')) {
+ ++position;
+ }
+ start++;
+ end = position;
+
+ if (end > start)
+ return new Point(start, end - start);
+
+ } catch (BadLocationException x) {
+ }
+
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPAutoIndentStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPAutoIndentStrategy.java
new file mode 100644
index 0000000..0283480
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPAutoIndentStrategy.java
@@ -0,0 +1,333 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Auto indent strategy sensitive to brackets.
+ */
+public class PHPAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
+
+ public PHPAutoIndentStrategy() {
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IAutoIndentStrategy
+ */
+ public void customizeDocumentCommand(IDocument d, DocumentCommand c) {
+ if (c.length == 0 && c.text != null && endsWithDelimiter(d, c.text))
+ smartIndentAfterNewLine(d, c);
+ else if ("}".equals(c.text)) {
+ smartInsertAfterBracket(d, c);
+ }
+ }
+
+ /**
+ * Returns whether or not the text ends with one of the given search
+ * strings.
+ */
+ private boolean endsWithDelimiter(IDocument d, String txt) {
+
+ String[] delimiters = d.getLegalLineDelimiters();
+
+ for (int i = 0; i < delimiters.length; i++) {
+ if (txt.endsWith(delimiters[i]))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the line number of the next bracket after end.
+ *
+ * @returns the line number of the next matching bracket after end
+ * @param document -
+ * the document being parsed
+ * @param line -
+ * the line to start searching back from
+ * @param end -
+ * the end position to search back from
+ * @param closingBracketIncrease -
+ * the number of brackets to skip
+ */
+ protected int findMatchingOpenBracket(IDocument document, int line,
+ int end, int closingBracketIncrease) throws BadLocationException {
+
+ int start = document.getLineOffset(line);
+ int brackcount = getBracketCount(document, start, end, false)
+ - closingBracketIncrease;
+
+ // sum up the brackets counts of each line (closing brackets count
+ // negative,
+ // opening positive) until we find a line the brings the count to zero
+ while (brackcount < 0) {
+ line--;
+ if (line < 0) {
+ return -1;
+ }
+ start = document.getLineOffset(line);
+ end = start + document.getLineLength(line) - 1;
+ brackcount += getBracketCount(document, start, end, false);
+ }
+ return line;
+ }
+
+ /**
+ * Returns the bracket value of a section of text. Closing brackets have a
+ * value of -1 and open brackets have a value of 1.
+ *
+ * @returns the line number of the next matching bracket after end
+ * @param document -
+ * the document being parsed
+ * @param start -
+ * the start position for the search
+ * @param end -
+ * the end position for the search
+ * @param ignoreCloseBrackets -
+ * whether or not to ignore closing brackets in the count
+ */
+ private int getBracketCount(IDocument document, int start, int end,
+ boolean ignoreCloseBrackets) throws BadLocationException {
+
+ int begin = start;
+ int bracketcount = 0;
+ while (begin < end) {
+ char curr = document.getChar(begin);
+ begin++;
+ switch (curr) {
+ case '/':
+ if (begin < end) {
+ char next = document.getChar(begin);
+ if (next == '*') {
+ // a comment starts, advance to the comment end
+ begin = getCommentEnd(document, begin + 1, end);
+ } else if (next == '/') {
+ // '//'-comment: nothing to do anymore on this line
+ begin = end;
+ }
+ }
+ break;
+ case '*':
+ if (begin < end) {
+ char next = document.getChar(begin);
+ if (next == '/') {
+ // we have been in a comment: forget what we read before
+ bracketcount = 0;
+ begin++;
+ }
+ }
+ break;
+ case '{':
+ bracketcount++;
+ ignoreCloseBrackets = false;
+ break;
+ case '}':
+ if (!ignoreCloseBrackets) {
+ bracketcount--;
+ }
+ break;
+ case '"':
+ case '\'':
+ begin = getStringEnd(document, begin, end, curr);
+ break;
+ default:
+ }
+ }
+ return bracketcount;
+ }
+
+ /**
+ * Returns the end position a comment starting at pos.
+ *
+ * @returns the end position a comment starting at pos
+ * @param document -
+ * the document being parsed
+ * @param position -
+ * the start position for the search
+ * @param end -
+ * the end position for the search
+ */
+ private int getCommentEnd(IDocument document, int position, int end)
+ throws BadLocationException {
+ int currentPosition = position;
+ while (currentPosition < end) {
+ char curr = document.getChar(currentPosition);
+ currentPosition++;
+ if (curr == '*') {
+ if (currentPosition < end
+ && document.getChar(currentPosition) == '/') {
+ return currentPosition + 1;
+ }
+ }
+ }
+ return end;
+ }
+
+ /**
+ * Returns the String at line with the leading whitespace removed.
+ *
+ * @returns the String at line with the leading whitespace removed.
+ * @param document -
+ * the document being parsed
+ * @param line -
+ * the line being searched
+ */
+ protected String getIndentOfLine(IDocument document, int line)
+ throws BadLocationException {
+ if (line > -1) {
+ int start = document.getLineOffset(line);
+ int end = start + document.getLineLength(line) - 1;
+ int whiteend = findEndOfWhiteSpace(document, start, end);
+ return document.get(start, whiteend - start);
+ } else {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Returns the position of the character in the document after position.
+ *
+ * @returns the next location of character.
+ * @param document -
+ * the document being parsed
+ * @param position -
+ * the position to start searching from
+ * @param end -
+ * the end of the document
+ * @param character -
+ * the character you are trying to match
+ */
+ private int getStringEnd(IDocument document, int position, int end,
+ char character) throws BadLocationException {
+ int currentPosition = position;
+ while (currentPosition < end) {
+ char currentCharacter = document.getChar(currentPosition);
+ currentPosition++;
+ if (currentCharacter == '\\') {
+ // ignore escaped characters
+ currentPosition++;
+ } else if (currentCharacter == character) {
+ return currentPosition;
+ }
+ }
+ return end;
+ }
+
+ /**
+ * Set the indent of a new line based on the command provided in the
+ * supplied document.
+ *
+ * @param document -
+ * the document being parsed
+ * @param command -
+ * the command being performed
+ */
+ protected void smartIndentAfterNewLine(IDocument document,
+ DocumentCommand command) {
+
+ int docLength = document.getLength();
+ if (command.offset == -1 || docLength == 0)
+ return;
+
+ try {
+ int p = (command.offset == docLength ? command.offset - 1
+ : command.offset);
+ int line = document.getLineOfOffset(p);
+
+ StringBuffer buf = new StringBuffer(command.text);
+ if (command.offset < docLength
+ && document.getChar(command.offset) == '}') {
+ int indLine = findMatchingOpenBracket(document, line,
+ command.offset, 0);
+ if (indLine == -1) {
+ indLine = line;
+ }
+ buf.append(getIndentOfLine(document, indLine));
+ } else {
+ int start = document.getLineOffset(line);
+ int whiteend = findEndOfWhiteSpace(document, start,
+ command.offset);
+ int offset = -1;
+ // if (command.offset > 0 && command.offset < docLength &&
+ // document.getChar(command.offset-1) == '{') {
+ // offset = command.offset;
+ // }
+ buf.append(document.get(start, whiteend - start));
+ if (getBracketCount(document, start, command.offset, true) > 0) {
+ buf.append('\t');
+ }
+ // if (offset >= 0) {
+ // buf.append('}');
+ // }
+ }
+ command.text = buf.toString();
+
+ } catch (BadLocationException excp) {
+ System.out.println(PHPEditorMessages
+ .getString("AutoIndent.error.bad_location_1")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Set the indent of a bracket based on the command provided in the supplied
+ * document.
+ *
+ * @param document -
+ * the document being parsed
+ * @param command -
+ * the command being performed
+ */
+ protected void smartInsertAfterBracket(IDocument document,
+ DocumentCommand command) {
+ if (command.offset == -1 || document.getLength() == 0)
+ return;
+
+ try {
+ int p = (command.offset == document.getLength() ? command.offset - 1
+ : command.offset);
+ int line = document.getLineOfOffset(p);
+ int start = document.getLineOffset(line);
+ int whiteend = findEndOfWhiteSpace(document, start, command.offset);
+
+ // shift only when line does not contain any text up to the closing
+ // bracket
+ if (whiteend == command.offset) {
+ // evaluate the line with the opening bracket that matches out
+ // closing bracket
+ int indLine = findMatchingOpenBracket(document, line,
+ command.offset, 1);
+ if (indLine != -1 && indLine != line) {
+ // take the indent of the found line
+ StringBuffer replaceText = new StringBuffer(
+ getIndentOfLine(document, indLine));
+ // add the rest of the current line including the just added
+ // close bracket
+ replaceText.append(document.get(whiteend, command.offset
+ - whiteend));
+ replaceText.append(command.text);
+ // modify document command
+ command.length = command.offset - start;
+ command.offset = start;
+ command.text = replaceText.toString();
+ }
+ }
+ } catch (BadLocationException excp) {
+ System.out.println(PHPEditorMessages
+ .getString("AutoIndent.error.bad_location_2")); //$NON-NLS-1$
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPCodeScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPCodeScanner.java
new file mode 100644
index 0000000..410e0c1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPCodeScanner.java
@@ -0,0 +1,477 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.phpeditor.PHPSyntaxRdr;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPWhitespaceDetector;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPWordDetector;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+
+/**
+ * PHP Code Scanner
+ */
+public class PHPCodeScanner extends AbstractJavaScanner {
+
+ /**
+ * Rule to detect java operators.
+ *
+ * @since 3.0
+ */
+ protected class OperatorRule implements IRule {
+
+ /** Java operators */
+ private final char[] PHP_OPERATORS = { ';', '(', ')', '.', '=', '/',
+ '\\', '+', '-', '*', '[', ']', '<', '>', ':', '?', '!', ',',
+ '|', '&', '^', '%', '~', '@' };
+
+ /** Token to return for this rule */
+ private final IToken fToken;
+
+ /** Token to return for braces */
+ private final IToken fTokenBraces;
+
+ /** Token to return for heredocs */
+ private final IToken fTokenHeredoc;
+
+ /**
+ * Creates a new operator rule.
+ *
+ * @param token
+ * Token to use for this rule
+ * @param tokenHeredoc
+ * TODO
+ */
+ public OperatorRule(IToken token, IToken tokenBraces,
+ IToken tokenHeredoc) {
+ fToken = token;
+ fTokenBraces = tokenBraces;
+ fTokenHeredoc = tokenHeredoc;
+ }
+
+ /**
+ * Is this character an operator character?
+ *
+ * @param character
+ * Character to determine whether it is an operator character
+ * @return true
iff the character is an operator,
+ * false
otherwise.
+ */
+ public boolean isOperator(char character) {
+ for (int index = 0; index < PHP_OPERATORS.length; index++) {
+ if (PHP_OPERATORS[index] == character)
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner)
+ */
+ public IToken evaluate(ICharacterScanner scanner) {
+
+ int character = scanner.read();
+ if (character == '{' || character == '}') {
+ return fTokenBraces;
+ }
+ if (isOperator((char) character)) {
+ int lastCharacter = character;
+ character = scanner.read();
+ // the readHEREDOC(scanner) call doesn't work, if we have our
+ // own partitions for single quoted
+ // or double quoted strings:
+ //
+ // if (lastCharacter == '<' && character == '<') {
+ // int heredocCharacter = scanner.read();
+ // if (heredocCharacter == '<') {
+ // // start of heredoc comment;
+ // if (readHEREDOC(scanner)) {
+ // return fTokenHeredoc;
+ // }
+ // } else {
+ // scanner.unread();
+ // }
+ // }
+ if (!isOperator((char) character)) {
+ scanner.unread();
+ return fToken;
+ }
+ if (checkPHPTag(scanner, lastCharacter, character)) {
+ return Token.UNDEFINED;
+ }
+ do {
+ lastCharacter = character;
+ character = scanner.read();
+ if (checkPHPTag(scanner, lastCharacter, character)) {
+ return fToken;
+ }
+ if (character == ICharacterScanner.EOF) {
+ return fToken;
+ }
+ } while (isOperator((char) character));
+ scanner.unread();
+ return fToken;
+ } else {
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+ }
+
+ // private boolean readHEREDOC(ICharacterScanner scanner) {
+ // // search until heredoc ends
+ // int ch;
+ // StringBuffer buf = new StringBuffer();
+ // char[] heredocIdent;
+ //
+ // ch = scanner.read();
+ // if (!Scanner.isPHPIdentifierStart((char)ch)) {
+ // scanner.unread();
+ // scanner.unread();
+ // return false;
+ // }
+ // while (Scanner.isPHPIdentifierPart((char)ch)) {
+ // buf.append((char)ch);
+ // ch = scanner.read();
+ // }
+ // if (ch==ICharacterScanner.EOF) {
+ // return true;
+ // }
+ // heredocIdent = buf.toString().toCharArray();
+ // while (true) {
+ // ch = scanner.read();
+ // if (ch==ICharacterScanner.EOF) {
+ // return true;
+ // }
+ // if (ch == '\n') { // heredoc could end after a newline
+ // int pos = 0;
+ // while (true) {
+ // if (pos == heredocIdent.length) {
+ // return true;
+ // }
+ // ch = scanner.read(); // ignore escaped character
+ // if (ch != heredocIdent[pos]) {
+ // break;
+ // }
+ // if (ch==ICharacterScanner.EOF) {
+ // return true;
+ // }
+ // pos++;
+ // }
+ // }
+ // }
+ // }
+
+ /**
+ * Check if lastCharacter/character are a PHP start or end token ( <?
+ * ... ?> )
+ *
+ * @param scanner
+ * @param lastCharacter
+ * @param character
+ * @return
+ */
+ private boolean checkPHPTag(ICharacterScanner scanner,
+ int lastCharacter, int character) {
+ if (lastCharacter == '<' && character == '?') {
+ scanner.unread();
+ scanner.unread();
+ return true;
+ } else if (lastCharacter == '?' && character == '>') {
+ scanner.unread();
+ scanner.unread();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ protected class AccentStringRule implements IRule {
+
+ /** Token to return for this rule */
+ private final IToken fToken;
+
+ public AccentStringRule(IToken token) {
+ fToken = token;
+
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner)
+ */
+ public IToken evaluate(ICharacterScanner scanner) {
+
+ int character = scanner.read();
+
+ if (character == '`') {
+
+ while (character != ICharacterScanner.EOF) {
+ character = scanner.read();
+ if (character == '\\') {
+ character = scanner.read();
+ } else if (character == '`') {
+ return fToken;
+ }
+ }
+ scanner.unread();
+ return Token.UNDEFINED;
+ } else {
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+ }
+
+ }
+
+ private class PHPWordRule extends WordRule {
+ private StringBuffer fBuffer = new StringBuffer();
+
+ protected Map fWordsIgnoreCase = new HashMap();
+
+ public PHPWordRule(IWordDetector detector) {
+ super(detector, Token.UNDEFINED);
+ }
+
+ public PHPWordRule(IWordDetector detector, IToken defaultToken) {
+ super(detector, defaultToken);
+ }
+
+ /**
+ * Adds a word and the token to be returned if it is detected.
+ *
+ * @param word
+ * the word this rule will search for, may not be
+ * null
+ * @param token
+ * the token to be returned if the word has been found, may
+ * not be null
+ */
+ public void addWordIgnoreCase(String word, IToken token) {
+ Assert.isNotNull(word);
+ Assert.isNotNull(token);
+
+ fWordsIgnoreCase.put(word, token);
+ }
+
+ public IToken evaluate(ICharacterScanner scanner) {
+ int c = scanner.read();
+ boolean isVariable = false;
+ boolean isUnderscore = false;
+ String word;
+ if (c == '<') {
+ c = scanner.read();
+ if (c != '?') {
+ scanner.unread();
+ scanner.unread();
+ return Token.UNDEFINED;
+ } else {
+ c = scanner.read();
+ if (c == '=') { // =
+ return getToken(IPreferenceConstants.PHP_TAG);
+ }
+ if (c != 'p' && c != 'P') {
+ scanner.unread();
+ return getToken(IPreferenceConstants.PHP_TAG);
+ } else {
+ c = scanner.read();
+ if (c != 'h' && c != 'H') {
+ scanner.unread();
+ scanner.unread();
+ return getToken(IPreferenceConstants.PHP_TAG);
+ } else {
+ c = scanner.read();
+ if (c != 'p' && c != 'P') {
+ scanner.unread();
+ scanner.unread();
+ scanner.unread();
+ return getToken(IPreferenceConstants.PHP_TAG);
+ } else {
+ return getToken(IPreferenceConstants.PHP_TAG);
+ }
+ }
+ }
+ }
+ }
+ if (c == '?') {
+ c = scanner.read();
+ if (c == '>') {
+ return getToken(IPreferenceConstants.PHP_TAG);
+ }
+ scanner.unread();
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+ if (fDetector.isWordStart((char) c)) {
+ if (c == '$') {
+ isVariable = true;
+ }
+ if (fColumn == UNDEFINED
+ || (fColumn == scanner.getColumn() - 1)) {
+
+ fBuffer.setLength(0);
+ fBuffer.append((char) c);
+ c = scanner.read();
+ if (c == '_') {
+ isUnderscore = true;
+ }
+ while (c != ICharacterScanner.EOF
+ && fDetector.isWordPart((char) c)) {
+ fBuffer.append((char) c);
+ c = scanner.read();
+ }
+ scanner.unread();
+
+ if (isVariable) {
+ if (isUnderscore) {
+ return getToken(IPreferenceConstants.PHP_VARIABLE_DOLLAR);
+ }
+ return getToken(IPreferenceConstants.PHP_VARIABLE);
+ }
+ word = fBuffer.toString();
+ IToken token = (IToken) fWords.get(word);
+ if (token != null)
+ return token;
+
+ token = (IToken) fWordsIgnoreCase.get(word.toLowerCase());
+ if (token != null)
+ return token;
+
+ if (fDefaultToken.isUndefined())
+ unreadBuffer(scanner);
+
+ return fDefaultToken;
+ }
+ }
+
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+ }
+
+ // private PHPColorProvider fColorProvider;
+
+ private static String[] fgTokenProperties = {
+ IPreferenceConstants.PHP_MULTILINE_COMMENT,
+ IPreferenceConstants.PHP_SINGLELINE_COMMENT,
+ IPreferenceConstants.PHP_TAG, IPreferenceConstants.PHP_KEYWORD,
+ IPreferenceConstants.PHP_FUNCTIONNAME,
+ IPreferenceConstants.PHP_VARIABLE,
+ IPreferenceConstants.PHP_VARIABLE_DOLLAR,
+ IPreferenceConstants.PHP_STRING_DQ,
+ IPreferenceConstants.PHP_STRING_SQ, IPreferenceConstants.PHP_TYPE,
+ IPreferenceConstants.PHP_CONSTANT,
+ IPreferenceConstants.PHP_DEFAULT,
+ IPreferenceConstants.PHP_OPERATOR,
+ IPreferenceConstants.PHP_BRACE_OPERATOR,
+ IPreferenceConstants.PHP_KEYWORD_RETURN };
+
+ /**
+ * Creates a PHP code scanner
+ */
+ // public PHPCodeScanner(JavaColorManager provider, IPreferenceStore store)
+ // {
+ public PHPCodeScanner(IColorManager manager, IPreferenceStore store) {
+ super(manager, store);
+ initialize();
+ }
+
+ /*
+ * @see AbstractJavaScanner#getTokenProperties()
+ */
+ protected String[] getTokenProperties() {
+ return fgTokenProperties;
+ }
+
+ /*
+ * @see AbstractJavaScanner#createRules()
+ */
+ protected List createRules() {
+ List rules = new ArrayList();
+ Token token = getToken(IPreferenceConstants.PHP_SINGLELINE_COMMENT);
+ // Add rule for single line comments.
+ // rules.add(new EndOfLineRule("//", token)); //$NON-NLS-1$
+ // rules.add(new EndOfLineRule("#", token)); //$NON-NLS-1$
+ // Add rule for strings and character constants.
+ // token = getToken(IPreferenceConstants.PHP_STRING_SQ);
+ // rules.add(new SingleQuoteStringRule(token));
+ // token = getToken(IPreferenceConstants.PHP_STRING_DQ);
+ // rules.add(new DoubleQuoteStringRule(token));
+ rules.add(new AccentStringRule(token));
+
+ token = getToken(IPreferenceConstants.PHP_MULTILINE_COMMENT);
+ rules.add(new MultiLineRule("/*", "*/", token)); //$NON-NLS-2$ //$NON-NLS-1$
+ // Add generic whitespace rule.
+ rules.add(new WhitespaceRule(new PHPWhitespaceDetector()));
+ // Add word rule for keywords, types, and constants.
+ token = getToken(IPreferenceConstants.PHP_DEFAULT);
+ PHPWordRule wordRule = new PHPWordRule(new PHPWordDetector(), token);
+
+ Token keyword = getToken(IPreferenceConstants.PHP_KEYWORD);
+ Token functionName = getToken(IPreferenceConstants.PHP_FUNCTIONNAME);
+ Token type = getToken(IPreferenceConstants.PHP_TYPE);
+ Token constant = getToken(IPreferenceConstants.PHP_CONSTANT);
+
+ ArrayList buffer = PHPSyntaxRdr.getSyntaxData();
+ // String strbuffer = null; unused
+ PHPElement elbuffer = null;
+ String name;
+ for (int i = 0; i < buffer.size(); i++) {
+ // while ((buffer != null)
+ // && (!buffer.isEmpty()
+ // && ((elbuffer = (PHPElement) buffer.remove(0)) != null))) {
+ elbuffer = (PHPElement) buffer.get(i);
+ if (elbuffer instanceof PHPKeyword) {
+ name = ((PHPKeyword) elbuffer).getName();
+ if (!name.equals("return")) {
+ wordRule.addWord(name, keyword);
+ }
+ } else if (elbuffer instanceof PHPFunction) {
+ wordRule.addWordIgnoreCase(((PHPFunction) elbuffer).getName(),
+ functionName);
+ } else if (elbuffer instanceof PHPType) {
+ wordRule.addWord(elbuffer.getName(), type);
+ } else if (elbuffer instanceof PHPConstant) {
+ wordRule.addWord(elbuffer.getName(), constant);
+ }
+ }
+
+ // Add word rule for keyword 'return'.
+ token = getToken(IPreferenceConstants.PHP_KEYWORD_RETURN);
+ wordRule.addWord("return", token);
+
+ // Add rule for operators and brackets (at the end !)
+ rules.add(new OperatorRule(getToken(IPreferenceConstants.PHP_OPERATOR),
+ getToken(IPreferenceConstants.PHP_BRACE_OPERATOR),
+ getToken(IPreferenceConstants.PHP_STRING_DQ)));
+
+ rules.add(wordRule);
+
+ setDefaultReturnToken(getToken(IPreferenceConstants.PHP_DEFAULT));
+ return rules;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPCompletionProcessor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPCompletionProcessor.java
new file mode 100644
index 0000000..8c20ba6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPCompletionProcessor.java
@@ -0,0 +1,1068 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedMap;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.ToolFactory;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.DefaultErrorHandlingPolicies;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
+import net.sourceforge.phpdt.internal.compiler.parser.VariableInfo;
+import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContextType;
+import net.sourceforge.phpdt.internal.ui.text.PHPCodeReader;
+import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
+import net.sourceforge.phpdt.internal.ui.text.java.JavaParameterListValidator;
+import net.sourceforge.phpdt.internal.ui.text.java.PHPCompletionProposalComparator;
+import net.sourceforge.phpdt.internal.ui.text.template.BuiltInEngine;
+import net.sourceforge.phpdt.internal.ui.text.template.DeclarationEngine;
+import net.sourceforge.phpdt.internal.ui.text.template.LocalVariableProposal;
+import net.sourceforge.phpdt.internal.ui.text.template.contentassist.TemplateEngine;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.PHPSyntaxRdr;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+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.IContextInformationExtension;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+
+/**
+ * Example PHP completion processor.
+ */
+public class PHPCompletionProcessor implements IContentAssistProcessor {
+ /**
+ * Simple content assist tip closer. The tip is valid in a range of 5
+ * characters around its popup location.
+ */
+ // protected static class Validator implements IContextInformationValidator,
+ // IContextInformationPresenter {
+ // protected int fInstallOffset;
+ //
+ // /*
+ // * @see IContextInformationValidator#isContextInformationValid(int)
+ // */
+ // public boolean isContextInformationValid(int offset) {
+ // return Math.abs(fInstallOffset - offset) < 5;
+ // }
+ //
+ // /*
+ // * @see IContextInformationValidator#install(IContextInformation,
+ // ITextViewer, int)
+ // */
+ // public void install(IContextInformation info, ITextViewer viewer, int
+ // offset) {
+ // fInstallOffset = offset;
+ // }
+ //
+ // /*
+ // * @see
+ // org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int,
+ // TextPresentation)
+ // */
+ // public boolean updatePresentation(int documentPosition, TextPresentation
+ // presentation) {
+ // return false;
+ // }
+ // };
+ private static class ContextInformationWrapper implements
+ IContextInformation, IContextInformationExtension {
+ private final IContextInformation fContextInformation;
+
+ private int fPosition;
+
+ public ContextInformationWrapper(IContextInformation contextInformation) {
+ fContextInformation = contextInformation;
+ }
+
+ /*
+ * @see IContextInformation#getContextDisplayString()
+ */
+ public String getContextDisplayString() {
+ return fContextInformation.getContextDisplayString();
+ }
+
+ /*
+ * @see IContextInformation#getImage()
+ */
+ public Image getImage() {
+ return fContextInformation.getImage();
+ }
+
+ /*
+ * @see IContextInformation#getInformationDisplayString()
+ */
+ public String getInformationDisplayString() {
+ return fContextInformation.getInformationDisplayString();
+ }
+
+ /*
+ * @see IContextInformationExtension#getContextInformationPosition()
+ */
+ public int getContextInformationPosition() {
+ return fPosition;
+ }
+
+ public void setContextInformationPosition(int position) {
+ fPosition = position;
+ }
+ };
+
+ // private class TableName {
+ // String fTableName;
+ //
+ // TableName() {
+ // fTableName = null;
+ // }
+ //
+ // /**
+ // * @return Returns the tableName.
+ // */
+ // public String getTableName() {
+ // if (fTableName == null) {
+ // return "";
+ // }
+ // return fTableName;
+ // }
+ //
+ // /**
+ // * @param tableName
+ // * The tableName to set.
+ // */
+ // public void setTableName(String tableName) {
+ // fTableName = tableName;
+ // }
+ // }
+
+ private char[] fProposalAutoActivationSet;
+
+ protected IContextInformationValidator fValidator = null;
+
+ private TemplateEngine fTemplateEngine;
+
+ private PHPCompletionProposalComparator fComparator;
+
+ private IEditorPart fEditor;
+
+ protected IWorkingCopyManager fManager;
+
+ public PHPCompletionProcessor(IEditorPart editor) {
+ fEditor = editor;
+ fManager = WebUI.getDefault().getWorkingCopyManager();
+ TemplateContextType contextType = WebUI.getDefault()
+ .getTemplateContextRegistry().getContextType("php"); //$NON-NLS-1$
+ if (contextType != null)
+ fTemplateEngine = new TemplateEngine(contextType);
+ fComparator = new PHPCompletionProposalComparator();
+ }
+
+ /**
+ * Tells this processor to order the proposals alphabetically.
+ *
+ * @param order
+ * true
if proposals should be ordered.
+ */
+ public void orderProposalsAlphabetically(boolean order) {
+ fComparator.setOrderAlphabetically(order);
+ }
+
+ /**
+ * Sets this processor's set of characters triggering the activation of the
+ * completion proposal computation.
+ *
+ * @param activationSet
+ * the activation set
+ */
+ public void setCompletionProposalAutoActivationCharacters(
+ char[] activationSet) {
+ fProposalAutoActivationSet = activationSet;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
+ int documentOffset) {
+ int contextInformationPosition = guessContextInformationPosition(
+ viewer, documentOffset);
+ return internalComputeCompletionProposals(viewer, documentOffset,
+ contextInformationPosition);
+ }
+
+ private int getLastToken(List list, ITextViewer viewer,
+ int completionPosition, JavaContext context) {
+ // TableName tableName) {
+ IDocument document = viewer.getDocument();
+ int start = context.getStart();
+ // int end = context.getEnd();
+ String startText;
+ int lastSignificantToken = ITerminalSymbols.TokenNameEOF;
+ try {
+ // begin search 2 lines behind of this
+ int j = start;
+ if (j != 0) {
+ char ch;
+ while (j > 0) {
+ ch = document.getChar(--j);
+ if (ch == '\n') {
+ break;
+ }
+ }
+ while (j > 0) {
+ ch = document.getChar(--j);
+ if (ch == '\n') {
+ break;
+ }
+ }
+ }
+ if (j != start) {
+ // scan the line for the dereferencing operator '->'
+ startText = document.get(j, start - j);
+ if (Scanner.DEBUG) {
+ System.out.println(startText);
+ }
+ int token = ITerminalSymbols.TokenNameEOF;
+ // token = getLastSQLToken(startText);
+ // tableName.setTableName(getLastSQLTableName(startText));
+ Scanner scanner = ToolFactory
+ .createScanner(false, false, false);
+ scanner.setSource(startText.toCharArray());
+ scanner.setPHPMode(true);
+ int beforeLastToken = ITerminalSymbols.TokenNameEOF;
+ int lastToken = ITerminalSymbols.TokenNameEOF;
+ char[] ident = null;
+ try {
+ token = scanner.getNextToken();
+ lastToken = token;
+ while (token != ITerminalSymbols.TokenNameERROR
+ && token != ITerminalSymbols.TokenNameEOF) {
+ beforeLastToken = lastToken;
+ if (token == ITerminalSymbols.TokenNameVariable) {
+ ident = scanner.getCurrentTokenSource();
+ if (ident.length == 5 && ident[0] == '$'
+ && ident[1] == 't' && ident[2] == 'h'
+ && ident[3] == 'i' && ident[4] == 's') {
+ token = ITerminalSymbols.TokenNamethis_PHP_COMPLETION;
+ }
+ }
+ lastToken = token;
+ // System.out.println(scanner.toStringAction(lastToken));
+ token = scanner.getNextToken();
+ }
+ } catch (InvalidInputException e1) {
+ } catch (SyntaxError e) {
+ }
+ switch (lastToken) {
+ case ITerminalSymbols.TokenNameMINUS_GREATER:
+ // dereferencing operator '->' found
+ lastSignificantToken = ITerminalSymbols.TokenNameMINUS_GREATER;
+ if (beforeLastToken == ITerminalSymbols.TokenNameVariable) {
+ lastSignificantToken = ITerminalSymbols.TokenNameVariable;
+ list.set(0, ident);
+ } else if (beforeLastToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION) {
+ lastSignificantToken = ITerminalSymbols.TokenNamethis_PHP_COMPLETION;
+ list.set(0, ident);
+ }
+ break;
+ case ITerminalSymbols.TokenNamenew:
+ lastSignificantToken = ITerminalSymbols.TokenNamenew;
+ break;
+ }
+ }
+ } catch (BadLocationException e) {
+ }
+ return lastSignificantToken;
+ }
+
+ String getSQLTableName(String sqlText, int start) {
+ int tableNameStart = -1;
+ int currentCharacterPosition = start + 1;
+ char ch;
+ try {
+ while (true) {
+ ch = sqlText.charAt(currentCharacterPosition++);
+ if (tableNameStart == -1 && Scanner.isPHPIdentifierStart(ch)) {
+ tableNameStart = currentCharacterPosition - 1;
+ } else {
+ if (!Scanner.isPHPIdentifierPart(ch)) {
+ return sqlText.substring(tableNameStart,
+ currentCharacterPosition - 1);
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ if (tableNameStart >= 0) {
+ return sqlText.substring(tableNameStart,
+ currentCharacterPosition - 1);
+ }
+ }
+ return "";
+ }
+
+ // private String getLastSQLTableName(String startText) {
+ // // scan for sql identifiers
+ // char ch = ' ';
+ // int currentSQLPosition = startText.length();
+ // int identEnd = -1;
+ // String ident = null;
+ // try {
+ // while (true) {
+ // ch = startText.charAt(--currentSQLPosition);
+ // if (Scanner.isSQLIdentifierPart(ch)) {
+ // // if (ch >= 'A' && ch <= 'Z') {
+ // if (identEnd < 0) {
+ // identEnd = currentSQLPosition + 1;
+ // }
+ // // } else if (ch >= 'a' && ch <= 'z') {
+ // // if (identEnd < 0) {
+ // // identEnd = currentSQLPosition + 1;
+ // // }
+ // } else if (identEnd >= 0) {
+ // ident = startText.substring(currentSQLPosition + 1, identEnd);
+ // // select -- from -- where --
+ // // update -- set -- where --
+ // // insert into -- ( -- ) values ( -- )
+ // if (ident.length() >= 4 && ident.length() <= 6) {
+ // ident = ident.toLowerCase();
+ // switch (ident.length()) {
+ // // case 3 :
+ // // if (ident.equals("set")) {
+ // // // System.out.println("set");
+ // // token = ITerminalSymbols.TokenNameSQLset;
+ // // return token;
+ // // }
+ // // break;
+ // case 4:
+ // if (ident.equals("from")) {
+ // // System.out.println("from");
+ // return getSQLTableName(startText, identEnd);
+ // } else if (ident.equals("into")) {
+ // // System.out.println("into");
+ // return getSQLTableName(startText, identEnd);
+ // }
+ // break;
+ // case 6:
+ // if (ident.equals("update")) {
+ // // System.out.println("update");
+ // return getSQLTableName(startText, identEnd);
+ // }
+ // break;
+ // }
+ // }
+ // identEnd = -1;
+ // } else if (Character.isWhitespace(ch)) {
+ // }
+ // }
+ // } catch (IndexOutOfBoundsException e) {
+ // }
+ // return "";
+ // }
+
+ /**
+ * Detect the last significant SQL token in the text before the completion
+ *
+ * @param startText
+ */
+ // private int getLastSQLToken(String startText) {
+ // int token;
+ // // scan for sql identifiers
+ // char ch = ' ';
+ // int currentSQLPosition = startText.length();
+ // int identEnd = -1;
+ // String ident = null;
+ // try {
+ // while (true) {
+ // ch = startText.charAt(--currentSQLPosition);
+ // if (ch >= 'A' && ch <= 'Z') {
+ // if (identEnd < 0) {
+ // identEnd = currentSQLPosition + 1;
+ // }
+ // } else if (ch >= 'a' && ch <= 'z') {
+ // if (identEnd < 0) {
+ // identEnd = currentSQLPosition + 1;
+ // }
+ // } else if (identEnd >= 0) {
+ // ident = startText.substring(currentSQLPosition + 1, identEnd);
+ // // select -- from -- where --
+ // // update -- set -- where --
+ // // insert into -- ( -- ) values ( -- )
+ // if (ident.length() >= 3 && ident.length() <= 6) {
+ // ident = ident.toLowerCase();
+ // switch (ident.length()) {
+ // case 3:
+ // if (ident.equals("set")) {
+ // // System.out.println("set");
+ // token = ITerminalSymbols.TokenNameSQLset;
+ // return token;
+ // }
+ // break;
+ // case 4:
+ // if (ident.equals("from")) {
+ // // System.out.println("from");
+ // token = ITerminalSymbols.TokenNameSQLfrom;
+ // // getSQLTableName();
+ // return token;
+ // } else if (ident.equals("into")) {
+ // // System.out.println("into");
+ // token = ITerminalSymbols.TokenNameSQLinto;
+ // return token;
+ // }
+ // break;
+ // case 5:
+ // if (ident.equals("where")) {
+ // // System.out.println("where");
+ // token = ITerminalSymbols.TokenNameSQLwhere;
+ // return token;
+ // }
+ // break;
+ // case 6:
+ // if (ident.equals("select")) {
+ // // System.out.println("select");
+ // token = ITerminalSymbols.TokenNameSQLselect;
+ // return token;
+ // } else if (ident.equals("insert")) {
+ // // System.out.println("insert");
+ // token = ITerminalSymbols.TokenNameSQLinsert;
+ // return token;
+ // } else if (ident.equals("update")) {
+ // // System.out.println("update");
+ // token = ITerminalSymbols.TokenNameSQLupdate;
+ // return token;
+ // } else if (ident.equals("values")) {
+ // // System.out.println("values");
+ // token = ITerminalSymbols.TokenNameSQLvalues;
+ // return token;
+ // }
+ // break;
+ // }
+ // }
+ // identEnd = -1;
+ // }
+ // }
+ // } catch (IndexOutOfBoundsException e) {
+ // }
+ // return ITerminalSymbols.TokenNameEOF;
+ // }
+ private ICompletionProposal[] internalComputeCompletionProposals(
+ ITextViewer viewer, int offset, int contextOffset) {
+ ICompilationUnit unit = fManager.getWorkingCopy(fEditor
+ .getEditorInput());
+ IDocument document = viewer.getDocument();
+ IFile file = null;
+ IProject project = null;
+ if (offset > 0) {
+ PHPEditor editor = null;
+ if (fEditor != null && (fEditor instanceof PHPEditor)) {
+ editor = (PHPEditor) fEditor;
+ IEditorInput editorInput = editor.getEditorInput();
+ if (editorInput instanceof IFileEditorInput) {
+ file = ((IFileEditorInput) editorInput).getFile();
+ project = file.getProject();
+ } else {
+ return new ICompletionProposal[0];
+ }
+ }
+ }
+
+ Point selection = viewer.getSelectedRange();
+ // remember selected text
+ String selectedText = null;
+ if (selection.y != 0) {
+ try {
+ selectedText = document.get(selection.x, selection.y);
+ } catch (BadLocationException e) {
+ }
+ }
+
+ if (offset > 2 && fProposalAutoActivationSet != null) {
+ // restrict auto activation for '>' character to '->' token
+
+ try {
+ char ch = document.getChar(offset - 1);
+ if (ch == '>') {
+ for (int i = 0; i < fProposalAutoActivationSet.length; i++) {
+ ch = fProposalAutoActivationSet[i];
+ if (ch == '>') { // auto activation enabled
+ ch = document.getChar(offset - 2);
+ if (ch != '-') {
+ return new IPHPCompletionProposal[0];
+ }
+ break;
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ }
+
+ JavaContextType phpContextType = (JavaContextType) WebUI
+ .getDefault().getTemplateContextRegistry()
+ .getContextType("php"); //$NON-NLS-1$
+ JavaContext context = (JavaContext) phpContextType.createContext(
+ document, offset, selection.y, unit);
+ context.setVariable("selection", selectedText); //$NON-NLS-1$
+ String prefix = context.getKey();
+
+ HashMap methodVariables = null;
+ // HashMap typeVariables = null;
+ HashMap unitVariables = null;
+ ICompilationUnit compilationUnit = (ICompilationUnit) context
+ .findEnclosingElement(IJavaElement.COMPILATION_UNIT);
+ // if (compilationUnit != null) {
+ // unitVariables = ((CompilationUnit) compilationUnit).variables;
+ // }
+ IType type = (IType) context.findEnclosingElement(IJavaElement.TYPE);
+ if (type != null) {
+ // typeVariables = ((SourceType) type).variables;
+ }
+ IMethod method = (IMethod) context
+ .findEnclosingElement(IJavaElement.METHOD);
+ // if (method != null) {
+ // methodVariables = ((SourceMethod) method).variables;
+ // }
+
+ boolean emptyPrefix = prefix == null || prefix.equals("");
+ IPHPCompletionProposal[] localVariableResults = new IPHPCompletionProposal[0];
+
+ if (!emptyPrefix && prefix.length() >= 1 && prefix.charAt(0) == '$') {
+ // php Variable ?
+ String lowerCasePrefix = prefix.toLowerCase();
+ HashSet localVariables = new HashSet();
+ if (compilationUnit != null) {
+ unitVariables = getUnitVariables(unitVariables, compilationUnit);
+ getVariableProposals(localVariables, viewer, project, context,
+ unitVariables, lowerCasePrefix, 94);
+ }
+ if (method != null) {
+ methodVariables = getMethodVariables(methodVariables, method);
+ getVariableProposals(localVariables, viewer, project, context,
+ methodVariables, lowerCasePrefix, 99);
+ }
+ if (!localVariables.isEmpty()) {
+ localVariableResults = (IPHPCompletionProposal[]) localVariables
+ .toArray(new IPHPCompletionProposal[localVariables
+ .size()]);
+ }
+ }
+
+ // TableName sqlTable = new TableName();
+ ArrayList list = new ArrayList();
+ list.add(null);
+ int lastSignificantToken = getLastToken(list, viewer, offset, context); // ,
+ // sqlTable);
+ boolean useClassMembers = (lastSignificantToken == ITerminalSymbols.TokenNameMINUS_GREATER)
+ || (lastSignificantToken == ITerminalSymbols.TokenNameVariable)
+ || (lastSignificantToken == ITerminalSymbols.TokenNamenew)
+ || (lastSignificantToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION);
+
+ if (fTemplateEngine != null) {
+ IPHPCompletionProposal[] templateResults = new IPHPCompletionProposal[0];
+ ICompletionProposal[] results;
+ if (!emptyPrefix) {
+ fTemplateEngine.reset();
+ fTemplateEngine.complete(viewer, offset, unit);
+ templateResults = fTemplateEngine.getResults();
+ }
+ // TODO delete this
+ IPHPCompletionProposal[] identifierResults = new IPHPCompletionProposal[0];
+
+ // declarations stored in file project.index on project level
+ IPHPCompletionProposal[] declarationResults = new IPHPCompletionProposal[0];
+ if (project != null) {
+ DeclarationEngine declarationEngine;
+ JavaContextType contextType = (JavaContextType) WebUI
+ .getDefault().getTemplateContextRegistry()
+ .getContextType("php"); //$NON-NLS-1$
+ if (contextType != null) {
+ IdentifierIndexManager indexManager = WebUI
+ .getDefault().getIndexManager(project);
+ SortedMap sortedMap;
+ declarationEngine = new DeclarationEngine(project,
+ contextType, lastSignificantToken, file);
+ if (lastSignificantToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION) {
+ // complete '$this->'
+ sortedMap = indexManager.getIdentifiers(file);
+ declarationEngine.completeObject(viewer, offset,
+ sortedMap, unit);
+ } else {
+ String typeRef = null;
+ char[] varName = (char[]) list.get(0);
+ if (varName != null) {
+ if (method != null) {
+ methodVariables = getMethodVariables(
+ methodVariables, method);
+ VariableInfo info = (VariableInfo) methodVariables
+ .get(new String(varName));
+ if (info != null && info.typeIdentifier != null) {
+ typeRef = new String(info.typeIdentifier);
+ }
+ }
+ }
+ if (typeRef != null) {
+ // complete '$variable->' with type information
+ sortedMap = indexManager.getIdentifiers(typeRef);
+ declarationEngine.completeObject(viewer, offset,
+ sortedMap, unit);
+ } else {
+ // complete '$variable->' without type information
+ sortedMap = indexManager.getIdentifierMap();
+ declarationEngine.complete(viewer, offset,
+ sortedMap, unit);
+ }
+ }
+ declarationResults = declarationEngine.getResults();
+ }
+ }
+ // built in function names from phpsyntax.xml
+ ArrayList syntaxbuffer = PHPSyntaxRdr.getSyntaxData();
+ IPHPCompletionProposal[] builtinResults = new IPHPCompletionProposal[0];
+ if ((!useClassMembers) && syntaxbuffer != null) {
+ BuiltInEngine builtinEngine;
+ JavaContextType contextType = (JavaContextType) WebUI
+ .getDefault().getTemplateContextRegistry()
+ .getContextType("php"); //$NON-NLS-1$
+ if (contextType != null) {
+ builtinEngine = new BuiltInEngine(contextType);
+ builtinEngine.complete(viewer, offset, syntaxbuffer, unit);
+ builtinResults = builtinEngine.getResults();
+ }
+ }
+ // ICompletionProposal[] sqlResults = new ICompletionProposal[0];
+ // if (project != null) {
+ // sqlResults = getSQLProposals(viewer, project, context, prefix,
+ // sqlTable);
+ // }
+ // concatenate the result arrays
+ IPHPCompletionProposal[] total;
+ total = new IPHPCompletionProposal[localVariableResults.length
+ + templateResults.length + identifierResults.length
+ + builtinResults.length + declarationResults.length];// +
+ // sqlResults.length];
+ System.arraycopy(templateResults, 0, total, 0,
+ templateResults.length);
+ System.arraycopy(identifierResults, 0, total,
+ templateResults.length, identifierResults.length);
+ System.arraycopy(builtinResults, 0, total, templateResults.length
+ + identifierResults.length, builtinResults.length);
+ System.arraycopy(declarationResults, 0, total,
+ templateResults.length + identifierResults.length
+ + builtinResults.length, declarationResults.length);
+ // System.arraycopy(sqlResults, 0, total, templateResults.length +
+ // identifierResults.length + builtinResults.length
+ // + declarationResults.length, sqlResults.length);
+ // System.arraycopy(localVariableResults, 0, total,
+ // templateResults.length
+ // + identifierResults.length + builtinResults.length
+ // + declarationResults.length + sqlResults.length,
+ // localVariableResults.length);
+ System
+ .arraycopy(localVariableResults, 0, total,
+ templateResults.length + identifierResults.length
+ + builtinResults.length
+ + declarationResults.length,
+ localVariableResults.length);
+ results = total;
+ // fNumberOfComputedResults = (results == null ? 0 :
+ // results.length);
+ /*
+ * Order here and not in result collector to make sure that the
+ * order applies to all proposals and not just those of the
+ * compilation unit.
+ */
+ return order(results);
+ }
+ return new IPHPCompletionProposal[0];
+ }
+
+ /**
+ * @param unitVariables
+ * @param unit
+ */
+ private HashMap getUnitVariables(HashMap unitVariables,
+ ICompilationUnit unit) {
+ if (unitVariables == null) {
+ try {
+ String unitText = unit.getSource();
+ unitVariables = new HashMap();
+
+ ProblemReporter problemReporter = new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ new CompilerOptions(JavaCore.getOptions()),
+ new DefaultProblemFactory());
+ UnitParser parser = new UnitParser(problemReporter);
+ parser.compilationUnit = new CompilationUnitDeclaration(
+ problemReporter, null, unitText.length());
+ parser.parse(unitText, unitVariables);
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ return unitVariables;
+ }
+
+ /**
+ * @param methodVariables
+ * @param method
+ */
+ private HashMap getMethodVariables(HashMap methodVariables, IMethod method) {
+ if (methodVariables == null) {
+ try {
+ String methodText = method.getSource();
+ methodVariables = new HashMap();
+ ProblemReporter problemReporter = new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ new CompilerOptions(JavaCore.getOptions()),
+ new DefaultProblemFactory());
+ UnitParser parser = new UnitParser(problemReporter);
+ parser.compilationUnit = new CompilationUnitDeclaration(
+ problemReporter, null, methodText.length());
+ parser.parseFunction(methodText, methodVariables);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ PHPeclipsePlugin.log(e);
+ }
+ }
+ return methodVariables;
+ }
+
+ /**
+ * @param viewer
+ * @param project
+ * @param context
+ * @param prefix
+ * @return
+ */
+ private void getVariableProposals(HashSet localVariables,
+ ITextViewer viewer, IProject project, JavaContext context,
+ HashMap variables, String prefix, int relevance) {
+ // try {
+ int start = context.getStart();
+ int end = context.getEnd();
+ IRegion region = new Region(start, end - start);
+ // IMethod method = (IMethod)
+ // context.findEnclosingElement(IJavaElement.METHOD);
+ // if (method != null && (method instanceof SourceMethod) &&
+ // ((SourceMethod)
+ // method).variables != null) {
+ // HashMap map = ((SourceMethod) method).variables;
+ Set set = variables.keySet();
+ Iterator iter = set.iterator();
+ String varName;
+ boolean matchesVarName;
+ while (iter.hasNext()) {
+ varName = (String) iter.next();
+ if (varName.length() >= prefix.length()) {
+ matchesVarName = true;
+ for (int i = 0; i < prefix.length(); i++) {
+ if (prefix.charAt(i) != Character.toLowerCase(varName
+ .charAt(i))) {
+ matchesVarName = false;
+ break;
+ }
+ }
+ if (matchesVarName) {
+ LocalVariableProposal prop;
+ // if (varName.length == prefix.length()) {
+ // prop = new LocalVariableProposal(new String(varName),
+ // region,
+ // viewer, relevance-10);
+ // } else {
+ prop = new LocalVariableProposal(new String(varName),
+ region, viewer, relevance);
+ // }
+ localVariables.add(prop);
+ }
+ }
+ }
+ // }
+
+ // char[] varName;
+ // boolean matchesVarName;
+ // if (method != null) {
+ // ISourceRange range = method.getSourceRange();
+ // char[] source = method.getSource().toCharArray();
+ // Scanner scanner = new Scanner();
+ // scanner.setSource(source);
+ // scanner.phpMode = true;
+ // int token = Scanner.TokenNameWHITESPACE;
+ // while ((token = scanner.getNextToken()) != Scanner.TokenNameEOF) {
+ // if (token == Scanner.TokenNameVariable) {
+ // varName = scanner.getCurrentTokenSource();
+ // if (varName.length >= prefix.length()) {
+ // matchesVarName = true;
+ // for (int i = 0; i < prefix.length(); i++) {
+ // if (prefix.charAt(i) != varName[i]) {
+ // matchesVarName = false;
+ // break;
+ // }
+ // }
+ // if (matchesVarName) {
+ // LocalVariableProposal prop = new LocalVariableProposal(new
+ // String(varName), region, viewer);
+ // if (varName.length == prefix.length()) {
+ // prop.setRelevance(98);
+ // }
+ // localVariables.add(prop);
+ // }
+ // }
+ // }
+ // }
+ // }
+ // } catch (Throwable e) {
+ // // ignore - Syntax exceptions could occur, if there are syntax errors
+ // !
+ // }
+ }
+
+ /**
+ * @param viewer
+ * @param project
+ * @param context
+ * @param prefix
+ * @param sqlTable
+ * @param sqlResults
+ * @return
+ */
+ // private ICompletionProposal[] getSQLProposals(ITextViewer viewer,
+ // IProject
+ // project, DocumentTemplateContext context,
+ // String prefix, TableName sqlTable) {
+ // ICompletionProposal[] sqlResults = new ICompletionProposal[0];
+ // // Get The Database bookmark from the Quantum SQL plugin:
+ // // BookmarkCollection sqlBookMarks = BookmarkCollection.getInstance();
+ // // if (sqlBookMarks != null) {
+ // String bookmarkString =
+ // ProjectPrefUtil.getMiscProjectsPreferenceValue(project,
+ // IPreferenceConstants.PHP_BOOKMARK_DEFAULT);
+ // if (bookmarkString != null && !bookmarkString.equals("")) {
+ // String[] bookmarks = ExternalInterface.getBookmarkNames();
+ // boolean foundBookmark = false;
+ // for (int i = 0; i < bookmarks.length; i++) {
+ // if (bookmarks[i].equals(bookmarkString)) {
+ // foundBookmark = true;
+ // }
+ // }
+ // if (!foundBookmark) {
+ // return sqlResults;
+ // }
+ // // Bookmark bookmark = sqlBookMarks.find(bookmarkString);
+ // ArrayList sqlList = new ArrayList();
+ // if (!ExternalInterface.isBookmarkConnected(bookmarkString)) {
+ // ExternalInterface.connectBookmark(bookmarkString, null);
+ // if (!ExternalInterface.isBookmarkConnected(bookmarkString)) {
+ // return sqlResults;
+ // }
+ // }
+ // // if (ExternalInterface.isBookmarkConnected(bookmarkString)) {
+ // try {
+ // int start = context.getStart();
+ // int end = context.getEnd();
+ // String foundSQLTableName = sqlTable.getTableName();
+ // String tableName;
+ // String columnName;
+ // String prefixWithoutDollar = prefix;
+ // boolean isDollarPrefix = false;
+ // if (prefix.length() > 0 && prefix.charAt(0) == '$') {
+ // prefixWithoutDollar = prefix.substring(1);
+ // isDollarPrefix = true;
+ // }
+ // IRegion region = new Region(start, end - start);
+ // ResultSet set;
+ // if (!isDollarPrefix) {
+ // String[] tableNames = ExternalInterface.getMatchingTableNames(null,
+ // bookmarkString, prefixWithoutDollar, null, false);
+ // for (int i = 0; i < tableNames.length; i++) {
+ // sqlList.add(new SQLProposal(tableNames[i], context, region, viewer,
+ // PHPUiImages.get(PHPUiImages.IMG_TABLE)));
+ // }
+ // }
+ //
+ // String[] columnNames = ExternalInterface.getMatchingColumnNames(null,
+ // bookmarkString, prefixWithoutDollar, null, false);
+ // for (int i = 0; i < columnNames.length; i++) {
+ // sqlList.add(new SQLProposal(columnNames[i], context, region, viewer,
+ // PHPUiImages.get(PHPUiImages.IMG_TABLE)));
+ // }
+ //
+ // sqlResults = new IPHPCompletionProposal[sqlList.size()];
+ // for (int i = 0; i < sqlList.size(); i++) {
+ // sqlResults[i] = (SQLProposal) sqlList.get(i);
+ // }
+ // } catch (Exception /* NotConnectedException */ e) {
+ //
+ // }
+ // // }
+ // }
+ // // }
+ // return sqlResults;
+ // }
+ private boolean looksLikeMethod(PHPCodeReader reader) throws IOException {
+ int curr = reader.read();
+ while (curr != PHPCodeReader.EOF && Character.isWhitespace((char) curr))
+ curr = reader.read();
+
+ if (curr == PHPCodeReader.EOF)
+ return false;
+
+ return Scanner.isPHPIdentifierPart((char) curr);
+ }
+
+ private int guessContextInformationPosition(ITextViewer viewer, int offset) {
+ int contextPosition = offset;
+ IDocument document = viewer.getDocument();
+ try {
+
+ PHPCodeReader reader = new PHPCodeReader();
+ reader.configureBackwardReader(document, offset, true, true);
+
+ int nestingLevel = 0;
+
+ int curr = reader.read();
+ while (curr != PHPCodeReader.EOF) {
+
+ if (')' == (char) curr)
+ ++nestingLevel;
+
+ else if ('(' == (char) curr) {
+ --nestingLevel;
+
+ if (nestingLevel < 0) {
+ int start = reader.getOffset();
+ if (looksLikeMethod(reader))
+ return start + 1;
+ }
+ }
+
+ curr = reader.read();
+ }
+ } catch (IOException e) {
+ }
+ return contextPosition;
+ }
+
+ /**
+ * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
+ */
+ public IContextInformation[] computeContextInformation(ITextViewer viewer,
+ int offset) {
+ int contextInformationPosition = guessContextInformationPosition(
+ viewer, offset);
+ List result = addContextInformations(viewer, contextInformationPosition);
+ return (IContextInformation[]) result
+ .toArray(new IContextInformation[result.size()]);
+ }
+
+ private List addContextInformations(ITextViewer viewer, int offset) {
+ ICompletionProposal[] proposals = internalComputeCompletionProposals(
+ viewer, offset, -1);
+ List result = new ArrayList();
+ for (int i = 0; i < proposals.length; i++) {
+ IContextInformation contextInformation = proposals[i]
+ .getContextInformation();
+ if (contextInformation != null) {
+ ContextInformationWrapper wrapper = new ContextInformationWrapper(
+ contextInformation);
+ wrapper.setContextInformationPosition(offset);
+ result.add(wrapper);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Order the given proposals.
+ */
+ private ICompletionProposal[] order(ICompletionProposal[] proposals) {
+ Arrays.sort(proposals, fComparator);
+ // int len = proposals.length;
+ // if (len > 10) {
+ // len = 10;
+ // }
+ // for (int i = 0; i < len; i++) {
+ // System.out.println(proposals[i].getDisplayString());
+ // }
+ return proposals;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return fProposalAutoActivationSet;
+ // return null; // new char[] { '$' };
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public char[] getContextInformationAutoActivationCharacters() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ if (fValidator == null)
+ fValidator = new JavaParameterListValidator();
+ return fValidator;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IContentAssistProcessor
+ */
+ public String getErrorMessage() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPConstant.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPConstant.java
new file mode 100644
index 0000000..b77593b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPConstant.java
@@ -0,0 +1,29 @@
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+/**
+ * @author Choochter
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>ObfuscatorIgnores. To enable and disable the creation
+ * of type comments go to Window>Preferences>Java>Code Generation.
+ */
+public class PHPConstant extends PHPElement {
+ private String fDescription;
+
+ public void setDescription(String description) {
+ this.fDescription = description;
+ }
+
+ public String getDescription() {
+ return this.fDescription;
+ }
+
+ public String getHoverText() {
+ return super.getHoverText() + "
" + getDescription();
+ }
+
+ public PHPConstant(String Name, String usage, String description) {
+ super(Name, usage);
+ setDescription(description);
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPDocumentPartitioner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPDocumentPartitioner.java
new file mode 100644
index 0000000..587806c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPDocumentPartitioner.java
@@ -0,0 +1,95 @@
+/**********************************************************************
+ Copyright (c) 2002 Widespace, OU and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://solareclipse.sourceforge.net/legal/cpl-v10.html
+
+ Contributors:
+ Igor Malinin - initial contribution
+
+ $Id: PHPDocumentPartitioner.java,v 1.6 2006-10-21 23:18:33 pombredanne Exp $
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.text.rules.FlatNode;
+import net.sourceforge.phpeclipse.ui.text.rules.MultiViewPartitioner;
+import net.sourceforge.phpeclipse.ui.text.rules.ViewNode;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class PHPDocumentPartitioner extends MultiViewPartitioner {
+ public static final String PHP_TEMPLATE_DATA = "__php_template_data";
+
+ public static final String PHP_SCRIPT_CODE = "__php_script_code";
+
+ public static final String[] LEGAL_TYPES = { PHP_TEMPLATE_DATA,
+ PHP_SCRIPT_CODE };
+
+ public PHPDocumentPartitioner(IPartitionTokenScanner scanner) {
+ super(scanner);
+ }
+
+ protected FlatNode createNode(String type, int offset, int length) {
+ if (type.equals(PHPPartitionScanner.PHP_SCRIPTING_AREA)) {
+ if (DEBUG) {
+ Assert.isTrue(offset >= 0);
+ }
+ ViewNode node = new ViewNode(type);
+ node.offset = offset;
+ node.length = length;
+ return node;
+ }
+
+ return super.createNode(type, offset, length);
+ }
+
+ /*
+ * @see net.sf.solareclipse.text.rules.DocumentViewPartitioner#createPartitioner(String)
+ */
+ protected IDocumentPartitioner createPartitioner(String contentType) {
+ if (contentType == null) {
+ // return JavaTextTools.createHTMLPartitioner();
+ return WebUI.getDefault().getJavaTextTools()
+ .getXMLTextTools().createPHPXMLPartitioner();
+ }
+
+ if (contentType.equals(PHPPartitionScanner.PHP_SCRIPTING_AREA)) {
+ return WebUI.getDefault().getJavaTextTools()
+ .createPHPPartitioner();
+ }
+ return null;
+ }
+
+ /*
+ * @see net.sf.solareclipse.text.rules.DocumentViewPartitioner#getContentType(String,
+ * String)
+ */
+ protected String getContentType(String parent, String view) {
+ if (parent == null) {
+ if (view == IDocument.DEFAULT_CONTENT_TYPE) {
+ return PHP_TEMPLATE_DATA;
+ }
+ } else {
+ if (view == IDocument.DEFAULT_CONTENT_TYPE) {
+ return PHP_SCRIPT_CODE;
+ }
+ }
+
+ return super.getContentType(parent, view);
+ }
+
+ public String[] getLegalContentTypes() {
+ return LEGAL_TYPES;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPDoubleClickSelector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPDoubleClickSelector.java
new file mode 100644
index 0000000..9a38d3b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPDoubleClickSelector.java
@@ -0,0 +1,261 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextViewer;
+
+/**
+ * Double click strategy aware of PHP identifier syntax rules.
+ */
+public class PHPDoubleClickSelector implements ITextDoubleClickStrategy {
+
+ protected ITextViewer fText;
+
+ protected int fPos;
+
+ protected int fStartPos;
+
+ protected int fEndPos;
+
+ protected static char[] fgBrackets = { '{', '}', '(', ')', '[', ']', '"',
+ '"' };
+
+ /*
+ * Create a PHPDoubleClickSelector.
+ */
+ public PHPDoubleClickSelector() {
+ super();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on ITextDoubleClickStrategy
+ */
+ public void doubleClicked(ITextViewer text) {
+
+ fPos = text.getSelectedRange().x;
+
+ if (fPos < 0)
+ return;
+
+ fText = text;
+
+ if (!selectBracketBlock())
+ selectWord();
+ }
+
+ /**
+ * Match the brackets at the current selection. Return true if successful,
+ * false otherwise.
+ */
+ protected boolean matchBracketsAt() {
+
+ char prevChar, nextChar;
+
+ int i;
+ int bracketIndex1 = fgBrackets.length;
+ int bracketIndex2 = fgBrackets.length;
+
+ fStartPos = -1;
+ fEndPos = -1;
+
+ // get the chars preceding and following the start position
+ try {
+
+ IDocument doc = fText.getDocument();
+
+ prevChar = doc.getChar(fPos - 1);
+ nextChar = doc.getChar(fPos);
+
+ // is the char either an open or close bracket?
+ for (i = 0; i < fgBrackets.length; i = i + 2) {
+ if (prevChar == fgBrackets[i]) {
+ fStartPos = fPos - 1;
+ bracketIndex1 = i;
+ }
+ }
+ for (i = 1; i < fgBrackets.length; i = i + 2) {
+ if (nextChar == fgBrackets[i]) {
+ fEndPos = fPos;
+ bracketIndex2 = i;
+ }
+ }
+
+ if (fStartPos > -1 && bracketIndex1 < bracketIndex2) {
+ fEndPos = searchForClosingBracket(fStartPos, prevChar,
+ fgBrackets[bracketIndex1 + 1], doc);
+ if (fEndPos > -1)
+ return true;
+ else
+ fStartPos = -1;
+ } else if (fEndPos > -1) {
+ fStartPos = searchForOpenBracket(fEndPos,
+ fgBrackets[bracketIndex2 - 1], nextChar, doc);
+ if (fStartPos > -1)
+ return true;
+ else
+ fEndPos = -1;
+ }
+
+ } catch (BadLocationException x) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Select the word at the current selection. Return true if successful,
+ * false otherwise.
+ */
+ protected boolean matchWord() {
+
+ IDocument doc = fText.getDocument();
+
+ try {
+
+ int pos = fPos;
+ char c;
+
+ while (pos >= 0) {
+ c = doc.getChar(pos);
+ if (!Scanner.isPHPIdentifierPart(c) && (c != '$')) {
+ break;
+ }
+ --pos;
+ }
+
+ fStartPos = pos;
+
+ pos = fPos;
+ int length = doc.getLength();
+
+ while (pos < length) {
+ c = doc.getChar(pos);
+ if (!Scanner.isPHPIdentifierPart(c) && (c != '$'))
+ break;
+ ++pos;
+ }
+
+ fEndPos = pos;
+
+ return true;
+
+ } catch (BadLocationException x) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the position of the closing bracket after startPosition.
+ *
+ * @returns the location of the closing bracket.
+ * @param startPosition -
+ * the beginning position
+ * @param openBracket -
+ * the character that represents the open bracket
+ * @param closeBracket -
+ * the character that represents the close bracket
+ * @param document -
+ * the document being searched
+ */
+ protected int searchForClosingBracket(int startPosition, char openBracket,
+ char closeBracket, IDocument document) throws BadLocationException {
+ int stack = 1;
+ int closePosition = startPosition + 1;
+ int length = document.getLength();
+ char nextChar;
+
+ while (closePosition < length && stack > 0) {
+ nextChar = document.getChar(closePosition);
+ if (nextChar == openBracket && nextChar != closeBracket)
+ stack++;
+ else if (nextChar == closeBracket)
+ stack--;
+ closePosition++;
+ }
+
+ if (stack == 0)
+ return closePosition - 1;
+ else
+ return -1;
+
+ }
+
+ /**
+ * Returns the position of the open bracket before startPosition.
+ *
+ * @returns the location of the starting bracket.
+ * @param startPosition -
+ * the beginning position
+ * @param openBracket -
+ * the character that represents the open bracket
+ * @param closeBracket -
+ * the character that represents the close bracket
+ * @param document -
+ * the document being searched
+ */
+ protected int searchForOpenBracket(int startPosition, char openBracket,
+ char closeBracket, IDocument document) throws BadLocationException {
+ int stack = 1;
+ int openPos = startPosition - 1;
+ char nextChar;
+
+ while (openPos >= 0 && stack > 0) {
+ nextChar = document.getChar(openPos);
+ if (nextChar == closeBracket && nextChar != openBracket)
+ stack++;
+ else if (nextChar == openBracket)
+ stack--;
+ openPos--;
+ }
+
+ if (stack == 0)
+ return openPos + 1;
+ else
+ return -1;
+ }
+
+ /**
+ * Select the area between the selected bracket and the closing bracket.
+ * Return true if successful.
+ */
+ protected boolean selectBracketBlock() {
+ if (matchBracketsAt()) {
+
+ if (fStartPos == fEndPos)
+ fText.setSelectedRange(fStartPos, 0);
+ else
+ fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Select the word at the current selection.
+ */
+ protected void selectWord() {
+ if (matchWord()) {
+
+ if (fStartPos == fEndPos)
+ fText.setSelectedRange(fStartPos, 0);
+ else
+ fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPEditorMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPEditorMessages.java
new file mode 100644
index 0000000..905771d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPEditorMessages.java
@@ -0,0 +1,44 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class PHPEditorMessages {
+
+ private static final String RESOURCE_BUNDLE = "net.sourceforge.phpeclipse.phpeditor.PHPEditorMessages"; //$NON-NLS-1$
+
+ // private static ResourceBundle fgResourceBundle = null;
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ // ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+ private PHPEditorMessages() {
+ // if (fgResourceBundle == null) {
+ // try {
+ // fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
+ // } catch (MissingResourceException x) {
+ // fgResourceBundle = null;
+ // }
+ // }
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!"; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPElement.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPElement.java
new file mode 100644
index 0000000..fde8279
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPElement.java
@@ -0,0 +1,46 @@
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+/**
+ * @author choochter
+ */
+public abstract class PHPElement {
+
+ private String ElementName;
+
+ private String ElementUsage;
+
+ // Setters
+ public final void setName(String ElementName) {
+ this.ElementName = ElementName;
+ }
+
+ public final void setUsage(String usage) {
+ this.ElementUsage = usage;
+ }
+
+ // Getters
+ public final String getName() {
+ return ElementName;
+ }
+
+ public final String getUsage() {
+ return ElementUsage;
+ }
+
+ public String getHoverText() {
+ return "" + getUsage() + "";
+ }
+
+ public PHPElement() {
+ }
+
+ public PHPElement(String name, String usage) {
+ setName(name);
+ if ((usage == null) || (usage.equals(""))) {
+ setUsage(name + " - ");
+ } else {
+ setUsage(usage);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPFunction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPFunction.java
new file mode 100644
index 0000000..2949a27
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPFunction.java
@@ -0,0 +1,29 @@
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+/**
+ * @author Choochter
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>ObfuscatorIgnores. To enable and disable the creation
+ * of type comments go to Window>Preferences>Java>Code Generation.
+ */
+public class PHPFunction extends PHPElement {
+ private String fDescription;
+
+ public void setDescription(String description) {
+ this.fDescription = description;
+ }
+
+ public String getDescription() {
+ return this.fDescription;
+ }
+
+ public String getHoverText() {
+ return super.getHoverText() + "
" + getDescription();
+ }
+
+ public PHPFunction(String Name, String usage, String description) {
+ super(Name, usage);
+ setDescription(description);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPKeyword.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPKeyword.java
new file mode 100644
index 0000000..c710e18
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPKeyword.java
@@ -0,0 +1,29 @@
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+/**
+ * @author Choochter
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>ObfuscatorIgnores. To enable and disable the creation
+ * of type comments go to Window>Preferences>Java>Code Generation.
+ */
+public class PHPKeyword extends PHPElement {
+ // private int tokenval;
+ // public void settokenval(String tokenval) { this.tokenval =
+ // Integer.parseInt(tokenval);}
+ // public void settokenval(int tokenval) { this.tokenval = tokenval;}
+ // public int gettokenval() { return this.tokenval; }
+
+ public PHPKeyword(String Name, String Description) {
+ super(Name, Description);
+ // if ((tokenval == null) || (tokenval.equals("")))
+ // {
+ // //if there is not a tokenval, then not implemented.
+ // settokenval(-1);
+ // }
+ // else {
+ // settokenval(tokenval);
+ // }
+ // settokenval(tokenval);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java
new file mode 100644
index 0000000..0b8409d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java
@@ -0,0 +1,465 @@
+/**********************************************************************
+ Copyright (c) 2002 Widespace, OU and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://solareclipse.sourceforge.net/legal/cpl-v10.html
+
+ Contributors:
+ Igor Malinin - initial contribution
+
+ $Id: PHPPartitionScanner.java,v 1.35 2007-03-17 14:07:31 axelcl Exp $
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpeclipse.ui.text.rules.AbstractPartitioner;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class PHPPartitionScanner implements IPartitionTokenScanner {
+ public static final String PHP_SCRIPTING_AREA = "__php_scripting_area ";
+
+ public static final int STATE_DEFAULT = 0;
+
+ // public static final int STATE_TAG = 1;
+ // public static final int STATE_SCRIPT = 2;
+
+ private IDocument document;
+
+ // private int begin;
+
+ private int end;
+
+ private int offset;
+
+ private int length;
+
+ private int position;
+
+ // private int state;
+
+ private Map tokens = new HashMap();
+
+ public PHPPartitionScanner() {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
+ */
+ public IToken nextToken() {
+ offset += length;
+
+ /*
+ * switch (state) { case STATE_TAG: return nextTagToken(); }
+ */
+
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ // state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '<':
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ // state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '?': //
+ // int ch = read();
+ //
+ // switch (ch) {
+ // case ICharacterScanner.EOF:
+ // state = STATE_DEFAULT;
+ // return getToken(PHP_SCRIPTING_AREA);
+ // }
+ return scanUntilPHPEndToken(PHP_SCRIPTING_AREA);
+ }
+
+ unread();
+ }
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ // state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '<':
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ // state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '?':
+ unread();
+ break;
+
+ case '<':
+ unread();
+
+ default:
+ continue loop;
+ }
+
+ unread();
+
+ // state = STATE_DEFAULT;
+ return getToken(null);
+ }
+ }
+ }
+
+ private IToken scanUntilPHPEndToken(String token) {
+ int ch = read();
+ while (true) {
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ // state = STATE_DEFAULT;
+ return getToken(token);
+ case '"': // double quoted string
+ // read until end of double quoted string
+ if (!readUntilEscapedDQ()) {
+ // state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ break;
+ case '<': // heredoc string
+ ch = read();
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ break;
+ case '<':
+ ch = read();
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ break;
+ case '<':
+ // read until end of heredoc string
+ if (!readUntilEscapedHEREDOC()) {
+ // state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ }
+ }
+ break;
+ case '\'': // single quoted string
+ // read until end of single quoted string
+ if (!readUntilEscapedSQ()) {
+ // state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ break;
+ case '/': // comment start?
+ ch = read();
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ break;
+ case '/':
+ // read until end of line
+ if (!readSingleLine()) {
+ // state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ break;
+ case '*':
+ // read until end of comment
+ if (!readMultiLineComment()) {
+ // state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ break;
+ default:
+ continue;
+ }
+ break;
+ case '#': // line comment
+ // read until end of line
+ if (!readSingleLine()) {
+ // state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ break;
+ case '?':
+ ch = read();
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ case '>':
+ // state = STATE_DEFAULT;
+ return getToken(token);
+
+ case '?':
+ continue;
+ default:
+ continue;
+ }
+ }
+
+ ch = read();
+ }
+ }
+
+ private IToken getToken(String type) {
+ length = position - offset;
+
+ if (length == 0) {
+ return Token.EOF;
+ }
+
+ // if (length<0) {
+ // try {
+ // System.out.println("Length<0:"+document.get(offset,5)+""+length);
+ // } catch (BadLocationException e) {
+ // e.printStackTrace();
+ // }
+ // }
+
+ if (type == null) {
+ return Token.UNDEFINED;
+ }
+
+ IToken token = (IToken) tokens.get(type);
+ if (token == null) {
+ token = new Token(type);
+ tokens.put(type, token);
+ }
+
+ return token;
+ }
+
+ private int read() {
+ if (position >= end) {
+ return ICharacterScanner.EOF;
+ }
+
+ try {
+ return document.getChar(position++);
+ } catch (BadLocationException e) {
+ --position;
+ return ICharacterScanner.EOF;
+ }
+ }
+
+ private boolean readUntilEscapedDQ() {
+ // search last double quoted character
+ try {
+ char ch;
+ while (true) {
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++);
+ if (ch == '\\') {
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++); // ignore escaped
+ // character
+ } else if (ch == '"') {
+ return true;
+ }
+ }
+ } catch (BadLocationException e) {
+ --position;
+ }
+ return false;
+ }
+
+ private boolean readUntilEscapedSQ() {
+ // search last single quoted character
+ try {
+ char ch;
+ while (true) {
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++);
+ if (ch == '\\') {
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++); // ignore escaped
+ // character
+ } else if (ch == '\'') {
+ return true;
+ }
+ }
+ } catch (BadLocationException e) {
+ --position;
+ }
+ return false;
+ }
+
+ private boolean readUntilEscapedHEREDOC() {
+ // search until heredoc ends
+ try {
+ char ch;
+ StringBuffer buf = new StringBuffer();
+ char[] heredocIdent;
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++);
+ // #1493165 start
+ while (ch == ' ') {
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++);
+ }
+ // #1493165 end
+ if (!Scanner.isPHPIdentifierStart(ch)) {
+ return false;
+ }
+ while (Scanner.isPHPIdentifierPart(ch)) {
+ buf.append(ch);
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++);
+ }
+ heredocIdent = buf.toString().toCharArray();
+ while (true) {
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++);
+ if (ch == '\n') { // heredoc could end after a newline
+ int pos = 0;
+ while (true) {
+ if (position >= end) {
+ return false;
+ }
+ if (pos == heredocIdent.length) {
+ return true;
+ }
+ ch = document.getChar(position++); // ignore escaped
+ // character
+ if (ch != heredocIdent[pos]) {
+ break;
+ }
+ pos++;
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ --position;
+ }
+ return false;
+ }
+
+ private boolean readSingleLine() {
+ try {
+ do {
+ if (position >= end) {
+ return false;
+ }
+ } while (document.getChar(position++) != '\n');
+ return true;
+ } catch (BadLocationException e) {
+ --position;
+ }
+ return false;
+ }
+
+ private boolean readMultiLineComment() {
+ try {
+ char ch;
+ while (true) {
+ if (position >= end) {
+ return false;
+ }
+ ch = document.getChar(position++);
+ if (ch == '*') {
+ if (position >= end) {
+ return false;
+ }
+ if (document.getChar(position) == '/') {
+ position++;
+ return true;
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ --position;
+ }
+ return false;
+ }
+
+ private void unread() {
+ --position;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
+ */
+ public int getTokenOffset() {
+ if (AbstractPartitioner.DEBUG) {
+ Assert.isTrue(offset >= 0, Integer.toString(offset));
+ }
+ return offset;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
+ */
+ public int getTokenLength() {
+ return length;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int,
+ * int)
+ */
+ public void setRange(IDocument document, int offset, int length) {
+ this.document = document;
+ // this.begin = offset;
+ this.end = offset + length;
+
+ this.offset = offset;
+ this.position = offset;
+ this.length = 0;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
+ */
+ public void setPartialRange(IDocument document, int offset, int length,
+ String contentType, int partitionOffset) {
+ // state = STATE_DEFAULT;
+ if (partitionOffset > -1) {
+ int delta = offset - partitionOffset;
+ if (delta > 0) {
+ setRange(document, partitionOffset, length + delta);
+ return;
+ }
+ }
+ setRange(document, partitionOffset, length);
+ }
+
+ // private boolean isContinuationPartition(IDocument document, int offset) {
+ // try {
+ // String type = document.getContentType(offset - 1);
+ //
+ // if (type != IDocument.DEFAULT_CONTENT_TYPE) {
+ // return true;
+ // }
+ // } catch (BadLocationException e) {}
+ //
+ // return false;
+ // }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPType.java
new file mode 100644
index 0000000..5b109ee
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPType.java
@@ -0,0 +1,14 @@
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+/**
+ * @author Choochter
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>ObfuscatorIgnores. To enable and disable the creation
+ * of type comments go to Window>Preferences>Java>Code Generation.
+ */
+public class PHPType extends PHPElement {
+ public PHPType(String Name, String Description) {
+ super(Name, Description);
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPWordExtractor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPWordExtractor.java
new file mode 100644
index 0000000..ed9b88c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/PHPWordExtractor.java
@@ -0,0 +1,77 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Detects PHP words in documents.
+ */
+public class PHPWordExtractor {
+
+ /**
+ * Find the location of the word at offset in document.
+ *
+ * @returns Point - x is the start position, y is the end position. Return
+ * null if it is not found.
+ * @param document
+ * the document being searched.
+ * @param offset -
+ * the position to start searching from.
+ */
+ public static Point findWord(IDocument document, int offset) {
+
+ int start = -1;
+ int end = -1;
+
+ try {
+
+ int position = offset;
+ char character;
+
+ while (position >= 0) {
+ character = document.getChar(position);
+ if (!Scanner.isPHPIdentifierPart(character)
+ && (character != '$'))
+ break;
+ --position;
+ }
+
+ start = position;
+
+ position = offset;
+ int length = document.getLength();
+
+ while (position < length) {
+ character = document.getChar(position);
+ if (!Scanner.isPHPIdentifierPart(character)
+ && (character != '$'))
+ break;
+ ++position;
+ }
+
+ start++;
+ end = position;
+
+ if (end > start)
+ return new Point(start, end - start);
+
+ } catch (BadLocationException x) {
+ }
+
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/SmartyCodeScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/SmartyCodeScanner.java
new file mode 100644
index 0000000..ac1aa25
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/SmartyCodeScanner.java
@@ -0,0 +1,182 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPWhitespaceDetector;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPWordDetector;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+
+/**
+ * PHP Code Scanner
+ */
+public class SmartyCodeScanner extends AbstractJavaScanner {
+ public static String[] SMARTY_KEYWORDS = { "capture", "config_load",
+ "else", "elseif", "foreach", "foreachelse", "if", "include",
+ "insert", "ldelim", "literal", "php", "rdelim", "section",
+ "sectionelse", "strip" };
+
+ public static String[] SMARTY_FUNCTION_NAMES = { "assign", "counter",
+ "cycle", "debug", "eval", "fetch", "html_checkboxes", "html_image",
+ "html_options", "html_radios", "html_select_date",
+ "html_select_time", "html_table", "math", "popup", "popup_init",
+ "textformat" };
+
+ private class SmartyWordRule extends WordRule {
+ private StringBuffer fBuffer = new StringBuffer();
+
+ public SmartyWordRule(IWordDetector detector) {
+ super(detector, Token.UNDEFINED);
+ }
+
+ public SmartyWordRule(IWordDetector detector, IToken defaultToken) {
+ super(detector, defaultToken);
+ }
+
+ public IToken evaluate(ICharacterScanner scanner) {
+ int c = scanner.read();
+ boolean isVariable = false;
+ if (c == '{') {
+ c = scanner.read();
+ if (c != '/') {
+ scanner.unread();
+ }
+ return getToken(IPreferenceConstants.PHP_TAG);
+ }
+ if (c == '}') {
+ return getToken(IPreferenceConstants.PHP_TAG);
+ }
+ if (fDetector.isWordStart((char) c)) {
+ if (c == '$') {
+ isVariable = true;
+ }
+ if (fColumn == UNDEFINED
+ || (fColumn == scanner.getColumn() - 1)) {
+
+ fBuffer.setLength(0);
+ do {
+ fBuffer.append((char) c);
+ c = scanner.read();
+ } while (c != ICharacterScanner.EOF
+ && fDetector.isWordPart((char) c));
+ scanner.unread();
+
+ if (isVariable) {
+ return getToken(IPreferenceConstants.PHP_VARIABLE);
+ }
+ IToken token = (IToken) fWords.get(fBuffer.toString());
+ if (token != null)
+ return token;
+
+ if (fDefaultToken.isUndefined())
+ unreadBuffer(scanner);
+
+ return fDefaultToken;
+ }
+ }
+
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+ }
+
+ private static String[] fgTokenProperties = {
+ IPreferenceConstants.PHP_MULTILINE_COMMENT,
+ IPreferenceConstants.PHP_SINGLELINE_COMMENT,
+ IPreferenceConstants.PHP_TAG, IPreferenceConstants.PHP_KEYWORD,
+ IPreferenceConstants.PHP_FUNCTIONNAME,
+ IPreferenceConstants.PHP_VARIABLE,
+ IPreferenceConstants.PHP_VARIABLE_DOLLAR,
+ IPreferenceConstants.PHP_STRING_DQ,
+ IPreferenceConstants.PHP_STRING_SQ, IPreferenceConstants.PHP_TYPE,
+ IPreferenceConstants.PHP_CONSTANT, IPreferenceConstants.PHP_DEFAULT };
+
+ /**
+ * Creates a PHP code scanner
+ */
+ // public PHPCodeScanner(JavaColorManager provider, IPreferenceStore store)
+ // {
+ public SmartyCodeScanner(IColorManager manager, IPreferenceStore store) {
+ super(manager, store);
+ initialize();
+ }
+
+ /*
+ * @see AbstractJavaScanner#getTokenProperties()
+ */
+ protected String[] getTokenProperties() {
+ return fgTokenProperties;
+ }
+
+ /*
+ * @see AbstractJavaScanner#createRules()
+ */
+ protected List createRules() {
+ List rules = new ArrayList();
+ // Add rule for strings and character constants.
+ Token token = getToken(IPreferenceConstants.PHP_STRING_DQ);
+ rules.add(new MultiLineRule("\"", "\"", token, '\\')); //$NON-NLS-2$ //$NON-NLS-1$
+
+ // Add generic whitespace rule.
+ rules.add(new WhitespaceRule(new PHPWhitespaceDetector()));
+ // Add word rule for keywords, types, and constants.
+ token = getToken(IPreferenceConstants.PHP_DEFAULT);
+
+ SmartyWordRule wordRule = new SmartyWordRule(new PHPWordDetector(),
+ token);
+
+ Token keyword = getToken(IPreferenceConstants.PHP_KEYWORD);
+ Token functionName = getToken(IPreferenceConstants.PHP_FUNCTIONNAME);
+ // Token type = getToken(IPreferenceConstants.PHP_TYPE);
+ // Token constant = getToken(IPreferenceConstants.PHP_CONSTANT);
+
+ for (int i = 0; i < SMARTY_KEYWORDS.length; i++) {
+ wordRule.addWord(SMARTY_KEYWORDS[i], keyword);
+ }
+
+ for (int i = 0; i < SMARTY_FUNCTION_NAMES.length; i++) {
+ wordRule.addWord(SMARTY_FUNCTION_NAMES[i], functionName);
+ }
+
+ // ArrayList buffer = PHPSyntaxRdr.getSyntaxData();
+ // PHPElement elbuffer = null;
+ // for (int i = 0; i < buffer.size(); i++) {
+ //
+ // elbuffer = (PHPElement) buffer.get(i);
+ // if (elbuffer instanceof PHPKeyword)
+ // wordRule.addWord(((PHPKeyword) elbuffer).getName(), keyword);
+ // // if (elbuffer instanceof PHPFunction)
+ // // wordRule.addWord(((PHPFunction) elbuffer).getName(),
+ // functionName);
+ // if (elbuffer instanceof PHPType)
+ // wordRule.addWord(elbuffer.getName(), type);
+ // if (elbuffer instanceof PHPConstant)
+ // wordRule.addWord(elbuffer.getName(), constant);
+ // }
+ rules.add(wordRule);
+ setDefaultReturnToken(getToken(IPreferenceConstants.PHP_DEFAULT));
+ return rules;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/SmartyDocCodeScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/SmartyDocCodeScanner.java
new file mode 100644
index 0000000..a483212
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/php/SmartyDocCodeScanner.java
@@ -0,0 +1,180 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.php;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.text.AbstractJavaScanner;
+import net.sourceforge.phpdt.ui.text.IColorManager;
+import net.sourceforge.phpeclipse.IPreferenceConstants;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPWhitespaceDetector;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+
+/**
+ * A rule based SmartyDoc scanner.
+ */
+public final class SmartyDocCodeScanner extends AbstractJavaScanner {
+
+ /**
+ * A key word detector.
+ */
+ static class JavaDocKeywordDetector implements IWordDetector {
+
+ /**
+ * @see IWordDetector#isWordStart
+ */
+ public boolean isWordStart(char c) {
+ return (c == '@');
+ }
+
+ /**
+ * @see IWordDetector#isWordPart
+ */
+ public boolean isWordPart(char c) {
+ return Character.isLetter(c);
+ }
+ };
+
+ /**
+ * Detector for HTML comment delimiters.
+ */
+ static class HTMLCommentDetector implements IWordDetector {
+
+ /**
+ * @see IWordDetector#isWordStart
+ */
+ public boolean isWordStart(char c) {
+ return (c == '<' || c == '-');
+ }
+
+ /**
+ * @see IWordDetector#isWordPart
+ */
+ public boolean isWordPart(char c) {
+ return (c == '-' || c == '!' || c == '>');
+ }
+ };
+
+ class TagRule extends SingleLineRule {
+
+ /*
+ * @see SingleLineRule
+ */
+ public TagRule(IToken token) {
+ super("<", ">", token, (char) 0); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ /*
+ * @see SingleLineRule
+ */
+ public TagRule(IToken token, char escapeCharacter) {
+ super("<", ">", token, escapeCharacter); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ private IToken checkForWhitespace(ICharacterScanner scanner) {
+
+ try {
+
+ char c = getDocument().getChar(getTokenOffset() + 1);
+ if (!Character.isWhitespace(c))
+ return fToken;
+
+ } catch (BadLocationException x) {
+ }
+
+ return Token.UNDEFINED;
+ }
+
+ /*
+ * @see PatternRule#evaluate(ICharacterScanner)
+ */
+ public IToken evaluate(ICharacterScanner scanner) {
+ IToken result = super.evaluate(scanner);
+ if (result == fToken)
+ return checkForWhitespace(scanner);
+ return result;
+ }
+ };
+
+ private static String[] fgKeywords = {
+ "@author", "@deprecated", "@exception", "@link", "@param", "@return", "@see", "@since", "@throws", "@value", "@version", "@license", "@abstract", "@access", "@category",
+ "@copyright", "@example", "@final", "@filesource", "@global", "@ignore", "@internal", "@link", "@method", "@name", "@package", "@param", "@property", "@static",
+ "@staticvar", "@subpackage", "@todo", "@tutorial", "@uses", "@var","@id", "inheritdoc", "@property-read", "@property-write", "@source" }; //$NON-NLS-12$ //$NON-NLS-11$ //$NON-NLS-10$ //$NON-NLS-7$ //$NON-NLS-9$ //$NON-NLS-8$ //$NON-NLS-6$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+
+ private static String[] fgTokenProperties = {
+ IPreferenceConstants.PHPDOC_KEYWORD,
+ IPreferenceConstants.PHPDOC_TAG, IPreferenceConstants.PHPDOC_LINK,
+ IPreferenceConstants.PHPDOC_DEFAULT };
+
+ public SmartyDocCodeScanner(IColorManager manager, IPreferenceStore store) {
+ super(manager, store);
+ initialize();
+ }
+
+ public IDocument getDocument() {
+ return fDocument;
+ }
+
+ /*
+ * @see AbstractJavaScanner#getTokenProperties()
+ */
+ protected String[] getTokenProperties() {
+ return fgTokenProperties;
+ }
+
+ /*
+ * @see AbstractJavaScanner#createRules()
+ */
+ protected List createRules() {
+
+ List list = new ArrayList();
+
+ // Add rule for tags.
+ Token token = getToken(IPreferenceConstants.PHPDOC_TAG);
+ list.add(new TagRule(token));
+
+ // Add rule for HTML comments
+ WordRule wordRule = new WordRule(new HTMLCommentDetector(), token);
+ wordRule.addWord("", token); //$NON-NLS-1$
+ list.add(wordRule);
+
+ // Add rule for links.
+ token = getToken(IPreferenceConstants.PHPDOC_LINK);
+ list.add(new SingleLineRule("{@link", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
+
+ // Add generic whitespace rule.
+ list.add(new WhitespaceRule(new PHPWhitespaceDetector()));
+
+ // Add word rule for keywords.
+ token = getToken(IPreferenceConstants.PHPDOC_DEFAULT);
+ wordRule = new WordRule(new JavaDocKeywordDetector(), token);
+
+ token = getToken(IPreferenceConstants.PHPDOC_KEYWORD);
+ for (int i = 0; i < fgKeywords.length; i++)
+ wordRule.addWord(fgKeywords[i], token);
+ list.add(wordRule);
+
+ setDefaultReturnToken(getToken(IPreferenceConstants.PHPDOC_DEFAULT));
+ return list;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/syntax.xml b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/syntax.xml
new file mode 100644
index 0000000..6eef0eb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/syntax.xml
@@ -0,0 +1,6633 @@
+
+
+Returns the sum of two arbitrary precision numbers
+Compares two arbitrary precision numbers
+Returns the quotient of two arbitrary precision numbers (division)
+Returns the modulus of the two arbitrary precision operands
+Returns the multiplication of two arbitrary precision numbers
+Returns the value of an arbitrary precision number raised to the power of another
+Returns the value of an arbitrary precision number raised to the power of another reduced by a modulous
+Sets default scale parameter for all bc math functions
+Returns the square root of an arbitray precision number
+Returns the difference between two arbitrary precision numbers
+Compresses a string into BZip2 encoded data
+Decompresses BZip2 compressed data
+Returns the error number
+Returns the error number and error string in an associative array
+Returns the error string
+Opens a new BZip2 stream
+Reads up to length bytes from a BZip2 stream, or 1024 bytes if length is not specified
+Convert Julian Day to UNIX timestamp
+Convert UNIX timestamp to Julian Day
+Returns the number of days in a month for a given year and calendar
+Converts from Julian Day Count to a supported calendar and return extended information
+Returns information about a particular calendar
+Converts from a supported calendar to Julian Day Count
+Converts a french republic calendar date to julian day count
+Converts a gregorian calendar date to julian day count
+Returns name or number of day of week from julian day count
+Returns name of month for julian day count
+Converts a julian day count to a french republic calendar date
+Converts a julian day count to a gregorian calendar date
+Converts a julian day count to a jewish calendar date
+Convert a julian day count to a julian calendar date
+Converts a jewish calendar date to a julian day count
+Converts a julian calendar date to julian day count
+Return the timestamp of midnight on Easter of a given year (defaults to current year)
+Return the number of days after March 21 that Easter falls on for a given year (defaults to current year)
+Generate a globally unique identifier (GUID)
+Connect events from a COM object to a PHP object
+Returns a handle to an already running instance of a COM object
+Loads a Typelibrary and registers its constants
+Process COM messages, sleeping for up to timeoutms milliseconds
+Print out a PHP class definition for a dispatchable interface
+Determines the filename into which an object will be saved, or false if none is set, via IPersistFile::GetCurFile
+Gets maximum stream size required to store the object data, via IPersistStream::GetSizeMax (or IPersistStreamInit::GetSizeMax)
+Initializes the object to a default state, via IPersistStreamInit::InitNew
+Load object data from file, via IPersistFile::Load
+Initializes an object from the stream where it was previously saved, via IPersistStream::Load or OleLoadFromStream
+Persist object data to file, via IPersistFile::Save
+Saves the object to a stream, via IPersistStream::Save
+Creates a persistence helper object, usually associated with a com_object
+Returns the absolute value of a variant
+"Adds" two variant values together and returns the result
+performs a bitwise AND operation between two variants and returns the result
+Convert a variant into a new variant object of another type
+concatenates two variant values together and returns the result
+Compares two variants
+Returns a variant date representation of a unix timestamp
+Converts a variant date/time value to unix timestamp
+Returns the result from dividing two variants
+Performs a bitwise equivalence on two variants
+Returns the integer part ? of a variant
+Returns the VT_XXX type code for a variant
+Converts variants to integers and then returns the result from dividing them
+Performs a bitwise implication on two variants
+Returns the integer portion of a variant
+Divides two variants and returns only the remainder
+multiplies the values of the two variants and returns the result
+Performs logical negation on a variant
+Performs bitwise not negation on a variant
+Performs a logical disjunction on two variants
+Returns the result of performing the power function with two variants
+Rounds a variant to the specified number of decimal places
+Assigns a new value for a variant object
+Convert a variant into another type. Variant is modified "in-place"
+subtracts the value of the right variant from the left variant value and returns the result
+Performs a logical exclusion on two variants
+Checks for alphanumeric character(s)
+Checks for alphabetic character(s)
+Checks for control character(s)
+Checks for numeric character(s)
+Checks for any printable character(s) except space
+Checks for lowercase character(s)
+Checks for printable character(s)
+Checks for any printable character which is not whitespace or an alphanumeric character
+Checks for whitespace character(s)
+Checks for uppercase character(s)
+Checks for character(s) representing a hexadecimal digit
+Close a cURL session
+Copy a cURL handle along with all of it's preferences
+Return an integer containing the last error number
+Return a string contain the last error for the current session
+Perform a cURL session
+Get information regarding a specific transfer
+Initialize a cURL session
+Set an option for a cURL transfer
+Set an array of option for a cURL transfer
+Return cURL version information.
+Add a normal cURL handle to a cURL multi handle
+Close a set of cURL handles
+Run the sub-connections of the current cURL handle
+Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set
+Get information about the current transfers
+Returns a new cURL multi handle
+Remove a multi handle from a set of cURL handles
+Get all the sockets associated with the cURL extension, which can then be "selected"
+Returns true(1) if it is a valid date in gregorian calendar
+Format a local date/time
+Returns new DateTime object
+Sets the date.
+Gets the default timezone used by all date/time functions in a script
+Sets the default timezone used by all date/time functions in a script
+Returns date formatted according to given format
+
+Sets the ISO date.
+Alters the timestamp.
+Returns the DST offset.
+Returns associative array with detailed info about given date
+Returns an array with information about sun set/rise and twilight begin/end
+Returns time of sunrise for a given day and location
+Returns time of sunset for a given day and location
+Sets the time.
+Return new DateTimeZone object relative to give DateTime
+Sets the timezone for the DateTime object.
+Get date/time information
+Format a GMT date/time
+Get UNIX timestamp for a GMT date
+Format a GMT/UCT time/date according to locale settings
+Format a local time/date as integer
+Returns the results of the C system call localtime as an associative array if the associative_array argument is set to 1 other wise it is a regular array
+Get UNIX timestamp for a date
+Format a local time/date according to locale settings
+Convert string representation of date and time to a timestamp
+Return current UNIX timestamp
+Creates new DateTime object
+Creates new DateTimeZone object.
+Returns associative array containing dst, offset and the timezone name
+Returns numerically index array with all timezone identifiers.
+Returns the timezone name from abbrevation
+Returns the name of the timezone.
+Returns the timezone offset.
+Returns new DateTimeZone object
+Returns numeracilly indexed array containing associative array for all transitions for the timezone.
+Closes database
+Deletes the entry associated with key If inifile: remove all other key lines
+Checks, if the specified key exists
+Fetches the data associated with key
+Resets the internal key pointer and returns the first key
+List configured database handlers
+If not inifile: Insert value as key, return false, if key exists already If inifile: Add vakue as key (next instance of key)
+List opened databases
+Returns the next key
+Opens path using the specified handler in mode
+Optimizes (e.g. clean up, vacuum) database
+Opens path using the specified handler in mode persistently
+Inserts value as key, replaces key, if key exists already If inifile: remove all other key lines
+Synchronizes database
+Adds a record to the database
+Closes an open dBase-format database file
+Creates a new dBase-format database file
+Marks a record to be deleted
+
+Returns an array representing a record from the database
+Returns an associative array representing a record from the database
+Returns the number of fields (columns) in the database
+Returns the number of records in the database
+Opens a dBase-format database file
+Packs the database (deletes records marked for deletion)
+Replaces a record to the database
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Attr-isId Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-32791A2F Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7C603781 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3EDB695F Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-E5CBA7FB Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6531BCCF Since:
+Register extended class used to create base node type
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-adoptNode Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1084891198 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrAttrNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D26C0AF8 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1334481328 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-35CB04B5 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-2141741547 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrElNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-392B75AE Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-135944439 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1975348127 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBId Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-A6C9094 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBTNNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Core-Document-importNode Since: DOM Level 2
+URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-load Since: DOM Level 3
+Since: DOM extended
+Since: DOM extended
+URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-loadXML Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-normalizeDocument Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-renameNode Since: DOM Level 3
+Convenience method to save to file
+Convenience method to output as html
+Convenience method to save to file as html
+URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-saveXML Since: DOM Level 3
+Since: DOM extended
+Substitutues xincludes in a DomDocument
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMConfiguration-canSetParameter Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMConfiguration-getParameter Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Level-2-Core-DOM-createDocument Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Level-2-Core-DOM-createDocType Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMImplementation3-getFeature Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-5CED94D7 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMImplementationList-item Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-getDOMImpl Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-getDOMImpls Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMStringList-item Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-666EE0F9 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-217A91B8 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElGetAtNodeNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElGetAttrNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1938918D Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-A6C90942 Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElHasAttr Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElHasAttrNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6D6AC0F9 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D589198 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElRemAtNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68F082 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-887236154 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetAtNodeNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetAttrNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttr Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttrNode Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttrNS Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1074577549 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getNamedItemNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-349467F9 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D58B193 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-removeNamedItemNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1025163788 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-setNamedItemNS Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#NameList-getName Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#NameList-getNamespaceURI Since:
+Canonicalize nodes to a string
+Canonicalize nodes to a file
+Gets an xpath for a node
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-184E7107 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3A0ED0A4 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-compareDocumentPosition Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getFeature Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getUserData Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeHasAttrs Since: DOM Level 2
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-810594187 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727 Since:
+URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isDefaultNamespace Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isEqualNode Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isSameNode Since: DOM Level 3
+URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-lookupNamespacePrefix Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-normalize Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1734834066 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-785887307 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-setUserData Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-844377136 Since:
+Get a simplexml_element object from dom to allow for processing
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#i18n-methods-StringExtend-findOffset16 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#i18n-methods-StringExtend-findOffset32 Since:
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Text3-isWhitespaceInElementContent Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Text3-replaceWholeText Since: DOM Level 3
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-38853C1D Since:
+Get the type of an image
+Reads header data from the JPEG/TIFF image filename and optionally reads the internal thumbnails
+Get headername for index or false if not defined
+Reads the embedded thumbnail
+Get the number of rows affected by the last statement
+Turns on auto-commit
+Get the size of a BLOB identified by blob_handle
+Change the user for a session
+Get the size of a CLOB identified by clob_handle
+Close a connection to a database server
+Commit the transaction
+Create a connection to a database server
+Create a BLOB in the database for use with an insert or update statement
+Create a CLOB in the database for use with an insert or update statement
+Create a new database on the server
+Move the internal row counter to the specified row_number
+Get or set the database name used with a connection
+Get or set the databsae password used with a connection
+Send one or more SQL statements to a specified database on the server
+Gets the status (Stopped, Starting, Running, Stopping) for a given database
+Drop a database on the server
+Returns the last error code
+Returns the last error string
+Fetches a result row as an array (associative, numeric or both)
+Detch a row of data. Returns an assoc array
+Get the field properties for a specified field_index
+Returns an array of the lengths of each column in the result set
+Fetch a row of data. Returns an object
+Fetch a row of data. Returns an indexed array
+???
+Get the column length for a specified field_index
+Get the column name for a specified field_index
+???
+Get the table name for a specified field_index
+Get the field type for a specified field_index
+free the memory used to store a result
+???
+Get or set the host name used with a connection
+Get the internal index for the last insert statement
+Retreive a list of all databases on the server
+Retrieve a list of all fields for the specified database.table
+Retreive a list of all tables from the specifoied database
+Switch to the next result if multiple results are available
+Get number of fields in the result set
+Get number of rows
+Get or set the user password used with a connection
+Create a persistant connection to a database server
+Send one or more SQL statements to the server and execute them
+Read the BLOB data identified by blob_handle
+Read the CLOB data identified by clob_handle
+???
+Rollback all statments since last commit
+Get the number of rows affected by the last statement
+Select the database to open
+Change input/output character set
+Sets the mode for how LOB data re retreived (actual data or a handle)
+Change the password for a given user
+Sets the transaction locking and isolation
+Start a database on the server
+Stop a database on the server
+Retreive the table name for index after a call to fbsql_list_tables()
+Get or set the host user used with a connection
+Enable or disable FrontBase warnings
+Add javascript code to the fdf file
+Adds a template into the FDF document
+Closes the FDF document
+Creates a new FDF document
+Call a user defined function for each document value
+Gets error code for last operation
+Gets error description for error code
+Gets the appearance of a field and creates a PDF document out of it.
+Get attached uploaded file
+Gets FDF file encoding scheme
+Gets the value of /F key
+Gets the flags of a field
+Gets a value from the opt array of a field
+Gets the value of /Status key
+Gets the value of a field as string
+Gets version number for FDF api or file
+Set FDF specific HTTP headers
+Gets the name of the next field name or the first field name
+Opens a new FDF document
+Opens a new FDF document from string
+Sets target frame for form
+Writes out the FDF file
+Returns the FDF file as a string
+Sets the appearence of a field
+Sets FDF encoding (either "Shift-JIS" or "Unicode")
+Sets the value of /F key
+Sets flags for a field in the FDF document
+Sets the javascript action for a field
+Adds javascript code to be executed when Acrobat opens the FDF
+Sets a value in the opt array for a field
+Sets the value of /Status key
+Sets the submit form action for a field
+Sets target frame for form
+Sets the value of a field
+Sets FDF version for a file
+* Returns true if the variable with the name 'name' exists in source.
+* Returns the filtered variable 'name'* from source `type`.
+* Returns an array with all arguments defined in 'definition'.
+* Returns the filtered version of the vriable.
+* Returns an array with all arguments defined in 'definition'.
+* Returns the filter ID belonging to a named filter
+Attempt to allocate space on the remote FTP server
+Changes to the parent directory
+Changes directories
+Sets permissions on a file
+Closes the FTP stream
+Opens a FTP stream
+Deletes a file
+Requests execution of a program on the FTP server
+Retrieves a file from the FTP server and writes it to an open file
+Stores a file from an open file to the FTP server
+Retrieves a file from the FTP server and writes it to a local file
+Gets an FTP option
+Logs into the FTP server
+Returns the last modification time of the file, or -1 on error
+Creates a directory and returns the absolute path for the new directory or false on error
+Continues retrieving/sending a file nbronously
+Retrieves a file from the FTP server asynchronly and writes it to an open file
+Stores a file from an open file to the FTP server nbronly
+Retrieves a file from the FTP server nbhronly and writes it to a local file
+Stores a file on the FTP server
+Returns an array of filenames in the given directory
+Turns passive mode on or off
+Stores a file on the FTP server
+Returns the present working directory
+Sends a literal command to the FTP server
+Returns a detailed listing of a directory as an array of output lines
+Renames the given file to a new path
+Removes a directory
+Sets an FTP option
+Sends a SITE command to the server
+Returns the size of the file, or -1 on error
+Opens a FTP-SSL stream
+Returns the system type identifier
+
+Output WBMP image to browser or file
+Turn alpha blending mode on or off for the given image
+Should antialiased functions used or not
+Draw a partial ellipse
+Draw a character
+Draw a character rotated 90 degrees counter-clockwise
+Allocate a color for an image
+Allocate a color with an alpha level. Works for true color and palette based images
+Get the index of the color of a pixel
+Get the index of the closest color to the specified color
+Find the closest matching colour with alpha transparency
+Get the index of the color which has the hue, white and blackness nearest to the given color
+De-allocate a color for an image
+Get the index of the specified color
+Find exact match for colour with transparency
+Makes the colors of the palette version of an image more closely match the true color version
+Get the index of the specified color or its closest possible alternative
+Resolve/Allocate a colour with an alpha level. Works for true colour and palette based images
+Set the color for the specified palette index
+Get the colors for an index
+Find out the number of colors in an image's palette
+Define a color as transparent
+Apply a 3x3 convolution matrix, using coefficient div and offset
+Copy part of an image
+Merge one part of an image with another
+Merge one part of an image with another
+Copy and resize part of an image using resampling to help ensure clarity
+Copy and resize part of an image
+Create a new image
+Create a new image from GD file or URL
+Create a new image from GD2 file or URL
+Create a new image from a given part of GD2 file or URL
+Create a new image from GIF file or URL
+Create a new image from JPEG file or URL
+Create a new image from PNG file or URL
+Create a new image from the image stream in the string
+Create a new image from WBMP file or URL
+Create a new image from XBM file or URL
+Create a new image from XPM file or URL
+Create a new true color image
+Draw a dashed line
+Destroy an image
+Draw an ellipse
+Flood fill
+Draw a filled partial ellipse
+Draw an ellipse
+Draw a filled polygon
+Draw a filled rectangle
+Flood fill to specific color
+Applies Filter an image using a custom angle
+Get font height
+Get font width
+Give the bounding box of a text using fonts via freetype2
+Write text to the image using fonts via freetype2
+Apply a gamma correction to a GD image
+Output GD image to browser or file
+Output GD2 image to browser or file
+Output GIF image to browser or file
+Grab a screenshot
+Grab a window or its client area using a windows handle (HWND property in COM instance)
+Enable or disable interlace
+return true if the image uses truecolor
+Output JPEG image to browser or file
+Set the alpha blending flag to use the bundled libgd layering effects
+Draw a line
+Load a new font
+Copy the palette from the src image onto the dst image
+Output PNG image to browser or file
+Draw a polygon
+Return the bounding box needed by a string if rasterized
+Make a copy of a font for purposes like extending or reenconding
+To change a fonts character encoding vector
+Extend or or condense (if extend < 1) a font
+Free memory used by a font
+Load a new font from specified file
+Slant a font
+Rasterize a string over an image
+Draw a rectangle
+Rotate an image using a custom angle
+Include alpha channel to a saved image
+Set the brush image to $brush when filling $image with the "IMG_COLOR_BRUSHED" color
+Set a single pixel
+Set the line drawing styles for use with imageline and IMG_COLOR_STYLED.
+Set line thickness for drawing lines, ellipses, rectangles, polygons etc.
+Set the tile image to $tile when filling $image with the "IMG_COLOR_TILED" color
+Draw a string horizontally
+Draw a string vertically - rotated 90 degrees counter-clockwise
+Get image width
+Get image height
+Convert a true colour image to a palette based image with a number of colours, optionally using dithering.
+Give the bounding box of a text using TrueType fonts
+Write text to the image using a TrueType font
+Return the types of images supported in a bitfield - 1=GIF, 2=JPEG, 4=PNG, 8=WBMP, 16=XPM
+Output WBMP image to browser or file
+Output XBM image to browser or file
+Bind to the text domain domain_name, looking for translations in dir. Returns the current domain
+Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist
+Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist
+Return the translation of msgid for the current domain, or msgid unaltered if a translation does not exist
+Plural version of gettext()
+Set the textdomain to "domain". Returns the current domain
+Calculates absolute value
+Add a and b
+Calculates logical AND of a and b
+Clears bit in a
+Compares two numbers
+Calculates one's complement of a
+Divide a by b, returns quotient only
+Divide a by b, returns quotient and reminder
+Divide a by b, returns reminder only
+Divide a by b using exact division algorithm
+Calculates factorial function
+Computes greatest common denominator (gcd) of a and b
+Computes G, S, and T, such that AS + BT = G = `gcd' (A, B)
+Calculates hamming distance between a and b
+Initializes GMP number
+Gets signed long value of GMP number
+Computes the inverse of a modulo b
+Computes Jacobi symbol
+Computes Legendre symbol
+Computes a modulo b
+Multiply a and b
+Negates a number
+Finds next prime of a
+Calculates logical OR of a and b
+Checks if a is an exact square
+Calculates the population count of a
+Raise base to power exp
+Raise base to power exp and take result modulo mod
+Checks if a is "probably prime"
+Gets random number
+Finds first zero bit
+Finds first non-zero bit
+Sets or clear bit in a
+Gets the sign of the number
+Takes integer part of square root of a
+Square root with remainder
+Gets string representation of GMP number
+Subtract b from a
+Tests if bit is set in a
+Calculates logical exclusive OR of a and b
+Generate a hash of a given input string Returns lowercase hexits by default
+Return a list of registered hashing algorithms
+Generate a hash of a given file Returns lowercase hexits by default
+Output resulting digest
+Generate a hash of a given input string with a key using HMAC Returns lowercase hexits by default
+Generate a hash of a given file with a key using HMAC Returns lowercase hexits by default
+Initialize a hashing context
+Pump data into the hashing algorithm
+Pump data into the hashing algorithm from a file
+Pump data into the hashing algorithm from an open stream
+Returns str converted to the out_charset character set
+Get internal encoding and output encoding for ob_iconv_handler()
+Decodes a mime header field
+Decodes multiple mime header fields
+Composes a mime header field with field_name and field_value in a specified scheme
+Sets internal encoding and output encoding for ob_iconv_handler()
+Returns the character count of str
+Finds position of first occurrence of needle within part of haystack beginning with offset
+Finds position of last occurrence of needle within part of haystack beginning with offset
+Returns specified part of a string
+Convert an 8-bit string to a quoted-printable string
+Returns an array of all IMAP alerts that have been generated since the last page load or since the last imap_alerts() call, whichever came last. The alert stack is cleared after imap_alerts() is called.
+Append a new message to a specified mailbox
+Decode BASE64 encoded text
+Convert an 8bit string to a base64 string
+Read the message body
+Read the structure of a specified body section of a specific message
+Get mailbox properties
+Clears flags on messages
+Close an IMAP stream
+Create a new mailbox
+Mark a message for deletion
+Delete a mailbox
+Returns an array of all IMAP errors generated since the last page load, or since the last imap_errors() call, whichever came last. The error stack is cleared after imap_errors() is called.
+Permanently delete all messages marked for deletion
+Read an overview of the information in the headers of the given message sequence
+Get a specific body section
+Get the full unfiltered header for a message
+Read the full structure of a message
+Returns the quota set to the mailbox account qroot
+Returns the quota set to the mailbox account mbox
+Gets the ACL for a given mailbox
+Reads the list of mailboxes and returns a full array of objects containing name, attributes, and delimiter
+Return a list of subscribed mailboxes, in the same format as imap_getmailboxes()
+Read the headers of the message
+Returns headers for all messages in a mailbox
+Returns the last error that was generated by an IMAP function. The error stack is NOT cleared after this call.
+Read the list of mailboxes
+Return a list of subscribed mailboxes
+Send an email message
+Create a MIME message based on given envelope and body sections
+Copy specified message to a mailbox
+Move specified message to a mailbox
+Returns info about the current mailbox
+Decode mime header element in accordance with RFC 2047 and return array of objects containing 'charset' encoding and decoded 'text'
+Get the sequence number associated with a UID
+Gives the number of messages in the current mailbox
+Gives the number of recent messages in current mailbox
+Open an IMAP stream to a mailbox
+Check if the IMAP stream is still active
+Convert a quoted-printable string to an 8-bit string
+Rename a mailbox
+Reopen an IMAP stream to a new mailbox
+Parses an address string
+Parse a set of mail headers contained in a string, and return an object similar to imap_headerinfo()
+Returns a properly formatted email address given the mailbox, host, and personal info
+Save a specific body section to a file
+Read list of mailboxes containing a certain string
+Return a list of messages matching the given criteria
+Will set the quota for qroot mailbox
+Sets the ACL for a given mailbox
+Sets flags on messages
+Sort an array of message headers, optionally including only messages that meet specified criteria.
+Get status info from a mailbox
+Subscribe to a mailbox
+Return threaded by REFERENCES tree
+Set or fetch imap timeout
+Get the unique message id associated with a standard sequential message number
+Remove the delete flag from a message
+Unsubscribe from a mailbox
+Decode a modified UTF-7 string
+Encode a string in modified UTF-7
+Convert a mime-encoded text to UTF-8
+Add data into created blob
+Cancel creating blob
+Close blob
+Create blob for adding data
+Output blob contents to browser
+Get len bytes data from open blob
+Create blob, copy file in it, and close it
+Return blob length and other useful info
+Open blob for retrieving data parts
+Frees the event handler set by ibase_set_event_handler()
+Register the callback for handling each of the named events
+Waits for any one of the passed Interbase events to be posted by the database, and returns its name
+Returns the number of rows affected by the previous INSERT, UPDATE or DELETE statement
+Execute a previously prepared query
+Fetch a row from the results of a query
+Fetch a object from the results of a query
+Fetch a row from the results of a query
+Get information about a field
+Free memory used by a query
+Free the memory used by a result
+Assign a name to a result for use with ... WHERE CURRENT OF <name> statements
+Get the number of fields in result
+Get the number of params in a prepared query
+Return the number of rows that are available in a result
+Get information about a parameter
+Prepare a query for later execution
+Execute a query
+Add a user to security database
+Initiates a backup task in the service manager and returns immediately
+Request statistics about a database
+Delete a user from security database
+Execute a maintenance command on the database server
+Modify a user in security database
+Initiates a restore task in the service manager and returns immediately
+Request information about a database server
+Connect to the service manager
+Disconnect from the service manager
+Close an InterBase connection
+Commit transaction
+Commit transaction and retain the transaction context
+Open a connection to an InterBase database
+Drop an InterBase database
+Return error code
+Return error message
+Increments the named generator and returns its new value
+Open a persistent connection to an InterBase database
+Rollback transaction
+Rollback transaction and retain the transaction context
+Start a transaction over one or several databases
+Decodes the JSON representation into a PHP value
+Returns the JSON representation of a value
+Translate 8859 characters to t61 characters
+Add entries to LDAP directory
+Bind to LDAP directory
+Determine if an entry has a specific value for one of its attributes
+Connect to an LDAP server
+Count the number of entries in a search result
+Delete an entry from a directory
+Convert DN to User Friendly Naming format
+Convert error number to error string
+Get the current ldap error number
+Get the current ldap error string
+Splits DN into its component parts
+Return first attribute
+Return first result id
+Return first reference
+Free result memory
+Get attributes from a search result entry
+Get the DN of a result entry
+Get all result entries
+Get the current value of various session-wide parameters
+Get all values with lengths from a result entry
+Single-level search
+Add attribute values to current
+Delete attribute values
+Replace attribute values with new ones
+Get the next attribute in result
+Get next result entry
+Get next reference
+Extract information from reference entry
+Extract information from result
+Read an entry
+Bind to LDAP directory using SASL
+Search LDAP tree under base_dn
+Set the value of various session-wide parameters
+Set a callback function to do re-binds on referral chasing.
+Sort LDAP result entries
+Start TLS
+Translate t61 characters to 8859 characters
+Unbind from LDAP directory
+Clear last error from libxml
+Retrieve array of errors
+Retrieve last error from libxml
+Set the streams context for the next libxml document load or write
+Disable libxml errors and allow user to fetch error information as needed
+Check if the string is valid for the specified encoding
+Returns a case-folded version of sourcestring
+Returns converted string in desired encoding
+Conversion between full-width character and half-width character (Japanese)
+Converts the string resource in variables to desired encoding
+Decodes the MIME "encoded-word" in the string
+Converts HTML numeric entities to character code
+Encodings of the given string is returned (as a string)
+Converts the string to MIME "encoded-word" in the format of =?charset?(B|Q)?encoded_string?=
+Converts specified characters to HTML numeric entities
+Returns the current settings of mbstring
+Returns the input encoding
+Sets the current output_encoding or returns the current output_encoding as a string
+Sets the current internal encoding or Returns the current internal encoding as a string
+Sets the current language or Returns the current language as a string
+Returns an array of all supported entity encodings or Returns the entity encoding as a string
+Returns an array of all supported alias encodings
+Returns an array or string of all supported mime names
+Returns string in output buffer converted to the http_output encoding
+Parses GET/POST/COOKIE data and sets global variables
+Return the preferred MIME name (charset) as a string
+* Sends an email message with MIME scheme
+Returns part of a string
+Trim the string in terminal width
+Finds position of first occurrence of a string within another, case insensitive
+Finds first occurrence of a string within another, case insensitive
+Get character numbers of a string
+Find position of first occurrence of a string within another
+Finds the last occurrence of a character in a string within another
+Finds the last occurrence of a character in a string within another, case insensitive
+Finds position of last occurrence of a string within another, case insensitive
+Find position of last occurrence of a string within another
+Finds first occurrence of a string within another
+* Returns a lowercased version of sourcestring
+* Returns a uppercased version of sourcestring
+Gets terminal width of a string
+Sets the current substitute_character or returns the current substitute_character
+Returns part of a string
+Count the number of substring occurrences
+Regular expression match for multibyte string
+Regular expression match for multibyte string
+Replace regular expression for multibyte string
+Regular expression search for multibyte string
+Get search start position
+Get matched substring of the last time
+Initialize string and regular expression for search.
+Regular expression search for multibyte string
+Regular expression search for multibyte string
+Set search start position
+Case-insensitive regular expression match for multibyte string
+Case insensitive replace regular expression for multibyte string
+Returns the current encoding for regex as a string.
+Set or get the default options for mbregex functions
+split multibyte string into array by regular expression
+CBC crypt/decrypt data using key key with cipher cipher starting with iv
+CFB crypt/decrypt data using key key with cipher cipher starting with iv
+Create an initialization vector (IV)
+OFB crypt/decrypt data using key key with cipher cipher starting with iv
+ECB crypt/decrypt data using key key with cipher cipher starting with iv
+Returns the name of the algorithm specified by the descriptor td
+Returns the block size of the cipher specified by the descriptor td
+Returns the size of the IV in bytes of the algorithm specified by the descriptor td
+Returns the maximum supported key size in bytes of the algorithm specified by the descriptor td
+Returns the name of the mode specified by the descriptor td
+This function decrypts the crypttext
+Returns TRUE if the alrogithm is a block algorithms
+Returns TRUE if the mode is for use with block algorithms
+Returns TRUE if the mode outputs blocks
+This function runs the self test on the algorithm specified by the descriptor td
+OFB crypt/decrypt data using key key with cipher cipher starting with iv
+This function encrypts the plaintext
+This function terminates encrypt specified by the descriptor td
+This function initializes all buffers for the specific module
+Get the key size of cipher
+Get the name of cipher
+Get the IV size of cipher (Usually the same as the blocksize)
+Get the key size of cipher
+List all algorithms in "module_dir"
+List all modes "module_dir"
+Free the descriptor td
+Returns the block size of the algorithm
+Returns the maximum supported key size of the algorithm
+This function decrypts the crypttext
+Returns TRUE if the algorithm is a block algorithm
+Returns TRUE if the mode is for use with block algorithms
+Returns TRUE if the mode outputs blocks of bytes
+Opens the module of the algorithm and the mode to be used
+Does a self test of the module "module"
+OFB crypt/decrypt data using key key with cipher cipher starting with iv
+This function decrypts the plaintext
+Hash data with hash
+Gets the number of available hashes
+Gets the block size of hash
+Gets the name of hash
+Get the name of the keygen algorithm
+Get the required size of the salt for the keygen algorithm
+Generate a key
+Get the number of available keygen algorithms
+Generates a key using hash functions
+Whether the keygen algorithm uses the bytes_count parameter
+Whether the keygen algorithm uses a hash algorithm
+Whether the keygen algorithm requires a salt
+Return content-type for file
+Returns the action flag for keyPress(char)
+Set scale (?)
+Use constant pool (?)
+Use SWF version (?)
+Creates a new SWFAction object, compiling the given script
+Creates a new SWFBitmap object from jpg (with optional mask) or dbl file
+Returns the height of this bitmap
+Returns the width of this bitmap
+Creates a new SWFButton object
+associates a sound with a button transition NOTE: the transitions are all wrong _UP, _OVER, _DOWN _HIT
+Sets the action to perform when conditions described in flags is met
+Sets the character to display for the condition described in flags
+Sets the action to perform when button is pressed
+Sets the character for this button's down state
+Sets the character for this button's hit test state
+enable track as menu button behaviour
+Sets the character for this button's over state
+Sets the character for this button's up state
+Adds this SWFAction to the given SWFSprite instance
+Sets the add color part of this SWFDisplayItem's CXform to (r, g, b [, a]), a defaults to 0
+another way of defining a MASK layer
+Displaces this SWFDisplayItem by (dx, dy) in movie coordinates
+Moves this SWFDisplayItem to movie coordinates (x, y)
+Sets the multiply color part of this SWFDisplayItem's CXform to (r, g, b [, a]), a defaults to 1.0
+Rotates this SWFDisplayItem the given (clockwise) degrees from its current orientation
+Rotates this SWFDisplayItem the given (clockwise) degrees from its original orientation
+Multiplies this SWFDisplayItem's current x scale by xScale, its y scale by yScale
+Scales this SWFDisplayItem by xScale in the x direction, yScale in the y, or both to xScale if only one arg
+Sets this SWFDisplayItem's z-depth to depth. Items with higher depth values are drawn on top of those with lower values
+defines a MASK layer at level
+Sets the item's transform matrix
+Sets this SWFDisplayItem's name to name
+Sets this SWFDisplayItem's ratio to ratio. Obviously only does anything if displayitem was created from an SWFMorph
+Adds xSkew to this SWFDisplayItem's x skew value
+Sets this SWFDisplayItem's x skew value to xSkew
+Adds ySkew to this SWFDisplayItem's y skew value
+Sets this SWFDisplayItem's y skew value to ySkew
+Creates a new SWFFill object
+Moves this SWFFill to shape coordinates (x,y)
+Rotates this SWFFill the given (clockwise) degrees from its original orientation
+Scales this SWFFill by xScale in the x direction, yScale in the y, or both to xScale if only one arg
+Sets this SWFFill's x skew value to xSkew
+Sets this SWFFill's y skew value to ySkew
+Creates a new SWFFont object from given file
+adds characters to a font required within textfields
+Returns the ascent of the font, or 0 if not available
+Returns the descent of the font, or 0 if not available
+Returns the leading of the font, or 0 if not available
+Returns the glyph shape of a char as a text string
+Calculates the width of the given string in this font at full height
+Calculates the width of the given string in this font at full height
+Calculates the width of the given string in this font at full height
+adds characters to a font for exporting font
+adds characters to a font for exporting font
+Creates a new SWFGradient object
+Adds given entry to the gradient
+Creates a new SWFMorph object
+Return's this SWFMorph's start shape object
+Return's this SWFMorph's start shape object
+Creates swfmovie object according to the passed version
+
+Labels frame
+
+
+
+
+
+Saves the movie. 'where' can be stream and the movie will be saved there otherwise it is treated as string and written in file with that name
+
+Sets background color (r,g,b)
+Sets movie dimension
+Sets number of frames
+Sets movie rate
+Sets sound stream of the SWF movie. The parameter can be stream or string. Retuens the number of frames.
+Returns a SWFPrebuiltClip object
+Creates a new SWFShape object
+Returns a fill object, for use with swfshape_setleftfill and swfshape_setrightfill. If 1 or 2 parameter(s) is (are) passed first should be object (from gradient class) and the second int (flags). Gradient fill is performed. If 3 or 4 parameters are passed : r, g, b [, a]. Solid fill is performed.
+Draws an arc of radius r centered at the current location, from angle startAngle to angle endAngle measured clockwise from 12 o'clock
+Draws a circle of radius r centered at the current location, in a counter-clockwise fashion
+Draws a cubic bezier curve using the current position and the three given points as control points
+Draws a cubic bezier curve using the current position and the three given points as control points
+Draws a curve from the current pen position (x, y) to the point (x+bdx, y+bdy) in the current line style, using point (x+adx, y+ady) as a control point or draws a cubic bezier to point (x+cdx, x+cdy) with control points (x+adx, y+ady) and (x+bdx, y+bdy)
+Draws a curve from the current pen position (x,y) to the point (bx, by) in the current line style, using point (ax, ay) as a control point. Or draws a cubic bezier to point (dx, dy) with control points (ax, ay) and (bx, by)
+Draws the first character in the given string into the shape using the glyph definition from the given font
+Draws a line from the current pen position (x, y) to the point (x+dx, y+dy) in the current line style
+Draws a line from the current pen position to shape coordinates (x, y) in the current line style
+Moves the pen from its current location by vector (x, y)
+Moves the pen to shape coordinates (x, y)
+Sets the left side fill style to fill in case only one parameter is passed. When 3 or 4 parameters are passed they are treated as : int r, int g, int b, int a . Solid fill is performed in this case before setting left side fill type.
+Sets the right side fill style to fill in case only one parameter is passed. When 3 or 4 parameters are passed they are treated as : int r, int g, int b, int a . Solid fill is performed in this case before setting right side fill type.
+Sets the current line style for this SWFShape
+Creates a new SWFSound object from given file
+Creates a new SWFSprite object
+Adds the character to the sprite, returns a displayitem object
+Labels frame
+Moves the sprite to the next frame
+Remove the named character from the sprite's display list
+Sets the number of frames in this SWFSprite
+Creates new SWFText object
+Writes the given text into this SWFText object at the current pen position, using the current font, height, spacing, and color
+Writes the given text into this SWFText object at the current pen position, using the current font, height, spacing, and color
+Writes the given text into this SWFText object at the current pen position, using the current font, height, spacing, and color
+Returns the ascent of the current font at its current size, or 0 if not available
+Returns the descent of the current font at its current size, or 0 if not available
+Returns the leading of the current font at its current size, or 0 if not available
+calculates the width of the given string in this text objects current font and size
+calculates the width of the given string in this text objects current font and size
+Calculates the width of the given string in this text objects current font and size
+Moves this SWFText object's current pen position to (x, y) in text coordinates
+Sets this SWFText object's current color to the given color
+Sets this SWFText object's current font to given font
+Sets this SWFText object's current height to given height
+Sets this SWFText object's current letterspacing to given spacing
+Creates a new SWFTextField object
+adds characters to a font that will be available within a textfield
+Adds the given string to this textfield
+Sets the alignment of this textfield
+Sets the width and height of this textfield
+Sets the color of this textfield
+Sets the font for this textfield
+Sets the font height of this textfield
+Sets the indentation of the first line of this textfield
+Sets the left margin of this textfield
+Sets the line spacing of this textfield
+Sets both margins of this textfield
+Sets the variable name of this textfield
+Sets the padding of this textfield
+Sets the right margin of this textfield
+Returns a SWVideoStream object
+Return number of affected rows
+Close an mSQL connection
+Open a connection to an mSQL Server
+Create an mSQL database
+Move internal result pointer
+Send an SQL query to mSQL
+Drop (delete) an mSQL database
+Returns the text of the error message from previous mSQL operation
+Fetch a result row as an associative array
+Get column information from a result and return as an object
+Fetch a result row as an object
+Get a result row as an enumerated array
+Get the flags associated with the specified field in a result
+Returns the length of the specified field
+Get the name of the specified field in a result
+Set result pointer to a specific field offset
+Get name of the table the specified field is in
+Get the type of the specified field in a result
+Free result memory
+List databases available on an mSQL server
+List mSQL result fields
+List tables in an mSQL database
+Get number of fields in a result
+Get number of rows in a result
+Open a persistent connection to an mSQL Server
+Send an SQL query to mSQL
+Get result data
+Select an mSQL database
+Adds a parameter to a stored procedure or a remote stored procedure
+Closes a connection to a MS-SQL server
+Establishes a connection to a MS-SQL server
+Moves the internal row pointer of the MS-SQL result associated with the specified result identifier to pointer to the specified row number
+Executes a stored procedure on a MS-SQL server database
+Returns an associative array of the current row in the result set specified by result_id
+Returns an associative array of the current row in the result set specified by result_id
+Returns the next batch of records
+Gets information about certain fields in a query result
+Returns a psuedo-object of the current row in the result set specified by result_id
+Returns an array of the current row in the result set specified by result_id
+Get the length of a MS-SQL field
+Returns the name of the field given by offset in the result set given by result_id
+Seeks to the specified field offset
+Returns the type of a field
+Free a MS-SQL result index
+Free a MS-SQL statement index
+Gets the last message from the MS-SQL server
+Converts a 16 byte binary GUID to a string
+Initializes a stored procedure or a remote stored procedure
+Sets the lower error severity
+Sets the lower message severity
+Move the internal result pointer to the next result
+Returns the number of fields fetched in from the result id specified
+Returns the number of rows fetched in from the result id specified
+Establishes a persistent connection to a MS-SQL server
+Perform an SQL query on a MS-SQL server database
+Returns the contents of one cell from a MS-SQL result set
+Returns the number of records affected by the query
+Select a MS-SQL database
+Gets number of affected rows in previous MySQL operation
+Returns the default character set for the current connection
+Close a MySQL connection
+Opens a connection to a MySQL Server
+Create a MySQL database
+Move internal result pointer
+Sends an SQL query to MySQL
+Drops (delete) a MySQL database
+Returns the number of the error message from previous MySQL operation
+Returns the text of the error message from previous MySQL operation
+Escape string for mysql query
+Fetch a result row as an array (associative, numeric or both)
+Fetch a result row as an associative array
+Gets column information from a result and return as an object
+Gets max data size of each column in a result
+Fetch a result row as an object
+Gets a result row as an enumerated array
+Gets the flags associated with the specified field in a result
+Returns the length of the specified field
+Gets the name of the specified field in a result
+Sets result pointer to a specific field offset
+Gets name of the table the specified field is in
+Gets the type of the specified field in a result
+Free result memory
+Returns a string that represents the client library version
+Returns a string describing the type of connection in use, including the server host name
+Returns the protocol version used by current connection
+Returns a string that represents the server version number
+Returns a string containing information about the most recent query
+Gets the ID generated from the previous INSERT operation
+List databases available on a MySQL server
+List MySQL result fields
+Returns a result set describing the current server threads
+List tables in a MySQL database
+Gets number of fields in a result
+Gets number of rows in a result
+Opens a persistent connection to a MySQL Server
+Ping a server connection. If no connection then reconnect.
+Sends an SQL query to MySQL
+Escape special characters in a string for use in a SQL statement, taking into account the current charset of the connection
+Gets result data
+Selects a MySQL database
+sets client character set
+Returns a string containing status information
+Returns the thread id of current connection
+Sends an SQL query to MySQL, without fetching and buffering the result rows
+Get number of affected rows in previous MySQL operation
+Turn auto commit on or of
+Change logged-in user of the active connection
+Returns the name of the character set used for this connection
+Close connection
+Commit outstanding actions and close transaction
+Move internal result pointer
+
+
+Returns the numerical value of the error message from previous MySQL operation
+Returns the text of the error message from previous MySQL operation
+Fetch the number of fields returned by the last query for the given link
+Set result pointer to a specified field offset
+Get current field offset of result pointer
+Free query result memory for the given result handle
+Get MySQL client info
+Get MySQL client info
+Get MySQL protocol information
+Get MySQL server info
+Return the MySQL version for the server referenced by the given link
+Get information about the most recent query
+Initialize mysqli and return a resource for use with mysql_real_connect
+Get the ID generated from the previous INSERT operation
+Kill a mysql process on the server
+check if there any more query results from a multi query
+read next result from multi_query
+Get number of fields in result
+Get number of rows in result
+Set options
+Ping a server connection or reconnect if there is no connection
+Prepare a SQL statement for execution
+Open a connection to a mysql server
+Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection
+Binary-safe version of mysql_query()
+Undo actions from current transaction
+Select a MySQL database
+unsets user defined handler for load local infile command
+Set callback functions for LOAD DATA LOCAL INFILE
+Returns the SQLSTATE error from previous MySQL operation
+
+Get current system status
+Return the number of rows affected in the last query for the given link
+
+
+Bind variables to a prepared statement as parameters
+Bind variables to a prepared statement for result storage
+Close statement
+Move internal result pointer
+
+
+Execute a prepared statement
+Fetch results from a prepared statement into the bound variables
+Return the number of result columns for the given statement
+Free stored result memory for the given statement handle
+Initialize statement object
+Get the ID generated from the previous INSERT operation
+Return the number of rows in statements result set
+Return the number of parameter for the given statement
+prepare server side statement with query
+reset a prepared statement
+return result set from statement
+
+
+
+Buffer result set on client
+Return the current thread ID
+Return whether thread safety is given or not
+Directly retrieve query results - do not buffer results on client side
+
+initialize and start embedded server
+Open a connection to a mysql server
+Returns the numerical value of the error message from last connect command
+Returns the text of the error message from previous MySQL operation
+returns a character set object
+allows to execute multiple queries
+sets client character set
+
+
+
+
+Enforce execution of a query on the master in a master/slave setup
+
+
+
+
+Enforce execution of a query on a slave in a master/slave setup
+sets report level
+Bind a PHP array to an Oracle PL/SQL type by name
+Bind a PHP variable to an Oracle placeholder by name
+Cancel reading from a cursor
+Disconnect from database
+Append an object to the collection
+Assign a collection from another existing collection
+Assign element val to collection at index ndx
+Retrieve the value at collection index ndx
+Return the max value of a collection. For a varray this is the maximum length of the array
+Return the size of a collection
+Trim num elements from the end of a collection
+Commit the current context
+Connect to an Oracle database and log on. Returns a new session.
+Define a PHP variable to an Oracle column by name
+Return the last error of stmt|connection|global. If no error happened returns false.
+Execute a parsed statement
+Prepare a new row of data for reading
+Fetch all rows of result data into an array
+Fetch a result row as an array
+Fetch a result row as an associative array
+Fetch a result row as an object
+Fetch a result row as an enumerated array
+Tell whether a column is NULL
+Tell the name of a column
+Tell the precision of a column
+Tell the scale of a column
+Tell the maximum data size of a column
+Tell the data type of a column
+Tell the raw oracle data type of a column
+Deletes collection object
+Deletes large object description
+Free all resources associated with a statement
+Toggle internal debugging output for the OCI extension
+Appends data from a LOB to another LOB
+Closes lob descriptor
+Copies data from a LOB to another LOB
+Checks if EOF is reached
+Erases a specified portion of the internal LOB, starting at a specified offset
+Writes a large object into a file
+Flushes the LOB buffer
+Loads file into a LOB
+Tests to see if two LOB/FILE locators are equal
+Loads a large object
+Reads particular part of a large object
+Rewind pointer of a LOB
+Saves a large object
+Moves the pointer of a LOB
+Returns size of a large object
+Tells LOB pointer position
+Truncates a LOB
+Writes data to current position of a LOB
+Writes temporary blob
+Initialize a new collection
+Connect to an Oracle database and log on. Returns a new session.
+Return a new cursor (Statement-Handle) - use this to bind ref-cursors!
+Initialize a new empty descriptor LOB/FILE (LOB is default)
+Return the number of result columns in a statement
+Return the row count of an OCI statement
+Parse a query and return a statement
+Changes the password of an account
+Connect to an Oracle database using a persistent connection and log on. Returns a new session.
+Return a single column of result data
+Rollback the current context
+Return a string containing server version information
+Sets the number of rows to be prefetched on execute to prefetch_rows for stmt
+Return the query type of an OCI statement
+Fetch a row of result data into an array
+Returns current state of buffering for a LOB
+Enables/disables buffering for a LOB
+
+
+
+
+
+
+
+
+
+
+
+
+Toggle autocommit mode or get status
+Handle binary column data
+Close an ODBC connection
+Close all ODBC connections
+Returns a result identifier that can be used to fetch a list of columns and associated privileges for the specified table
+Returns a result identifier that can be used to fetch a list of column names in specified tables
+Commit an ODBC transaction
+Connect to a datasource
+Get cursor name
+Return information about the currently connected data source
+Get the last error code
+Get the last error message
+Prepare and execute an SQL statement
+Execute a prepared statement
+Fetch a result row as an associative array
+Fetch one result row into an array
+Fetch a result row as an object
+Fetch a row
+Get the length (precision) of a column
+Get a column name
+Return column number
+Get the scale of a column
+Get the datatype of a column
+Returns a result identifier to either a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table
+Free resources associated with a result
+Returns a result identifier containing information about data types supported by the data source
+Handle LONG columns
+Checks if multiple results are avaiable
+Get number of columns in a result
+Get number of rows in a result
+Establish a persistent connection to a datasource
+Prepares a statement for execution
+Returns a result identifier listing the column names that comprise the primary key for a table
+Returns a result identifier containing the list of input and output parameters, as well as the columns that make up the result set for the specified procedures
+Returns a result identifier containg the list of procedure names in a datasource
+Get result data
+Print result as HTML table
+Rollback a transaction
+Sets connection or statement options
+Returns a result identifier containing either the optimal set of columns that uniquely identifies a row in the table or columns that are automatically updated when any value in the row is updated by a transaction
+Returns a result identifier that contains statistics about a single table and the indexes associated with the table
+Returns a result identifier containing a list of tables and the privileges associated with each table
+Call the SQLTables function
+
+Exports a CSR to file or a var
+Exports a CSR to file
+Returns the subject of a CERT or FALSE on error
+Returns the subject of a CERT or FALSE on error
+Generates a privkey and CSR
+Signs a cert with another CERT
+Returns a description of the last error, and alters the index of the error messages. Returns false when the are no more messages
+Opens data
+Creates and exports a PKCS12 to a var
+Creates and exports a PKCS to file
+Parses a PKCS12 to an array
+Decrypts the S/MIME message in the file name infilename and output the results to the file name outfilename. recipcert is a CERT for one of the recipients. recipkey specifies the private key matching recipcert, if recipcert does not include the key
+Encrypts the message in the file named infile with the certificates in recipcerts and output the result to the file named outfile
+Signs the MIME message in the file named infile with signcert/signkey and output the result to file name outfile. headers lists plain text headers to exclude from the signed portion of the message, and should include to, from and subject as a minimum
+Verifys that the data block is intact, the signer is who they say they are, and returns the CERTs of the signers
+Gets an exportable representation of a key into a string or file
+Gets an exportable representation of a key into a file
+Frees a key
+returns an array with the key details (bits, pkey, type)
+Gets private keys
+Gets public key from X.509 certificate
+Generates a new private key
+Decrypts data with private key
+Encrypts data with private key
+Decrypts data with public key
+Encrypts data with public key
+Seals data
+Signs data
+Verifys data
+Checks if a private key corresponds to a CERT
+Checks the CERT to see if it can be used for the purpose in purpose. cainfo holds information about trusted CAs
+Exports a CERT to file or a var
+Exports a CERT to file or a var
+Frees X.509 certificates
+Returns an array of the fields/values of the CERT
+Reads X.509 certificates
+Set an alarm clock for delivery of a signal
+Executes specified program in current process space as defined by exec(2)
+Forks the currently running process following the same behavior as the UNIX fork() system call
+Get the priority of any process
+Change the priority of any process
+Assigns a system signal handler to a PHP function
+Waits on or returns the status of a forked child as defined by the waitpid() system call
+Waits on or returns the status of a forked child as defined by the waitpid() system call
+Returns the status code of a child's exit
+Returns true if the child status code represents a successful exit
+Returns true if the child status code represents a process that was terminated due to a signal
+Returns true if the child status code represents a stopped process (WUNTRACED must have been used with waitpid)
+Returns the number of the signal that caused the process to stop who's status code is passed
+Returns the number of the signal that terminated the process who's status code is passed
+Searches array and returns entries which match regex
+Returns the error code of the last regexp execution.
+Perform a Perl-style regular expression match
+Perform a Perl-style global regular expression match
+Quote regular expression characters plus an optional character
+Perform Perl-style regular expression replacement.
+Perform Perl-style regular expression replacement using replacement callback.
+Split string into an array using a perl-style regular expression as a delimiter
+Return array of available PDO drivers
+
+Prevents serialization of a PDO instance
+Prevents use of a PDO instance that has been unserialized
+Initiates a transaction
+Commit a transaction
+Fetch the error code associated with the last operation on the database handle
+Fetch extended error information associated with the last operation on the database handle
+Execute a query that does not return a row set, returning the number of affected rows
+Get an attribute
+Returns the id of the last row that we affected on this connection. Some databases require a sequence or table name to be passed in. Not always meaningful.
+Prepares a statement for execution and returns a statement object
+Prepare and execute $sql; returns the statement object for iteration
+quotes string for use in a query. The optional paramtype acts as a hint for drivers that have alternate quoting styles. The default value is PDO_PARAM_STR
+roll back a transaction
+Set an attribute
+Return array of available PDO drivers
+Prevents serialization of a PDOStatement instance
+Prevents use of a PDOStatement instance that has been unserialized
+bind a column to a PHP variable. On each row fetch $param will contain the value of the corresponding column. $column is the 1-based offset of the column, or the column name. For portability, don't call this before execute().
+bind a parameter to a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). This isn't supported by all drivers. It should be called prior to execute().
+bind an input parameter to the value of a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). It should be called prior to execute().
+Closes the cursor, leaving the statement ready for re-execution.
+Returns the number of columns in the result set
+A utility for internals hackers to debug parameter internals
+Fetch the error code associated with the last operation on the statement handle
+Fetch extended error information associated with the last operation on the statement handle
+Execute a prepared statement, optionally binding parameters
+Fetches the next row and returns it, or false if there are no more rows
+Returns an array of all of the results.
+Returns a data of the specified column in the result set.
+Fetches the next row and returns it as an object.
+Get an attribute
+Returns meta data for a numbered column
+Advances to the next rowset in a multi-rowset statement handle. Returns true if it succeded, false otherwise
+Returns the number of rows in a result set, or the number of rows affected by the last execute(). It is not always meaningful.
+Set an attribute
+Changes the default fetch mode for subsequent fetches (params have different meaning for different fetch modes)
+Returns the number of affected tuples
+Cancel request
+Get the current client encoding
+Close a PostgreSQL connection
+Open a PostgreSQL connection
+Get connection is busy or not
+Reset connection (reconnect)
+Get connection status
+Check and convert values for PostgreSQL SQL statement
+Copy table from array
+Copy table to array
+Get the database name
+Delete records has ids (id=>value)
+Sync with backend. Completes the Copy command
+Escape binary for bytea type
+Escape string for text/char type
+Execute a prepared query
+Fetch all rows into array
+Fetch all rows into array
+Fetch a row as an array
+Fetch a row as an assoc array
+Fetch a row as an object
+Returns values from a result identifier
+Get a row as an enumerated array
+Test if a field is NULL
+Returns the name of the field
+Returns the field number of the named field
+Returns the printed length
+Returns the internal size of the field
+Returns the name of the table field belongs to, or table's oid if oid_only is true
+Returns the type name for the given field
+Returns the type oid for the given field
+Free result memory
+Get asynchronous notification
+Get backend(server) pid
+Get asynchronous query result
+Returns the host name associated with the connection
+Insert values (filed=>value) to table
+Get the error message string
+Returns the last notice set by the backend
+Returns the last object identifier
+Close a large object
+Create a large object
+Export large object direct to filesystem
+Import large object direct from filesystem
+Open a large object and return fd
+Read a large object
+Read a large object and send straight to browser
+Seeks position of large object
+Returns current position of large object
+Delete a large object
+Write a large object
+Get meta_data
+Return the number of fields in the result
+Return the number of rows in the result
+Get the options associated with the connection
+Open a persistent PostgreSQL connection
+Ping database. If connection is bad, try to reconnect.
+Return the port number associated with the connection
+Prepare a query for future execution
+Send null-terminated string to backend server
+Execute a query
+Execute a query
+Get error message associated with result
+Get error message field associated with result
+Set internal row offset
+Get status of query result
+Select records that has ids (id=>value)
+Executes prevriously prepared stmtname asynchronously
+Asynchronously prepare a query for future execution
+Send asynchronous query
+Send asynchronous parameterized query
+Set client encoding
+Set error verbosity
+Enable tracing a PostgreSQL connection
+Get transaction status
+Return the tty name associated with the connection
+Unescape binary for bytea type
+Disable tracing of a PostgreSQL connection
+Update table using values (field=>value) and ids (id=>value)
+Returns an array with client, protocol and server version (when available)
+Determine accessibility of a file (POSIX.1 5.6.3)
+Generate terminal path name (POSIX.1, 4.7.1)
+Retrieve the error number set by the last posix function which failed.
+Get working directory pathname (POSIX.1, 5.2.2)
+Get the current effective group id (POSIX.1, 4.2.1)
+Get the current effective user id (POSIX.1, 4.2.1)
+Get the current group id (POSIX.1, 4.2.1)
+Group database access (POSIX.1, 9.2.1)
+Group database access (POSIX.1, 9.2.1)
+Get supplementary group id's (POSIX.1, 4.2.3)
+Get user name (POSIX.1, 4.2.4)
+Get the process group id of the specified process (This is not a POSIX function, but a SVR4ism, so we compile conditionally)
+Get current process group id (POSIX.1, 4.3.1)
+Get the current process id (POSIX.1, 4.1.1)
+Get the parent process id (POSIX.1, 4.1.1)
+User database access (POSIX.1, 9.2.2)
+User database access (POSIX.1, 9.2.2)
+Get system resource consumption limits (This is not a POSIX function, but a BSDism and a SVR4ism. We compile conditionally)
+Get process group id of session leader (This is not a POSIX function, but a SVR4ism, so be compile conditionally)
+Get the current user id (POSIX.1, 4.2.1)
+Calculate the group access list for the user specified in name.
+Determine if filedesc is a tty (POSIX.1, 4.7.1)
+Send a signal to a process (POSIX.1, 3.3.2)
+Make a FIFO special file (POSIX.1, 5.4.2)
+Make a special or ordinary file (POSIX.1)
+Set effective group id
+Set effective user id
+Set group id (POSIX.1, 4.2.2)
+Set process group id for job control (POSIX.1, 4.3.3)
+Create session and set process group id (POSIX.1, 4.3.2)
+Set user id (POSIX.1, 4.2.2)
+Retrieve the system error message associated with the given errno.
+Get process times (POSIX.1, 4.5.2)
+Determine terminal device name (POSIX.1, 4.7.2)
+Get system name (POSIX.1, 4.4.1)
+Adds a word to a personal list
+Adds a word to the current session
+Returns true if word is valid
+Clears the current session
+Create a new config to be used later to create a manager
+location of language data files
+location of the main word list
+Ignore words <= n chars
+Select mode for config (PSPELL_FAST, PSPELL_NORMAL or PSPELL_BAD_SPELLERS)
+Use a personal dictionary for this config
+Use a personal dictionary with replacement pairs for this config
+Consider run-together words as valid components
+Save replacement pairs when personal list is saved for this config
+Load a dictionary
+Load a dictionary based on the given config
+Load a dictionary with a personal wordlist
+Saves the current (personal) wordlist
+Notify the dictionary of a user-selected replacement
+Returns array of suggestions
+Reads a line
+Adds a line to the history
+Initializes the readline callback interface and terminal, prints the prompt and returns immediately
+Removes a previously installed callback handler and restores terminal settings
+Informs the readline callback interface that a character is ready for input
+Clears the history
+Readline completion function?
+Gets/sets various internal readline variables.
+Lists the history
+Inform readline that the cursor has moved to a new line
+Reads the history
+Ask readline to redraw the display
+Writes the history
+Recode file input into file output according to request
+Recode string str according to request string
+Return the current cache expire. If new_cache_expire is given, the current cache_expire is replaced with new_cache_expire
+Return the current cache limiter. If new_cache_limited is given, the current cache_limiter is replaced with new_cache_limiter
+Deserializes data and reinitializes the variables
+Destroy the current session and all data associated with it
+Serializes the current setup and returns the serialized representation
+Return the session cookie parameters
+Return the current session id. If newid is given, the session id is replaced with newid
+Return the current module name used for accessing session data. If newname is given, the module name is replaced with newname
+Return the current session name. If newname is given, the session name is replaced with newname
+Update the current session id with a newly generated one. If delete_old_session is set to true, remove the old session.
+Return the current save path passed to module_name. If newname is given, the save path is replaced with newname
+Set session cookie parameters
+Sets user-level functions
+Begin session - reinitializes freezed variables, registers browsers etc
+Unset all registered variables
+Write session data and end session
+Add Attribute with optional namespace information
+Add Element with optional namespace information
+Return a well-formed XML string based on SimpleXML element
+Identifies an element's attributes
+Finds children of given node
+Return all namespaces registered with document
+Finds children of given node
+Return all namespaces in use
+Creates a prefix/ns context for the next XPath query
+Runs XPath query on the XML data
+SimpleXMLElement constructor
+Return a string to confirm that the module is compiled in
+* * Generic SNMPv3 object fetcher * From here is passed on the the common internal object fetcher. * * st=SNMP_CMD_GET snmp3_get() - query an agent and return a single value. * st=SNMP_CMD_GETNEXT snmp3_getnext() - query an agent and return the next single value. * st=SNMP_CMD_WALK snmp3_walk() - walk the mib and return a single dimensional array * containing the values. * st=SNMP_CMD_REALWALK snmp3_real_walk() - walk the mib and return an * array of oid,value pairs. * st=SNMP_CMD_SET snmp3_set() - query an agent and set a single value *
+Fetch a SNMP object
+Fetch a SNMP object
+Return all objects including their respective object id withing the specified one
+Set the value of a SNMP object
+Return all objects under the specified object id
+Fetch the value of a SNMP object
+Fetch the value of a SNMP object
+Fetch the value of a SNMP object
+Fetch the value of a SNMP object
+Fetch the value of a SNMP object
+Return the current status of quick_print
+Return the method how the SNMP values will be returned
+Reads and parses a MIB file into the active MIB tree.
+Return all values that are enums with their enum value instead of the raw integer
+Set the OID output format.
+Return all objects including their respective object id withing the specified one
+Specify the method how the SNMP values will be returned
+Fetch a SNMP object
+Fetch a SNMP object
+Return all objects including their respective object id withing the specified one
+Set the value of a SNMP object
+Return all objects under the specified object id
+SoapClient::__doRequest()
+Returns array of cookies.
+Returns last SOAP request headers
+Returns last SOAP response headers
+Sets cookie thet will sent with SOAP request. The call to this function will effect all folowing calls of SOAP methods. If value is not specified cookie is removed.
+Sets the location option (the endpoint URL that will be touched by the following SOAP requests). If new_location is not specified or null then SoapClient will use endpoint from WSDL file. The function returns old value of location options.
+Sets SOAP headers for subsequent calls (replaces any previous values). If no value is specified, all of the headers are removed.
+Adds one or several functions those will handle SOAP requests
+Returns list of defined functions
+Sets class which will handle SOAP requests
+Sets object which will handle SOAP requests
+Accepts a connection on the listening socket fd
+Binds an open socket to a listening port, port is only specified in AF_INET family.
+Clears the error on the socket or the last error code.
+Closes a file descriptor
+Opens a connection to addr:port on the socket specified by socket
+Creates an endpoint for communication in the domain specified by domain, of type specified by type
+Opens a socket on port to accept connections
+Creates a pair of indistinguishable sockets and stores them in fds.
+Gets socket options for the socket
+Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type.
+Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type.
+Returns the last socket error (either the last used or the provided socket resource)
+Sets the maximum number of connections allowed to be waited for on the socket specified by fd
+Reads a maximum of length bytes from socket
+Receives data from a connected socket
+Receives data from a socket, connected or not
+Runs the select() system call on the sets mentioned with a timeout specified by tv_sec and tv_usec
+Sends data to a connected socket
+Sends a message to a socket, whether it is connected or not
+Sets blocking mode on a socket resource
+Sets nonblocking mode on a socket resource
+Sets socket options for the socket
+Shuts down a socket for receiving, sending, or both.
+Returns a string describing an error
+Writes the buffer to the socket resource, length is optional
+Return all classes and interfaces implemented by SPL
+Return an array containing the names of all parent classes
+Default implementation for __autoload()
+Try all registerd autoload function to load the requested class
+Register and return default file extensions for spl_autoload
+Register given function as __autoload() implementation
+Unregister given function as __autoload() implementation
+Return an array containing the names of all clsses and interfaces defined in SPL
+Return hash id for given object
+Move to next entry
+Rewind array back to the start
+Seek to position.
+Check whether array contains more entries
+proto void ArrayIterator::__construct(array|object ar = array() [, int flags = 0]) U Cronstructs a new array iterator from a path.
+proto void ArrayIterator::append(mixed $newval) U Appends the value (cannot be called for objects).
+proto int ArrayIterator::asort() U Sort the entries by values.
+proto int ArrayIterator::count() U Return the number of elements in the Iterator.
+Get flags
+Create a new iterator from a ArrayObject instance
+Get the class used in getIterator.
+proto int ArrayIterator::ksort() U Sort the entries by key.
+proto int ArrayIterator::natcasesort() U Sort the entries by key using case insensitive "natural order" algorithm.
+proto int ArrayIterator::natsort() U Sort the entries by values using "natural order" algorithm.
+proto bool ArrayIterator::offsetExists(mixed $index) U Returns whether the requested $index exists.
+proto mixed ArrayIterator::offsetGet(mixed $index) U Returns the value at the specified $index.
+proto void ArrayIterator::offsetSet(mixed $index, mixed $newval) U Sets the value at the specified $index to $newval.
+proto void ArrayIterator::offsetUnset(mixed $index) U Unsets the value at the specified $index.
+Set flags
+Set the class used in getIterator.
+proto int ArrayIterator::uasort(callback cmp_function) U Sort the entries by values user defined function.
+proto int ArrayIterator::uksort(callback cmp_function) U Sort the entries by key using user defined function.
+Create a sub iterator for the current element (same class as $this)
+Check whether current element has children (e.g. is an array)
+Cronstructs a new dir iterator from a path.
+Return number of entries in directory, works only when USE_GLOB is in effect
+Return this (needed for Iterator interface)
+Returns filename component of current dir entry
+Returns an iterator for the current entry if it is a directory
+Return filename of current dir entry
+Returns true if current entry is '.' or '..'
+Return current dir entry
+Move to next entry
+Rewind dir back to the start
+Check whether dir contains more entries
+Cronstructs a new dir iterator from a path.
+Return getFilename(), getFileInfo() or $this depending on flags
+Get sub path
+Get sub path and file name
+Returns whether current entry is a directory and not '.' or '..'
+Return getPathname() or getFilename() depending on flags
+Move to next entry
+Rewind dir back to the start
+Cronstructs a new SplFileInfo from a path.
+Get last access time of file
+Returns filename component of path
+Get inode modification time of file
+Get/copy file info
+Return filename only
+Get file group
+Get file inode
+Return the target of a symbolic link
+Get last modification time of file
+Get file owner
+Return the path
+Get/copy file info
+Return path and filename
+Get file permissions
+Return the resolved path
+Get file size
+Get file type
+Returns true if file is directory
+Returns true if file is executable
+Returns true if file is a regular file
+Returns true if file is symbolic link
+Returns true if file can be read
+Returns true if file can be written
+Open the current file
+Class to use in openFile()
+Class to use in getFileInfo(), getPathInfo()
+Construct a new file object
+Return current line from file
+Return whether end of file is reached
+Flush the file
+Get a character form the file
+Return current line as csv
+Rturn next line from file
+Get a line from file pointer and strip HTML tags
+Portable file locking
+Output all remaining data from a file pointer
+Implements a mostly ANSI compatible fscanf()
+Return current file position
+Stat() on a filehandle
+Return current file position
+Truncate file to 'size' length
+Binary-safe file write
+Read NULL
+Get the delimiter and enclosure character used in fgetcsv
+Get file handling flags
+Get maximum line length
+Return false
+Return line number
+Read next line
+Rewind the file and read the first line
+Seek to specified line
+Set the delimiter and enclosure character used in fgetcsv
+Set file handling flags
+Set maximum line length
+Return !eof()
+Construct a new temp file object
+Create an AppendIterator
+Append an iterator
+Get access to inner ArrayIterator
+Get index of iterator
+Forward to next element
+Rewind to the first iterator and rewind the first iterator, too
+Check if the current state is valid
+Construct a CachingIterator from an Iterator
+Return the string representation of the current element
+Number of cached elements
+Return the cache
+Return the internal flags
+Check whether the inner iterator has a valid next element
+Move the iterator forward
+Return whether the requested index exists
+Return the internal cache if used
+Set given index in cache
+Unset given index in cache
+Rewind the iterator
+Set the internal flags
+Check whether the current element is valid
+Throws exception BadMethodCallException
+Throws exception BadMethodCallException
+Does nothing
+Does nothing
+Return false
+Create an Iterator from another iterator
+proto mixed CachingIterator::current() U proto mixed LimitIterator::current() U proto mixed ParentIterator::current() U proto mixed IteratorIterator::current() U proto mixed NoRewindIterator::current() U proto mixed AppendIterator::current() U Get the current element value
+proto Iterator CachingIterator::getInnerIterator() U proto Iterator LimitIterator::getInnerIterator() U proto Iterator ParentIterator::getInnerIterator() U Get the inner iterator
+proto mixed CachingIterator::key() U proto mixed LimitIterator::key() U proto mixed ParentIterator::key() U proto mixed IteratorIterator::key() U proto mixed NoRewindIterator::key() U proto mixed AppendIterator::key() U Get the current key
+Move the iterator forward
+Rewind the iterator
+proto bool ParentIterator::valid() U proto bool IteratorIterator::valid() U proto bool NoRewindIterator::valid() U Check whether the current element is valid
+Create an iterator from another iterator
+Prevent a call to inner iterators rewind() (internally the current data will be fetched if valid())
+Create an iterator from anything that is traversable
+Return the current position
+Move the iterator forward
+Rewind the iterator to the specified starting offset
+Seek to the given position
+Check whether the current element is valid
+Create an iterator from another iterator
+Return inner iterators current()
+Return inner iterators key()
+Return inner iterators next()
+Prevent a call to inner iterators rewind()
+Return inner iterators valid()
+Create a ParentIterator from a RecursiveIterator
+proto void IteratorIterator::next() U proto void NoRewindIterator::next() U Move the iterator forward
+proto void IteratorIterator::rewind() Rewind the iterator
+Create an iterator from a RecursiveIterator
+Return the inner iterator's children as a RecursiveCachingIterator
+Check whether the current element of the inner iterator has children
+Create a RecursiveFilterIterator from a RecursiveIterator
+Return the inner iterator's children contained in a RecursiveFilterIterator
+Check whether the inner iterator's current element has children
+Called when recursing one level down
+Called when iteration begins (after first rewind() call)
+Return children of current element
+Called for each element to test whether it has children
+Access the current element value
+Called when end recursing one level
+Called when iteration ends (when valid() first returns false
+Get the current depth of the recursive iteration
+The current active sub iterator
+The current active sub iterator or the iterator at specified level
+Access the current key
+Move forward to the next element
+Called when the next element is available
+Rewind the iterator to the first element of the top level inner iterator.
+Set the maximum allowed depth (or any depth if pmax_depth = -1]
+Check whether the current position is valid
+Create an RecursiveRegexIterator from another recursive iterator and a regular expression
+Return the inner iterator's children contained in a RecursiveRegexIterator
+Create an RegexIterator from another iterator and a regular expression
+Match (string)current() against regular expression
+Returns current PREG flags (if in use or NULL)
+Returns current operation flags
+Returns current operation mode
+Set operation flags
+Set new operation mode
+Set PREG flags
+Construct a LimitIterator from an Iterator with a given starting offset and optionally a maximum count
+Calls a function for every element in an iterator
+Count the elements in an iterator
+Copy the iterator into an array
+Attaches an object to the storage if not yet contained
+Determine whethe an object is contained in the storage
+Determine number of objects in storage
+
+Detaches an object from the storage
+
+
+
+
+
+
+Get number of child elements
+Get current element
+Get child element iterator
+Check whether element has children (elements)
+Get name of current child element
+Move to next element
+Rewind to first element
+Check whether iteration is valid
+Executes a query against a given database and returns an array of arrays.
+Set busy timeout duration. If ms <= 0, all busy handlers are disabled.
+Returns the number of rows that were changed by the most recent SQL statement.
+Closes an open sqlite database.
+Fetches a column from the current row of a result set.
+Registers an aggregate function for queries.
+Registers a "regular" function for queries.
+Fetches the current row from a result set as an array.
+Returns the textual description of an error code.
+Escapes a string for use as a query parameter.
+Executes a result-less query against a given database
+Opens a SQLite database and creates an object for it. Will create the database if it does not exist.
+Fetches all rows from a result set as an array of arrays.
+Fetches the next row from a result set as an array.
+Return an array of column types from a particular table.
+Fetches the next row from a result set as an object.
+Fetches the first column of a result set as a string.
+Returns the name of a particular field of a result set.
+* Returns whether a previous row is available.
+Return the current row index of a buffered result.
+Returns the error code of the last error for a database.
+Returns the rowid of the most recently inserted row.
+Returns the encoding (iso8859 or UTF-8) of the linked SQLite library.
+Returns the version of the linked SQLite library.
+Seek to the next row number of a result set.
+Returns the number of fields in a result set.
+Returns the number of rows in a buffered result set.
+Opens a SQLite database. Will create the database if it does not exist.
+Opens a persistent handle to a SQLite database. Will create the database if it does not exist.
+* Seek to the previous row number of a result set.
+Executes a query against a given database and returns a result handle.
+Seek to the first row number of a buffered result set.
+Seek to a particular row number of a buffered result set.
+Executes a query and returns either an array for one single column or the value of the first row.
+Decode binary encoding on a string parameter passed to an UDF.
+Apply binary encoding (if required) to a string to return from an UDF.
+Executes a query that does not prefetch and buffer all data.
+Returns whether more rows are available.
+Retuns an array with all string keys lowercased [or uppercased]
+Split array into chunks
+Creates an array by using the elements of the first parameter as keys and the elements of the second as the corresponding values
+Return the value as key and the frequency of that value in input as value
+Returns the entries of arr1 that have values which are not present in any of the others arguments.
+Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal
+Returns the entries of arr1 that have keys which are not present in any of the others arguments. This function is like array_diff() but works on the keys instead of the values. The associativity is preserved.
+Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Elements are compared by user supplied function.
+Returns the entries of arr1 that have keys which are not present in any of the others arguments. User supplied function is used for comparing the keys. This function is like array_udiff() but works on the keys instead of the values. The associativity is preserved.
+Create an array containing num elements starting with index start_key each initialized to val
+Create an array using the elements of the first parameter as keys each initialized to val
+Filters elements from the array via the callback.
+Return array with key <-> value flipped
+Returns the entries of arr1 that have values which are present in all the other arguments
+Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check
+Returns the entries of arr1 that have keys which are present in all the other arguments. Kind of equivalent to array_diff(array_keys($arr1), array_keys($arr2)[,array_keys(...)]). Equivalent of array_intersect_assoc() but does not do compare of the data.
+Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check and they are compared by using an user-supplied callback.
+Returns the entries of arr1 that have keys which are present in all the other arguments. Kind of equivalent to array_diff(array_keys($arr1), array_keys($arr2)[,array_keys(...)]). The comparison of the keys is performed by a user supplied function. Equivalent of array_intersect_uassoc() but does not do compare of the data.
+Checks if the given key or index exists in the array
+Return just the keys from the input array, optionally only for the specified search_value
+Applies the callback to the elements in given arrays.
+Merges elements from passed arrays into one array
+Recursively merges elements from passed arrays into one array
+Sort multiple arrays at once similar to how ORDER BY clause works in SQL
+Returns a copy of input array padded with pad_value to size pad_size
+Pops an element off the end of the array
+Returns the product of the array entries
+Pushes elements onto the end of the array
+Return key/keys for random entry/entries in the array
+Iteratively reduce the array to a single value via the callback.
+Return input as a new array with the order of the entries reversed
+Searches the array for a given value and returns the corresponding key if successful
+Pops an element off the beginning of the array
+Returns elements specified by offset and length
+Removes the elements designated by offset and length and replace them with supplied array
+Returns the sum of the array entries
+Returns the entries of arr1 that have values which are not present in any of the others arguments. Elements are compared by user supplied function.
+Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Entries are compared by user supplied function.
+Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Keys and elements are compared by user supplied functions.
+Returns the entries of arr1 that have values which are present in all the other arguments. Data is compared by using an user-supplied callback.
+Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Data is compared by using an user-supplied callback.
+Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Both data and keys are compared by using user-supplied callbacks.
+Removes duplicate values from array
+Pushes elements onto the beginning of the array
+Return just the values from the input array
+Apply a user function to every member of an array
+Apply a user function recursively to every member of an array
+Sort an array in reverse order and maintain index association
+Sort an array and maintain index association
+Creates a hash containing variables and their values
+Count the number of elements in a variable (usually an array)
+Return the element currently pointed to by the internal array pointer
+Advances array argument's internal pointer to the last element and return it
+Imports variables into symbol table from an array
+Checks if the given value exists in the array
+Return the key of the element currently pointed to by the internal array pointer
+Sort an array by key value in reverse order
+Sort an array by key
+Return the highest value in an array or a series of arguments
+Return the lowest value in an array or a series of arguments
+Sort an array using case-insensitive natural sort
+Sort an array using natural sort
+Move array argument's internal pointer to the next element and return it
+Move array argument's internal pointer to the previous element and return it
+Create an array containing the range of integers or characters from low to high (inclusive)
+Set array argument's internal pointer to the first element and return it
+Sort an array in reverse order
+Randomly shuffle the contents of an array
+Sort an array
+Sort an array with a user-defined comparison function and maintain index association
+Sort an array by keys using a user-defined comparison function
+Sort an array by values using a user-defined comparison function
+Checks if assertion is false
+Set/get the various assert flags
+Decodes string using MIME base64 algorithm
+Encodes string using MIME base64 algorithm
+Call a user function which is the first parameter
+Call a user function which is the first parameter with the arguments contained in array
+Call a user method on a specific object or class
+Call a user method on a specific object or class using a parameter array
+Returns true if client disconnected
+Returns the connection status bitfield
+Given the name of a constant this function will return the constant's associated value
+Get the last occurred error as associative array. Returns NULL if there hasn't been an error yet.
+Send an error message somewhere
+Flush the output buffer
+Get the value of a PHP configuration option
+Get the name of the owner of the current PHP script
+Get the current include_path configuration option
+Get the value of an environment variable
+Get options from the command line argument list
+Returns protocol number associated with name as per /etc/protocols
+Returns protocol name associated with protocol number proto
+Returns port associated with service. Protocol must be "tcp" or "udp"
+Returns service name associated with port. Protocol must be "tcp" or "udp"
+Syntax highlight a source file
+Syntax highlight a string or optionally return it
+Set whether we want to ignore a user abort event or not
+Import GET/POST/Cookie variables into the global scope
+Converts a packed inet address to a human readable IP address string
+Converts a human readable IP address to a packed binary string
+Get a configuration option
+Get all configuration options
+Restore the value of a configuration option specified by varname
+Set a configuration option, returns false on error and the old value of the configuration option on success
+Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address
+Check if file was created by rfc1867 upload
+Converts an (IPv4) Internet network address into a string in Internet standard dotted format
+Move a file if and only if it was created by an upload
+Parse configuration file
+Return source with stripped comments and whitespace
+Prints out or returns information about the specified variable
+Set the value of an environment variable
+Register a user-level function to be called on request termination
+Registers a tick callback function
+Restore the value of the include_path configuration option
+Sets the include_path configuration option
+Delay for a given number of seconds
+
+Delay for a number of seconds and nano seconds
+Make the script sleep until the specified time
+Unregisters a tick callback function
+Delay for a given number of micro seconds
+Get information about the capabilities of a browser. If browser_name is omitted or null, HTTP_USER_AGENT is used. Returns an object by default; if return_array is true, returns an array.
+Calculate the crc32 polynomial of a string
+Hash a string
+Convert from one Cyrillic character set to another
+Parse a time/date generated with strftime()
+Change the current directory
+Change root directory
+Close directory connection identified by the dir_handle
+Directory class with properties, handle and class and methods read, rewind and close
+Gets the current directory
+Find pathnames matching a pattern
+Open a directory and return a dir_handle
+Read directory entry from dir_handle
+Rewind dir_handle back to the start
+List files & directories inside the specified path
+Load a PHP extension at runtime
+Check DNS records corresponding to a given Internet host name or IP address
+Get MX records corresponding to a given Internet host name
+Get the Internet host name corresponding to a given IP address
+Get the IP address corresponding to a given Internet host name
+Return a list of IP addresses that a given hostname resolves to.
+Quote and escape an argument for use in a shell command
+Escape shell metacharacters
+Execute an external program
+Execute an external program and display raw output
+Change the priority of the current process
+Execute command via shell and return complete output as string
+Execute an external program and display output
+Copy a file
+Close an open file pointer
+Test for end-of-file on a file pointer
+Flushes output
+Get a character from file pointer
+Get line from file pointer and parse for CSV fields
+Get a line from file pointer
+Get a line from file pointer and strip HTML tags
+Read entire file into an array
+Read the entire file into a string
+Write/Create a file with contents data and return the number of bytes written
+Portable file locking
+Match filename against pattern
+Open a file or a URL and return a file pointer
+Output all remaining data from a file pointer
+Format line as CSV and write to file pointer
+Binary-safe file read
+Implements a mostly ANSI compatible fscanf()
+Seek on a file pointer
+Stat() on a filehandle
+Get file pointer's read/write position
+Truncate file to 'size' length
+Binary-safe file write
+Extracts all meta tag content attributes from a file and returns an array
+Create a directory
+Close a file pointer opened by popen()
+Execute a command and open either a read or a write pipe to it
+Output a file or a URL
+Return the resolved path
+Rename a file
+Rewind the position of a file pointer
+Remove a directory
+Returns directory path used for temporary files
+Create a unique filename in a directory
+Create a temporary file that will be deleted automatically after use
+Return or change the umask
+Delete a file
+Change file group
+Change file mode
+Clear file stat cache
+Get free disk space for filesystem that path is on
+Get total disk space for filesystem that path is on
+Returns true if filename exists
+Get last access time of file
+Get inode modification time of file
+Get file group
+Get file inode
+Get last modification time of file
+Get file owner
+Get file permissions
+Get file size
+Get file type
+Returns true if file is directory
+Returns true if file is executable
+Returns true if file is a regular file
+Returns true if file is symbolic link
+Returns true if file can be read
+Returns true if file can be written
+Change symlink group
+Give information about a file or symbolic link
+Give information about a file
+Set modification time of file
+Output a formatted string into a stream
+Output a formatted string
+Return a formatted string
+Output a formatted string into a stream
+Output a formatted string
+Return a formatted string
+Open Internet or Unix domain socket connection
+Open persistent Internet or Unix domain socket connection
+Convert a pathname and a project identifier to a System V IPC key
+Sends a raw HTTP header
+Return list of headers to be sent / already sent
+Returns true if headers have already been sent, false otherwise
+Send a cookie
+Send a cookie with no url encoding of the value
+Returns the internal translation table used by htmlspecialchars and htmlentities
+Convert all HTML entities to their applicable characters
+Convert all applicable characters to HTML entities
+Convert special characters to HTML entities
+Convert special HTML entities back to characters
+Generates a form-encoded query string from an associative array or object.
+Get the size of an image as 4-element array
+Get file extension for image-type returned by getimagesize, exif_read_data, exif_thumbnail, exif_imagetype
+Get Mime-Type for image-type returned by getimagesize, exif_read_data, exif_thumbnail, exif_imagetype
+Return the special ID used to request the PHP logo in phpinfo screens
+Return the actual loaded ini filename
+Return comma-separated string of .ini files parsed from the additional ini dir
+Return the special ID used to request the PHP logo in phpinfo screens
+Return the special ID used to request the PHP logo in phpinfo screens
+Return the current SAPI module name
+Return information about the system PHP was built on
+Prints the list of people who've contributed to the PHP project
+Output a page of useful information about PHP and the current request
+Return the current PHP version
+Return the special ID used to request the Zend logo in phpinfo screens
+Embed binary IPTC data into a JPEG image.
+Parse binary IPTC-data into associative array
+Returns a value from the combined linear congruential generator
+Calculate Levenshtein distance between two strings
+Create a hard link
+Returns the st_dev field of the UNIX C stat structure describing the link
+Return the target of a symbolic link
+Create a symbolic link
+Calculate EZMLM list hash value.
+Send an email message
+Return the absolute value of the number
+Return the arc cosine of the number in radians
+Returns the inverse hyperbolic cosine of the number, i.e. the value whose hyperbolic cosine is number
+Returns the arc sine of the number in radians
+Returns the inverse hyperbolic sine of the number, i.e. the value whose hyperbolic sine is number
+Returns the arc tangent of the number in radians
+Returns the arc tangent of y/x, with the resulting quadrant determined by the signs of y and x
+Returns the inverse hyperbolic tangent of the number, i.e. the value whose hyperbolic tangent is number
+Converts a number in a string from any base <= 36 to any base <= 36
+Returns the decimal equivalent of the binary number
+Returns the next highest integer value of the number
+Returns the cosine of the number in radians
+Returns the hyperbolic cosine of the number, defined as (exp(number) + exp(-number))/2
+Returns a string containing a binary representation of the number
+Returns a string containing a hexadecimal representation of the given number
+Returns a string containing an octal representation of the given number
+Converts the number in degrees to the radian equivalent
+Returns e raised to the power of the number
+Returns exp(number) - 1, computed in a way that accurate even when the value of number is close to zero
+Returns the next lowest integer value from the number
+Returns the remainder of dividing x by y as a float
+Returns the decimal equivalent of the hexadecimal number
+Returns sqrt(num1*num1 + num2*num2)
+Returns whether argument is finite
+Returns whether argument is infinite
+Returns whether argument is not a number
+Returns the natural logarithm of the number, or the base log if base is specified
+Returns the base-10 logarithm of the number
+Returns log(1 + number), computed in a way that accurate even when the value of number is close to zero
+Formats a number with grouped thousands
+Returns the decimal equivalent of an octal string
+Returns an approximation of pi
+Returns base raised to the power of exponent. Returns integer result when possible
+Converts the radian number to the equivalent number in degrees
+Returns the number rounded to specified precision
+Returns the sine of the number in radians
+Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2
+Returns the square root of the number
+Returns the tangent of the number in radians
+Returns the hyperbolic tangent of the number, defined as sinh(number)/cosh(number)
+Calculate the md5 hash of a string
+Calculate the md5 hash of given filename
+Break english phrases down into their phonemes
+Returns an array of usage statistics
+Returns the current time as array
+Returns either a string or a float containing the current time in seconds and microseconds
+Takes one or more arguments and packs them into a binary string according to the format argument
+Unpack binary string into named array elements according to format argument
+Get time of last page modification
+Get PHP script owner's GID
+Get the inode of the current script being parsed
+Get current process ID
+Get PHP script owner's UID
+close a process opened by proc_open
+get information about a process opened by proc_open
+Run a process with more control over it's file descriptors
+kill a process opened by proc_open
+Convert a quoted-printable string to an 8 bit string
+Returns the maximum value a random number can have
+Returns the maximum value a random number from Mersenne Twister can have
+Returns a random number from Mersenne Twister
+Seeds Mersenne Twister random number generator
+Returns a random number
+Seeds random number generator
+Regular expression match
+Replace regular expression
+Case-insensitive regular expression match
+Case insensitive replace regular expression
+Split string into array by regular expression
+Split string into array by regular expression case-insensitive
+Make regular expression for case insensitive match
+Calculate the sha1 hash of a string
+Calculate the sha1 hash of given filename
+Calculate the soundex key of a string
+Create a file context and optionally set parameters
+Get a handle on the default file/stream context and optionally set parameters
+Retrieve options for a stream/wrapper/context
+* Overloaded form: stream_context_set_option(resource context|resource stream, array options) * Set an option (or several options) for a wrapper
+Set parameters for a file context
+Reads up to maxlen bytes from source stream and writes them to dest stream.
+Convenience wrapper for ini_set('unicode.stream_encoding', $encoding)
+Set character set for stream encoding UTODO: Return current encoding charset
+Append a filter to a stream
+Prepend a filter to a stream
+Flushes any data in the filter's internal buffer, removes it from the chain, and frees the resource
+Reads all remaining bytes (or up to maxlen bytes) from a stream and returns them as a string.
+Read up to maxlen bytes from a stream or until the ending string is found
+Retrieves header/meta data from streams/file pointers
+Retrieves list of registered socket transports
+Retrieves list of registered stream wrappers
+
+Determine what file will be opened by calls to fopen() with a relative path
+Runs the select() system call on the sets of streams with a timeout specified by tv_sec and tv_usec
+Set blocking/non-blocking mode on a socket or stream
+Set timeout on stream read to seconds + microseonds
+Set file write buffer
+Accept a client connection from a server socket
+Open a client connection to a remote address
+Enable or disable a specific kind of crypto on the stream
+Returns either the locally bound or remote name for a socket stream
+Creates a pair of connected, indistinguishable socket streams
+Receives data from a socket stream
+Send data to a socket stream. If target_addr is specified it must be in dotted quad (or [ipv6]) format
+Create a server socket bound to localaddress
+causes all or part of a full-duplex connection on the socket associated with stream to be shut down. If how is SHUT_RD, further receptions will be disallowed. If how is SHUT_WR, further transmissions will be disallowed. If how is SHUT_RDWR, further receptions and transmissions will be disallowed.
+Escapes all chars mentioned in charlist with backslash. It creates octal representations if asked to backslash characters with 8th bit set or with ASCII<32 (except '\n', '\r', '\t' etc...)
+Escapes single quote, double quotes and backslash characters in a string with backslashes
+Returns the filename component of the path
+Converts the binary representation of data to hex
+Converts a codepoint number to a character
+Returns split line
+Returns info about what characters are used in input
+Returns the directory name component of the path
+Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned.
+Converts logical Hebrew text to visual text
+Converts logical Hebrew text to visual text with newline conversion
+Joins array elements placing glue string between items and return one string
+An alias for implode
+Returns numeric formatting information based on the current locale
+Strips whitespace from the beginning of a string
+Convert monetary value(s) to string
+Converts newlines to HTML line breaks
+Query language and locale information
+Returns the codepoint value of a character
+Parses GET/POST/COOKIE data and sets global variables
+Returns information about a certain string
+Quotes meta characters
+Removes trailing whitespace
+Set locale information
+Calculates the similarity between two strings
+Implements an ANSI C compatible sscanf
+Parse a CSV string into an array
+Replaces all occurrences of search in haystack with replace / case-insensitive
+Returns input string padded on the left or right to specified length with pad_string
+Returns the input string repeat mult times
+Replaces all occurrences of search in haystack with replace
+Perform the rot13 transform on a string
+Shuffles string. One permutation of all possible is created
+Convert a string to an array. If split_length is specified, break the string down into chunks each split_length characters long.
+Counts the number of words inside a string. If format of 1 is specified, then the function will return an array containing all the words found inside the string. If format of 2 is specified, then the function will return an associated array where the position of the word is the key and the word itself is the value. For the purpose of this function, 'word' is defined as a locale dependent string containing alphabetic characters, which also may contain, but not start with "'" and "-" characters.
+An alias for strstr
+Compares two strings using the current locale
+Finds length of initial segment consisting entirely of characters not found in mask. If start or/and length is provide works like strcspn(substr($s,$start,$len),$bad_chars)
+Strips HTML and PHP tags from a string
+Strips backslashes from a string. Uses C-style conventions
+Finds position of first occurrence of a string within another, case insensitive
+Strips backslashes from a string
+Finds first occurrence of a string within another, case insensitive
+Returns the result of case-insensitive string comparison using 'natural' algorithm
+Returns the result of string comparison using 'natural' algorithm
+Search a string for any of a set of characters
+Finds position of first occurrence of a string within another
+Finds the last occurrence of a character in a string within another
+Reverse a string
+Finds position of last occurrence of a string within another string
+Finds position of last occurrence of a string within another string
+Finds length of initial segment consisting entirely of characters found in mask. If start or/and length is provided works like strspn(substr($s,$start,$len),$good_chars)
+Finds first occurrence of a string within another
+Tokenize a string
+Makes a string lowercase
+Makes a string titlecase
+Makes a string uppercase
+Translates characters in str using given translation tables
+Returns part of a string
+Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters
+Returns the number of times a substring occurs in the string
+Replaces part of a string with another string
+Strips whitespace from the beginning and end of a string
+Makes a string's first character uppercase
+Uppercase the first character of every word in a string
+Wraps buffer to selected number of characters using string break char
+Close connection to system logger
+Initializes all syslog-related variables
+Open connection to system logger
+Generate a system log message
+Get the float value of a variable
+Returns the type of the variable
+Get the integer value of a variable using the optional base for the conversion
+Returns true if variable is an array
+Returns true if variable is a native (binary) string
+Returns true if variable is a boolean
+Returns true if variable is a native, unicode or binary string
+Returns true if var is callable.
+Returns true if variable is float point
+Returns true if variable is a long (integer)
+Returns true if variable is null
+Returns true if value is a number or a numeric string
+Returns true if variable is an object
+Returns true if variable is a resource
+Returns true if value is a scalar
+Returns true if variable is a Unicode or binary string
+Returns true if variable is a unicode string
+Set the type of the variable
+Get the string value of a variable
+Generates a unique ID
+fetches all the headers sent by the server in response to a HTTP request
+Parse a URL and return its components
+Decodes URL-encodes string
+URL-encodes string
+Decodes URL-encoded string
+URL-encodes string
+Append bucket to brigade
+Return a bucket object from the brigade for operating on
+Create a new bucket for use on the current stream
+Prepend bucket to brigade
+Registers a custom filter handler class
+Returns a list of registered filters
+Non-function
+decode a uuencoded string
+uuencode a string
+Dumps a string representation of an internal zend value to output.
+Returns the peak allocated by PHP memory
+Returns the allocated by PHP memory
+Returns a string representation of variable (which can later be unserialized)
+Takes a string representation of variable and recreates it
+Dumps a string representation of variable to output
+Outputs or returns a string representation of a variable
+Dumps a string representation of variable to output (verbose form)
+Compares two "PHP-standardized" version number strings
+Get number of affected rows in last query
+Close Sybase connection
+Open Sybase server connection
+Move internal row pointer
+Fetch row as array
+Get field information
+Fetch row as object
+Get row as enumerated array
+Set field offset
+Free result memory
+Returns the last message from server (over min_message_severity)
+Sets the minimum error severity
+Sets the minimum message severity
+Get number of fields in result
+Get number of rows in result
+Open persistent Sybase connection
+Send Sybase query
+Get result data
+Select Sybase database
+Get number of affected rows in last query
+Close Sybase connection
+Open Sybase server connection
+Move internal row pointer
+Sets deadlock retry count
+Fetch row as array
+Fetch row as array without numberic indices
+Get field information
+Fetch row as object
+Get row as enumerated array
+Set field offset
+Free result memory
+Returns the last message from server (over min_message_severity)
+Sets minimum client severity
+Sets minimum server severity
+Get number of fields in result
+Get number of rows in result
+Open persistent Sybase connection
+Send Sybase query
+Get result data
+Select Sybase database
+Set the error handler, to be called when a server message is raised. If error_func is NULL the handler will be deleted
+Send Sybase query
+Attach to a message queue
+Send a message of type msgtype (must be > 0) to a message queue
+Destroy the queue
+Send a message of type msgtype (must be > 0) to a message queue
+Set information for a message queue
+Returns information about a message queue
+Acquires the semaphore with the given id, blocking if necessary
+Return an id for the semaphore with the given key, and allow max_acquire (default 1) processes to acquire it simultaneously
+Releases the semaphore with the given id
+Removes semaphore from Unix systems
+Creates or open a shared memory segment
+Disconnects from shared memory segment
+Returns a variable from shared memory
+Checks whether a specific entry exists
+Inserts or updates a variable in shared memory
+Removes shared memory from Unix systems
+Removes variable from shared memory
+Returns the parent node if available or NULL
+Returns true if this node has children
+Returns true if this node has siblings
+Returns true if this node is ASP
+Returns true if this node represents a comment
+Returns true if this node is part of a HTML document
+Returns true if this node is JSTE
+Returns true if this node is PHP
+Returns true if this node represents text (no markup)
+Returns the Number of Tidy accessibility warnings encountered for specified document.
+Execute configured cleanup and repair operations on parsed markup
+Returns the Number of Tidy configuration errors encountered for specified document.
+Run configured diagnostics on parsed and repaired markup.
+Returns the Number of Tidy errors encountered for specified document.
+Returns a TidyNode Object starting from the <BODY> tag of the tidy parse tree
+Get current Tidy configuration
+Return warnings and errors which occured parsing the specified document
+Returns a TidyNode Object starting from the <HEAD> tag of the tidy parse tree
+Returns a TidyNode Object starting from the <HTML> tag of the tidy parse tree
+Get the Detected HTML version for the specified document.
+Returns the documentation for the given option name
+Return a string representing the parsed tidy markup
+Get release date (version) for Tidy library
+Returns a TidyNode Object representing the root of the tidy parse tree
+Get status of specfied document.
+Returns the value of the specified configuration option for the tidy document.
+Indicates if the document is a XHTML document.
+Indicates if the document is a generic (non HTML/XHTML) XML document.
+Parse markup in file or URI
+Parse a document stored in a string
+Repair a file using an optionally provided configuration file
+Repair a string using an optionally provided configuration file
+Returns the Number of Tidy warnings encountered for specified document.
+
+
+Compare two strings using collation }}}
+Returns a collation attribute }}}
+Returns the current collation strength }}}
+Set a collation attribute }}}
+Set the collation strength }}}
+Sort an array using collation }}}
+Compare two strings using collation
+Create a new Collator object
+Returns a collation attribute
+Returns default collator
+Returns the current collation strength
+Set a collation attribute
+Sets default collator
+Set the collation strength
+Sort an array using collation
+Create a new Collator object
+Returns default locale
+Sets default locale
+Enumerate all assigned Unicode characters between the start and limit code points (start inclusive, limit exclusive) and call a function for each, passing the code point value and the character name.
+Enumerate all code points with their general categories invoking a callback for each category
+Get the character representation for the specified digit (optionally in the specified radix)
+Translate a human readable character name into a codepoint
+Get the "age" of the code point (the Unicode version when it was first designated or assigned a character)
+Returns the combining class of the character
+Returns the decimal digit value of the character (optionally in the specific radix).
+Returns the bidirectional category value for the character, which is used in the Unicode bidirectional algorithm (UAX #9 http://www.unicode.org/reports/tr9/)
+Maps the specified character to its "mirror-image"
+Get the human readable name associated with the character
+Get the numeric value for the character, as defined in the Unicode Character Database
+Get the property ID for the given property name
+Get the maximum possible value associated with the specified property
+Get the minimum possible value for the specified property
+Get the Unicode name for the given property
+Get the value of a property associated with the character
+Get the value ID for the given property value name
+Get the Unicode name for the givenproperty value
+Returns the general category value for the code point
+Determines if all the characters in the string have the specified binary property
+Determines if the string consists only of alpanumeric characters
+Determines if the string consists only of letter characters
+Determines if the string consists only of characters with Alphabetic property
+Determines if the string consists of only of base characters
+Determines if the string consists only of "blank" characters
+Determines if the string consists only of control characters
+Determines if the string consists only of defined characters (valid Unicode points)
+Determines if the string consists only of digits
+Determines if the string consists only of "graphic" characters
+Determines if the specified characters should be regarded as an ignorable character in an identifier, according to Java
+etermines if the specified characters are permissible in an identifier, according to Java
+Determines if the specified character is permissible as the first character in an identifier according to Unicode
+Determines whether the specified code points are ISO control codes
+Determines if the string is lowercase
+Determines whether the specified characters have the Bidi_Mirrored property
+Determines if the string consists only of printable characters
+Determines if the string consists only of punctuation characters
+Determines if the string consists only of space characters
+Determines whether the string consists only of titlecase characters
+Determines if the string is uppercase
+Determines if the string consists only of characters with Uppercase property
+Determines if the the code point is valid character, according to Unicode
+Determines if the string consists only of whitespace characters, according to Java/ICU
+Determines if the string consists only of hexadecimal digits
+Transliterate a string from the source script to the target script
+Takes a binary string converts it to a Unicode string using the specifed encoding
+Takes a Unicode string and converts it to a binary string using the specified encoding
+Returns global conversion error mode for the specified conversion direction
+Returns global substitution character for conversion from Unicode to codepage
+Restores the active error handler to the one which was previously active (before the last unicode_set_error_handler() call)
+Check whether unicode semantics are enabled
+Set (or clear) the custom Unicode conversion error handler
+Sets global conversion error mode for the specified conversion direction
+Sets global substitution character for conversion from Unicode to codepage
+TextIterator constructor
+Returns the element at the current boundary
+Positions iterator at the first character in the text and returns the offset
+Advances to the text boundary following the specified offset and returns its offset
+Return all text pieces determined by the text boundaries
+Returns locales for which text boundary information is available
+Return the status from the break rule that determined the most recent boundary
+Return the statuses from the break rules that determined the most recent boundary
+Determines whether specified offset is a text boundary
+Returns the number boundaries iterated through
+Positions iterator beyond the last character in the text and returns the offset
+Advances to the n'th text boundary following the current one and returns its offset
+Returns the offset of the current text boundary
+Advances to the text boundary preceding the specified offset and returns its offset
+Advances to the n'th text boundary preceding the current one and returns its offset
+Determines validity of the iterator
+Serializes given variables and adds them to packet given by packet_id
+Ends specified WDDX packet and returns the string containing the packet
+Starts a WDDX packet with optional comment and returns the packet id
+Creates a new packet and serializes the given value
+Creates a new packet and serializes given variables into a struct
+Unserializes given packet and returns a PHP value
+Converts a UTF-8 encoded string to ISO-8859-1
+Encodes an ISO-8859-1 string to UTF-8
+Get XML parser error string
+Get current byte index for an XML parser
+Get current column number for an XML parser
+Get current line number for an XML parser
+Get XML parser error code
+Start parsing an XML document
+Parsing a XML document
+Create an XML parser
+Create an XML parser
+Free an XML parser
+Get options from an XML parser
+Set options in an XML parser
+Set up character data handler
+Set up default handler
+Set up start and end element handlers
+Set up character data handler
+Set up external entity reference handler
+Set up notation declaration handler
+Set up object which should be used for callbacks
+Set up processing instruction (PI) handler
+Set up character data handler
+Set up unparsed entity declaration handler
+Sets the string that the the XMLReader will parse.
+Closes xmlreader - current frees resources until xmlTextReaderClose is fixed in libxml
+Moves the position of the current instance to the next node in the stream.
+Get value of an attribute from current element
+Get value of an attribute at index from current element
+Get value of a attribute via name and namespace from current element
+Indicates whether given property (one of the parser option constants) is set or not on parser
+Returns boolean indicating if parsed document is valid or not. Must set XMLREADER_LOADDTD or XMLREADER_VALIDATE parser option prior to the first call to read or this method will always return FALSE
+Return namespaceURI for associated prefix on current node
+Positions reader at specified attribute - Returns TRUE on success and FALSE on failure
+Positions reader at attribute at spcecified index. Returns TRUE on success and FALSE on failure
+Positions reader at attribute spcified by name and namespaceURI. Returns TRUE on success and FALSE on failure
+Moves the position of the current instance to the node that contains the current Attribute node.
+Moves the position of the current instance to the first attribute associated with the current node.
+Moves the position of the current instance to the next attribute associated with the current node.
+Moves the position of the current instance to the next node in the stream.
+Sets the URI that the the XMLReader will parse.
+Moves the position of the current instance to the next node in the stream.
+Reads the contents of the current node, including child nodes and markup.
+Reads the contents of the current node, including child nodes and markup.
+Reads the contents of an element or a text node as a string.
+Sets parser property (one of the parser option constants). Properties must be set after open() or XML() and before the first read() is called
+Sets the string that the the XMLReader will parse.
+Sets the string that the the XMLReader will parse.
+Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read().
+Decodes XML into native PHP types
+Decodes XML into native PHP types
+Generates XML for a PHP value
+Generates XML for a method request
+Gets xmlrpc type for a PHP value. Especially useful for base64 and datetime strings
+Determines if an array value represents an XMLRPC fault.
+Decodes XML into a list of method descriptions
+Adds introspection documentation
+Parses XML requests and call methods
+Creates an xmlrpc server
+Destroys server resources
+Register a PHP function to generate documentation
+Register a PHP function to handle method matching method_name
+Sets xmlrpc type, base64 or datetime, for a PHP string value
+End attribute - returns FALSE on error
+End current CDATA - returns FALSE on error
+Create end comment - returns FALSE on error
+End current document - returns FALSE on error
+End current DTD - returns FALSE on error
+End current DTD AttList - returns FALSE on error
+End current DTD element - returns FALSE on error
+End current DTD Entity - returns FALSE on error
+End current element - returns FALSE on error
+End current PI - returns FALSE on error
+Output current buffer
+End current element - returns FALSE on error
+Create new xmlwriter using memory for string output
+Create new xmlwriter using source uri for output
+Output current buffer as string
+Toggle indentation on/off - returns FALSE on error
+Set string used for indenting - returns FALSE on error
+Create start attribute - returns FALSE on error
+Create start namespaced attribute - returns FALSE on error
+Create start CDATA tag - returns FALSE on error
+Create start comment - returns FALSE on error
+Create document tag - returns FALSE on error
+Create start DTD tag - returns FALSE on error
+Create start DTD AttList - returns FALSE on error
+Create start DTD element - returns FALSE on error
+Create start DTD Entity - returns FALSE on error
+Create start element tag - returns FALSE on error
+Create start namespaced element tag - returns FALSE on error
+Create start PI tag - returns FALSE on error
+Write text - returns FALSE on error
+Write full attribute - returns FALSE on error
+Write full namespaced attribute - returns FALSE on error
+Write full CDATA tag - returns FALSE on error
+Write full comment tag - returns FALSE on error
+Write full DTD tag - returns FALSE on error
+Write full DTD AttList tag - returns FALSE on error
+Write full DTD element tag - returns FALSE on error
+Write full DTD Entity tag - returns FALSE on error
+Write full element tag - returns FALSE on error
+Write full namesapced element tag - returns FALSE on error
+Write full PI tag - returns FALSE on error
+Write text - returns FALSE on error
+
+
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# Since:
+
+
+
+URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# Since:
+
+
+Add a file in a Zip archive using its path and the name to use.
+Add a file using content and the entry name
+close the zip archive
+Returns the index of the entry named filename in the archive
+Delete a file using its index
+Delete a file using its index
+Returns the comment of an entry using its index
+Returns the comment of an entry using its index
+Returns the comment of an entry using its name
+get the contents of an entry using its index
+get the contents of an entry using its name
+Returns the name of the file at position index
+get a stream for an entry using its name
+Returns the index of the entry named filename in the archive
+Create new zip using source uri for output, return TRUE on success or the error code
+Rename an entry selected by its index to new_name
+Rename an entry selected by its name to new_name
+Set or remove (NULL/'') the comment of the archive
+Set or remove (NULL/'') the comment of an entry using its index
+Set or remove (NULL/'') the comment of an entry using its Name
+Returns the zip entry informations using its index
+Returns the information about a the zip entry filename
+All changes to files and global information in archive are reverted
+Revert all global changes to the archive archive. For now, this only reverts archive comment changes.
+Changes to the file at position index are reverted
+Changes to the file named 'name' are reverted
+Close a Zip archive
+Close a zip entry
+Return the compressed size of a ZZip entry
+Return a string containing the compression method used on a particular entry
+Return the actual filesize of a ZZip entry
+Return the name given a ZZip entry
+Open a Zip File, pointed by the resource entry
+Read from an open directory entry
+Create new zip using source uri for output
+Returns the next file in the archive
+Encode data with the zlib encoding
+Decode gzip encoded data
+Encode data with the raw deflate encoding
+Encode data with the gzip encoding
+Read and uncompress entire .gz-file into an array
+Decode raw deflate encoded data
+Open a .gz-file and return a .gz-file pointer
+Decode zlib encoded data
+Output a .gz-file
+Uncompress any raw/gzip/zlib encoded data
+Compress data with the specified encoding
+Returns the coding type used for output compression
+Sets the maximum time a script can run
+Clean (delete) the current output buffer
+Clean the output buffer, and delete current output buffer
+Flush (send) the output buffer, and delete current output buffer
+Flush (send) contents of the output buffer. The last buffer content is sent to next buffer
+Get current buffer contents and delete current output buffer
+Return the contents of the output buffer
+Get current buffer contents, flush (send) the output buffer, and delete current output buffer
+Return the length of the output buffer
+Return the nesting level of the output buffer
+Turn implicit flush on/off and is equivalent to calling flush() after every output call
+Turn on Output Buffering (specifying an optional output handler).
+Add URL rewriter values
+Reset(clear) URL rewriter values
+Registers a custom URL protocol handler class
+Restore the original protocol handler, overriding if necessary
+Unregister a wrapper for the life of the current request.
+Terminate apache process after this request
+Get a list of loaded Apache modules
+Fetch Apache version
+Perform a partial request of the given URI to obtain information about it
+Get and set Apache request notes
+Fetch all HTTP request headers
+Reset the Apache write timer
+Fetch all HTTP response headers
+Set an Apache subprocess_env variable
+Alias for apache_request_headers()
+Perform an Apache sub-request
+Get a list of loaded Apache modules
+Fetch Apache version
+Get an Apache subprocess_env variable
+Get and set Apache request notes
+Fetch all HTTP response headers
+Set an Apache subprocess_env variable
+Fetch all HTTP request headers
+Perform an apache sub-request
+Get a list of loaded Apache modules
+Fetch Apache version
+Get an Apache subprocess_env variable
+Get and set Apache request notes
+Fetch all HTTP response headers
+Set an Apache subprocess_env variable
+Fetch all HTTP request headers
+Perform an apache sub-request
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Terminate apache process after this request
+Get a list of loaded Apache modules
+Fetch Apache version
+Perform a partial request of the given URI to obtain information about it
+Get and set Apache request notes
+
+
+
+* fetch all headers that go out in case of an error or a subrequest
+Fetch all HTTP request headers
+* fetch all incoming request headers
+* fetch all outgoing request headers
+
+
+
+
+This is a wrapper for ap_sub_run_req and ap_destory_sub_req. It takes sub_request, runs it, destroys it, and returns it's status.
+
+
+
+
+
+Returns sub-request for the specified file. You would need to run it yourself with run().
+Returns sub-request for the specified uri. You would need to run it yourself with run()
+Returns sub-request for the specified file. You would need to run it yourself with run().
+
+Fetch all HTTP response headers
+Set an Apache subprocess_env variable
+
+Perform an Apache sub-request
+Adds a header to the current message.
+Add a recipient to the message envelope.
+Changes a header's value for the current message.
+Removes the named recipient from the current message's envelope.
+Returns the value of the given macro or NULL if the macro is not defined.
+Replaces the body of the current message. If called more than once, subsequent calls result in data being appended to the new body.
+Sets the flags describing the actions the filter may take.
+Directly set the SMTP error reply code for this connection. This code will be used on subsequent error replies resulting from actions taken by this filter.
+Sets the number of seconds libmilter will wait for an MTA connection before timing out a socket.
+Get all headers from the request
+Get all headers from the response
+Perform an NSAPI sub-request
+Dummy function which displays an error when a disabled function is called.
+Checks if the class exists
+Cause the process to crash by copying data to an inaccesible location
+Creates an anonymous function, and returns its name (funny, eh?)
+Return backtrace as array
+Define a new constant
+Check whether a constant exists
+Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element
+Return the current error_reporting level, and if an argument was passed - change to the new level
+Returns true if the named extension is loaded
+Get the $arg_num'th argument that was passed to the function
+Get an array of the arguments that were passed to the function
+Get the number of arguments that were passed to the function
+Checks if the function exists
+Retrieves the class name
+Returns an array of method names for class or class instance.
+Returns an array of default properties of the class.
+Returns an array of all declared classes.
+Returns an array of all declared interfaces.
+Return an array containing the names and values of all defined constants
+Returns an array of all defined functions
+Returns an associative array of names and values of all currently defined variable names (variables in the current scope)
+Returns an array with the names of functions belonging to the named extension
+Returns an array with the file names that were included (includes require and once varieties)
+Return an array containing names of loaded extensions
+Returns an array of object properties
+Retrieves the parent class name for object or class or current scope.
+Get the resource type name for a given resource
+Checks if the class exists
+Returns true if the object is of this class or has this class as one of its parents
+Returns true if the object has this class as one of its parents
+Cause an intentional memory leak, for testing/debugging purposes
+Checks if the class method exists
+Checks if the object or class has a property
+Restores the previously defined error handler function
+Restores the previously defined exception handler function
+Sets a user-defined error handler function. Returns the previously defined error handler, or false on error
+Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error
+Binary safe case-insensitive string comparison
+Binary safe string comparison
+Get string length
+Binary safe string comparison
+Binary safe string comparison
+Generates a user-level error/warning/notice message
+Generic test function
+Returns a unique identifier for the current thread
+Get the version of the Zend Engine
+Get the exception severity
+Clone the exception object
+Obtain the string representation of the Exception object
+Get the exception code
+Get the file in which the exception occurred
+Get the line in which the exception occurred
+Get the exception message
+Get the stack trace for the location in which the exception occurred
+Obtain the backtrace for the exception as a string (instead of an array)
+Exception constructor
+ErrorException constructor
+PHP 5 allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3.14159265358979323846
+2.7182818284590452354
+1.4426950408889634074
+0.43429448190325182765
+0.69314718055994530942
+2.30258509299404568402
+1.57079632679489661923
+0.78539816339744830962
+0.31830988618379067154
+0.63661977236758134308
+1.77245385090551602729
+1.12837916709551257390
+1.41421356237309504880
+1.73205080756887729352
+0.70710678118654752440
+1.14472988584940017414
+0.57721566490153286061
+1
+2
+3
+4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1
+4
+5
+6
+9
+255
+254
+-1
+
+1
+2
+3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Adds text/plain content type headers to encrypted/signed message. If decrypting or verifying, it strips those headers from the output - if the decrypted or verified message is not of MIME type text/plain then an error will occur.
+Normally the input message is converted to "canonical" format which is effectively using CR and LF as end of line: as required by the S/MIME specification. When this options is present, no translation occurs. This is useful when handling binary data which may not be in MIME format.
+When verifying a message, certificates (if any) included in the message are normally searched for the signing certificate. With this option only the certificates specified in the extracerts parameter of openssl_pkcs7_verify are used. The supplied certificates can still be used as untrusted CAs however.
+Do not verify the signers certificate of a signed message.
+Do not chain verification of signers certificates: that is don't use the certificates in the signed message as untrusted CAs.
+When signing a message the signer's certificate is normally included - with this option it is excluded. This will reduce the size of the signed message but the verifier must have a copy of the signers certificate available locally (passed using the extracerts to openssl_pkcs7_verify for example).
+Normally when a message is signed, a set of attributes are included which include the signing time and the supported symmetric algorithms. With this option they are not included.
+When signing a message, use cleartext signing with the MIME type multipart/signed. This is the default if you do not specify any flags to openssl_pkcs7_sign . If you turn this option off, the message will be signed using opaque signing, which is more resistant to translation by mail relays but cannot be read by mail agents that do not support S/MIME.
+Don't try and verify the signatures on a message
+
+
+
+
+
+Phar::SHA512 ( integer )
+Phar::PHPS ( integer )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ERR_NOERR
+ERR_DUPLICATE
+ERR_EOSCAN
+ERR_EMPTY
+ERR_CLOSE
+ERR_WLOCKED
+ERR_LOCKED
+ERR_NOLOCK
+ERR_READ
+ERR_WRITE
+ERR_CREATE
+ERR_LSEEK
+ERR_LENGTH
+ERR_OPEN
+ERR_WOPEN
+ERR_MAGIC
+ERR_VERSION
+ERR_PGSIZE
+ERR_CRC
+ERR_PIPE
+ERR_NIDX
+ERR_MALLOC
+ERR_NUSERS
+ERR_PREEXIT
+ERR_ONTRAP
+ERR_PREPROC
+ERR_DBPARSE
+ERR_DBRUNERR
+ERR_DBPREEXIT
+ERR_WAIT
+ERR_CORRUPT_TUPLE
+ERR_WARNING0
+ERR_PANIC
+ERR_FIFO
+ERR_PERM
+ERR_TCL
+ERR_RESTRICTED
+ERR_USER
+ERR_UNKNOWN
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+1
+2
+3
+4
+5
+7
+8
+9
+10
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Used to turn on-the-fly data compression on with Memcache::set , Memcache::add &listendand; Memcache::replace .
+1 if this Memcache session handler is available, 0 otherwise.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Used with stream_filter_append and stream_filter_prepend to indicate that the specified filter should only be applied when reading
+Used with stream_filter_append and stream_filter_prepend to indicate that the specified filter should only be applied when writing
+This constant is equivalent to STREAM_FILTER_READ | STREAM_FILTER_WRITE
+Return Code indicating that the userspace filter returned buckets in $out .
+Return Code indicating that the userspace filter did not return buckets in $out (i.e. No data available).
+Return Code indicating that the userspace filter encountered an unrecoverable error (i.e. Invalid data received).
+Flag indicating if the stream used the include path.
+Flag indicating if the wrapper is responsible for raising errors using trigger_error during opening of the stream. If this flag is not set, you should not raise any errors.
+Open client socket asynchronously. This option must be used together with the STREAM_CLIENT_CONNECT flag. Used with stream_socket_client .
+Open client socket connection. Client sockets should always include this flag. Used with stream_socket_client .
+Client socket opened with stream_socket_client should remain persistent between page loads.
+Tells a stream created with stream_socket_server to bind to the specified target. Server sockets should always include this flag.
+Tells a stream created with stream_socket_server and bound using the STREAM_SERVER_BIND flag to start listening on the socket. Connection-orientated transports (such as TCP) must use this flag, otherwise the server socket will not be enabled. Using this flag for connect-less transports (such as UDP) is an error.
+A remote address required for this stream has been resolved, or the resolution failed. See severity for an indication of which happened.
+A connection with an external resource has been established.
+Additional authorization is required to access the specified resource. Typical issued with severity level of STREAM_NOTIFY_SEVERITY_ERR .
+The mime-type of resource has been identified, refer to message for a description of the discovered type.
+The size of the resource has been discovered.
+The external resource has redirected the stream to an alternate location. Refer to message .
+Indicates current progress of the stream transfer in bytes_transferred and possibly bytes_max as well.
+There is no more data available on the stream.
+A generic error occurred on the stream, consult message and message_code for details.
+Authorization has been completed (with or without success).
+Normal, non-error related, notification.
+Non critical error condition. Processing may continue.
+A critical error occurred. Processing cannot continue.
+Provides a ICMP socket.
+Provides a IP socket.
+Provides a RAW socket.
+Provides a TCP socket.
+Provides a UDP socket.
+Internet Protocol Version 4 (IPv4).
+Internet Protocol Version 6 (IPv6).
+Unix system internal protocols.
+Provides datagrams, which are connectionless messages (UDP, for example).
+Provides a raw socket, which provides access to internal network protocols and interfaces. Usually this type of socket is just available to the root user.
+Provides a RDM (Reliably-delivered messages) socket.
+Provides a sequenced packet stream socket.
+Provides sequenced, two-way byte streams with a transmission mechanism for out-of-band data (TCP, for example).
+Used with stream_socket_shutdown to disable further receptions. Added in PHP 5.2.1.
+Used with stream_socket_shutdown to disable further transmissions. Added in PHP 5.2.1.
+Used with stream_socket_shutdown to disable further receptions and transmissions. Added in PHP 5.2.1.
+Fatal run-time errors. These indicate errors that can not be recovered from, such as a memory allocation problem. Execution of the script is halted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+no color (black)
+white
+red - supported when terminal is in color mode
+green - supported when terminal is in color mode
+yellow - supported when terminal is in color mode
+blue - supported when terminal is in color mode
+cyan - supported when terminal is in color mode
+magenta - supported when terminal is in color mode
+down arrow
+up arrow
+left arrow
+right arrow
+home key (upward+left arrow)
+backspace
+delete line
+insert line
+delete character
+insert char or enter insert mode
+exit insert char mode
+clear screen
+clear to end of screen
+clear to end of line
+scroll one line forward
+scroll one line backward
+next page
+previous page
+set tab
+clear tab
+clear all tabs
+soft (partial) reset
+reset or hard reset
+print
+lower left
+upper left of keypad
+upper right of keypad
+center of keypad
+lower left of keypad
+lower right of keypad
+back tab
+beginning
+cancel
+close
+cmd (command)
+copy
+create
+end
+exit
+find
+help
+mark
+message
+move
+next
+open
+options
+previous
+redo
+ref (reference)
+refresh
+replace
+restart
+resume
+save
+shiftet beg (beginning)
+shifted cancel
+shifted command
+shifted copy
+shifted create
+shifted delete char
+shifted delete line
+select
+shifted end
+shifted end of line
+shifted exit
+shifted find
+shifted help
+shifted home
+shifted input
+shifted left arrow
+shifted message
+shifted move
+shifted next
+shifted options
+shifted previous
+shifted print
+shifted redo
+shifted replace
+shifted right arrow
+shifted resume
+shifted save
+shifted suspend
+undo
+mouse event has occurred
+maximum key value
+ctrl pressed during click
+shift pressed during click
+alt pressed during click
+report all mouse events
+report mouse position
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+1
+2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The default transaction settings are to be used. This default is determined by the client library, which defines it as IBASE_WRITE|IBASE_CONCURRENCY|IBASE_WAIT in most cases.
+Starts a read-only transaction.
+Starts a read-write transaction.
+Starts a transaction with the isolation level set to 'consistency', which means the transaction cannot read from tables that are being modified by other concurrent transactions.
+Starts a transaction with the isolation level set to 'concurrency' (or 'snapshot'), which means the transaction has access to all tables, but cannot see changes that were committed by other transactions after the transaction was started.
+Starts a transaction with the isolation level set to 'read committed'. This flag should be combined with either IBASE_REC_VERSION or IBASE_REC_NO_VERSION . This isolation level allows access to changes that were committed after the transaction was started. If IBASE_REC_NO_VERSION was specified, only the latest version of a row can be read. If IBASE_REC_VERSION was specified, a row can even be read when a modification to it is pending in a concurrent transaction.
+Indicated that a transaction should wait and retry when a conflict occurs.
+Indicated that a transaction should fail immediately when a conflict occurs.
+Also available as IBASE_TEXT for backward compatibility. Causes BLOB contents to be fetched inline, instead of being fetched as BLOB identifiers.
+Causes arrays to be fetched inline. Otherwise, array identifiers are returned. Array identifiers can only be used as arguments to INSERT operations, as no functions to handle array identifiers are currently available.
+Causes date and time fields not to be returned as strings, but as UNIX timestamps (the number of seconds since the epoch, which is 1-Jan-1970 0:00 UTC). Might be problematic if used with dates before 1970 on some systems.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Unsigned 8-bit PCM.
+Signed 8-bit PCM.
+Unsigned 16-bit PCM. Little Endian byte order.
+Unsigned 16-bit PCM. Big Endian byte order.
+Signed 16-bit PCM. Little Endian byte order.
+Signed 16-bit PCM. Big Endian byte order.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if there is an error while sending data to the system logger, write directly to the system console
+open the connection to the logger immediately
+(default) delay opening the connection until the first message is logged
+
+print log message also to standard error
+include PID with each message
+security/authorization messages (use LOG_AUTHPRIV instead in systems where that constant is defined)
+security/authorization messages (private)
+clock daemon (cron and at)
+other system daemons
+kernel messages
+line printer subsystem
+mail subsystem
+USENET news subsystem
+messages generated internally by syslogd
+generic user-level messages
+UUCP subsystem
+system is unusable
+action must be taken immediately
+critical conditions
+error conditions
+warning conditions
+normal, but significant, condition
+informational message
+debug-level message
+IPv4 Address Resource
+Mail Exchanger Resource
+Alias (Canonical Name) Resource
+Authoritative Name Server Resource
+Pointer Resource
+Host Info Resource (See IANA's Operating System Names for the meaning of these values)
+Start of Authority Resource
+Text Resource
+Any Resource Record. On most systems this returns all resource records, however it should not be counted upon for critical uses. Try DNS_ALL instead.
+IPv6 Address Resource
+Iteratively query the name server for each available record type.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Use compression protocol
+Allow space after function names
+Allow interactive_timeout seconds (instead of wait_timeout) of inactivity before closing the connection.
+Use SSL encryption. This flag is only available with version 4.x of the MySQL client library or newer. Version 3.23.x is bundled both with PHP 4 and Windows binaries of PHP 5.
+Columns are returned into the array having the fieldname as the array index.
+Columns are returned into the array having both a numerical index and the fieldname as the array index.
+Columns are returned into the array having a numerical index to the fields. This index starts with 0, the first field in the result.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+string
+string
+integer
+integer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+KRB5_KDB_DISALLOW_FORWARDABLE
+KRB5_KDB_DISALLOW_RENEWABLE
+KRB5_KDB_DISALLOW_DUP_SKEY
+KRB5_KDB_REQUIRES_PRE_AUTH
+KRB5_KDB_REQUIRES_PWCHANGE
+KRB5_KDB_PWCHANGE_SERVER
+KRB5_KDB_NEW_PRINC
+long
+long
+long
+long
+long
+long
+string
+long
+long
+string
+long
+long
+long
+long
+long
+long
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+integer
+integer
+integer
+integer
+integer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Some value which can be obtained with fstat(1) changed for a file or directory.
+A file or directory was deleted or renamed.
+A file was created in a directory.
+This event never occurs.
+An event in response to fam_cancel_monitor .
+An event upon request to monitor a file or directory. When a directory is monitored, an event for that directory and every file contained in that directory is issued.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1
+2
+4
+8
+16
+32
+64
+128
+256
+example: 1.0.2-dev
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+XMLReader::ENTITY_REF ( integer )
+Document Type node
+Document Fragment node
+Notation node
+Whitespace node
+Significant Whitespace node
+End Element
+End Entity
+XML Declaration node
+Character data with fixed length
+Date, number of days since 1.1.0000
+Short integer (2 Bytes)
+Long integer (4 Bytes)
+same as PX_FIELD_NUMBER
+Double
+Boolean
+Binary large object
+Binary large object (not supported)
+Binary large object
+OLE object (basically a blob, not supported)
+Graphic (basically a blob, not supported)
+time, number of milli seconds since midnight
+timestamp, number of milli seconds since 1.1.0000
+Auto incrementing interger (like PX_FIELD_LONG)
+Decimal number stored in bcd format (not supported)
+Array of Bytes with not more than 255 bytes (not supported)
+Turn all field names into lower case
+Turn all field names into upper case
+Indexed database
+Primary index
+None indexed database
+None incremental secondary index
+Secondary index
+Incremental secondary index
+Non incremental secondary index
+Secondary index
+Non incremental secondary index
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The component name used to initialise the SQLDBC runtime environment.
+The application to be connected to the database.
+The version of the application.
+The SQL mode.
+TRUE, if the connection is an unicode (UCS2) client or FALSE, if not.
+The maximum allowed time of inactivity after which the connection to the database is closed by the system.
+Specifies whether and how shared locks and exclusive locks are implicitly requested or released.
+The number of different request packets used for the connection.
+The number of prepared statements to be cached for the connection for re-use.
+The prefix to use for result tables that are automatically named.
+Columns are returned into the array having the fieldname as the array index.
+Columns are returned into the array having the upper case fieldname as the array index.
+Columns are returned into the array having the lower case fieldname as the array index.
+Columns are returned into the array having both a numerical index and the fieldname as the array index.
+Columns are returned into the array having a numerical index to the fields. This index starts with 0, the first field in the result.
+
+
+
+
+
+
+
+
+
+
+TIDY_TAG_A
+TIDY_TAG_ACRONYM
+TIDY_TAG_APPLET
+TIDY_TAG_B
+TIDY_TAG_BASEFONT
+TIDY_TAG_BGSOUND
+TIDY_TAG_BLINK
+TIDY_TAG_BODY
+TIDY_TAG_BUTTON
+TIDY_TAG_CENTER
+TIDY_TAG_CODE
+TIDY_TAG_COLGROUP
+TIDY_TAG_DD
+TIDY_TAG_DFN
+TIDY_TAG_DIV
+TIDY_TAG_DT
+TIDY_TAG_EMBED
+TIDY_TAG_FONT
+TIDY_TAG_FRAME
+TIDY_TAG_H1
+TIDY_TAG_H3
+TIDY_TAG_H5
+TIDY_TAG_HEAD
+TIDY_TAG_HTML
+TIDY_TAG_IFRAME
+TIDY_TAG_IMG
+TIDY_TAG_INS
+TIDY_TAG_KBD
+TIDY_TAG_LABEL
+TIDY_TAG_LEGEND
+TIDY_TAG_LINK
+TIDY_TAG_MAP
+TIDY_TAG_MENU
+TIDY_TAG_MULTICOL
+TIDY_TAG_NOEMBED
+TIDY_TAG_NOLAYER
+TIDY_TAG_NOSCRIPT
+TIDY_TAG_OL
+TIDY_TAG_OPTION
+TIDY_TAG_PARAM
+TIDY_TAG_PRE
+TIDY_TAG_RP
+TIDY_TAG_RTC
+TIDY_TAG_S
+TIDY_TAG_SCRIPT
+TIDY_TAG_SERVER
+TIDY_TAG_SMALL
+TIDY_TAG_SPAN
+TIDY_TAG_STRONG
+TIDY_TAG_SUB
+TIDY_TAG_TBODY
+TIDY_TAG_TEXTAREA
+TIDY_TAG_TH
+TIDY_TAG_TITLE
+TIDY_TAG_TR
+TIDY_TAG_U
+TIDY_TAG_VAR
+TIDY_TAG_XMP
+TIDY_ATTR_ABBR
+TIDY_ATTR_ACCEPT_CHARSET
+TIDY_ATTR_ACTION
+TIDY_ATTR_ALIGN
+TIDY_ATTR_ALT
+TIDY_ATTR_AXIS
+TIDY_ATTR_BGCOLOR
+TIDY_ATTR_BORDER
+TIDY_ATTR_BOTTOMMARGIN
+TIDY_ATTR_CELLSPACING
+TIDY_ATTR_CHAROFF
+TIDY_ATTR_CHECKED
+TIDY_ATTR_CLASS
+TIDY_ATTR_CLEAR
+TIDY_ATTR_CODEBASE
+TIDY_ATTR_COLOR
+TIDY_ATTR_COLSPAN
+TIDY_ATTR_CONTENT
+TIDY_ATTR_DATA
+TIDY_ATTR_DATAPAGESIZE
+TIDY_ATTR_DATETIME
+TIDY_ATTR_DEFER
+TIDY_ATTR_DISABLED
+TIDY_ATTR_ENCTYPE
+TIDY_ATTR_FOR
+TIDY_ATTR_FRAMEBORDER
+TIDY_ATTR_GRIDX
+TIDY_ATTR_HEADERS
+TIDY_ATTR_HREF
+TIDY_ATTR_HSPACE
+TIDY_ATTR_ID
+TIDY_ATTR_LABEL
+TIDY_ATTR_LANGUAGE
+TIDY_ATTR_LAST_VISIT
+TIDY_ATTR_LINK
+TIDY_ATTR_LOWSRC
+TIDY_ATTR_MARGINWIDTH
+TIDY_ATTR_MEDIA
+TIDY_ATTR_MULTIPLE
+TIDY_ATTR_NOHREF
+TIDY_ATTR_NOSHADE
+TIDY_ATTR_OBJECT
+TIDY_ATTR_PROMPT
+TIDY_ATTR_READONLY
+TIDY_ATTR_REV
+TIDY_ATTR_ROWS
+TIDY_ATTR_RULES
+TIDY_ATTR_SCOPE
+TIDY_ATTR_SELECTED
+TIDY_ATTR_SHOWGRID
+TIDY_ATTR_SHOWGRIDY
+TIDY_ATTR_SPAN
+TIDY_ATTR_STANDBY
+TIDY_ATTR_STYLE
+TIDY_ATTR_TABINDEX
+TIDY_ATTR_TEXT
+TIDY_ATTR_TOPMARGIN
+TIDY_ATTR_USEMAP
+TIDY_ATTR_VALUE
+TIDY_ATTR_VERSION
+TIDY_ATTR_VSPACE
+TIDY_ATTR_WRAP
+TIDY_ATTR_XML_SPACE
+constant
+root node
+doctype
+HTML comment
+Processing Instruction
+Text
+start tag
+end tag
+empty tag
+CDATA
+XML section
+ASP code
+JSTE code
+PHP code
+XML declaration
+hotkey defined by newt_form_add_hot_key was pressed
+some component has caused form to exit
+file descriptor specified in newt_form_watch_fd is ready to be read or written to
+time specified in newt_form_set_timer has elapsed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Exit form, when component is activated
+Component is hidden
+Component is scrollable
+Component is disabled
+
+Wrap text
+Don't exit form on pressing F12
+
+Component is selected
+Component is checkbox
+Entry component is password entry
+Show cursor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wrap text in the textbox
+Scroll text in the textbox
+Don't exit form on F12 press
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Orders results so that $matches[0] is an array of full pattern matches, $matches[1] is an array of strings matched by the first parenthesized subpattern, and so on. This flag is only used with preg_match_all .
+Orders results so that $matches[0] is an array of first set of matches, $matches[1] is an array of second set of matches, and so on. This flag is only used with preg_match_all .
+See the description of PREG_SPLIT_OFFSET_CAPTURE . This flag is available since PHP 4.3.0.
+This flag tells preg_split to return only non-empty pieces.
+This flag tells preg_split to capture parenthesized expression in the delimiter pattern as well. This flag is available since PHP 4.0.5.
+If this flag is set, for every occurring match the appendant string offset will also be returned. Note that this changes the return values in an array where every element is an array consisting of the matched string at offset 0 and its string offset within subject at offset 1. This flag is available since PHP 4.3.0 and is only used for preg_split .
+Returned by preg_last_error if there were no errors. Available since PHP 5.2.0.
+Returned by preg_last_error if there was an internal PCRE error. Available since PHP 5.2.0.
+Returned by preg_last_error if <link linkend="ini.pcre.backtrack-limit">backtrack limit was exhausted. Available since PHP 5.2.0.
+Returned by preg_last_error if <link linkend="ini.pcre.recursion-limit">recursion limit was exhausted. Available since PHP 5.2.0.
+Returned by preg_last_error if the last error was caused by malformed UTF-8 data (only when running a regex in <link linkend="reference.pcre.pattern.modifiers">UTF-8 mode ). Available since PHP 5.2.0.
+Returned by preg_last_error if the offset didn't correspond to the begin of a valid UTF-8 code point (only when running a regex in UTF-8 mode ). Available since PHP 5.3.0.
+PCRE version and release date (e.g. "7.0 18-Dec-2006"). Available since PHP 5.2.4.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1
+2
+4
+8
+16
+32
+64
+-1
+1
+2
+4
+8
+16
+32
+64
+-1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/togglepresentation.gif b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/togglepresentation.gif
new file mode 100644
index 0000000..a0831f0
Binary files /dev/null and b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/togglepresentation.gif differ
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/HTMLWordDetector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/HTMLWordDetector.java
new file mode 100644
index 0000000..517c1c7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/HTMLWordDetector.java
@@ -0,0 +1,38 @@
+package net.sourceforge.phpeclipse.phpeditor.util;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.rules.IWordDetector;
+
+/**
+ * A Java aware word detector.
+ */
+public class HTMLWordDetector implements IWordDetector {
+
+ /*
+ * (non-Javadoc) Method declared on IWordDetector.
+ */
+ public boolean isWordPart(char character) {
+ return Scanner.isPHPIdentifierPart(character) || (character == '/')
+ || (character == '>');
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWordDetector.
+ */
+ public boolean isWordStart(char character) {
+ return character == '<';
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPColorProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPColorProvider.java
new file mode 100644
index 0000000..972a207
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPColorProvider.java
@@ -0,0 +1,86 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Manager for colors used in the Java editor
+ */
+public class PHPColorProvider {
+
+ public static final RGB MULTI_LINE_COMMENT = new RGB(63, 127, 95);
+
+ public static final RGB SINGLE_LINE_COMMENT = new RGB(63, 127, 95);
+
+ public static final RGB TAG = new RGB(255, 0, 128);
+
+ public static final RGB KEYWORD = new RGB(127, 0, 85);
+
+ public static final RGB VARIABLE = new RGB(127, 159, 191);
+
+ public static final /*RGB*/String FUNCTION_NAME = "127, 127, 159"; //new RGB(127, 127, 159);
+
+ public static final RGB STRING_DQ = new RGB(42, 0, 255);
+
+ public static final RGB STRING_SQ = new RGB(42, 0, 255);
+
+ public static final RGB DEFAULT = new RGB(0, 0, 0);
+
+ public static final RGB TYPE = new RGB(127, 0, 85);
+
+ public static final RGB CONSTANT = new RGB(127, 0, 85);
+
+ public static final RGB BACKGROUND = new RGB(255, 255, 255);
+
+ // public static final RGB LINKED_POSITION_COLOR = new RGB(0, 0, 0);
+
+ // public static final RGB LINE_NUMBER_COLOR = new RGB(0, 0, 0);
+ // public static final RGB BACKGROUND_COLOR = new RGB(255, 255, 255);
+
+ public static final RGB PHPDOC_TAG = new RGB(63, 127, 95);
+
+ public static final RGB PHPDOC_LINK = new RGB(63, 63, 191);
+
+ public static final RGB PHPDOC_DEFAULT = new RGB(63, 95, 191);
+
+ public static final RGB PHPDOC_KEYWORD = new RGB(127, 159, 191);
+
+ protected Map fColorTable = new HashMap(10);
+
+ /**
+ * Release all of the color resources held onto by the receiver.
+ */
+ public void dispose() {
+ Iterator e = fColorTable.values().iterator();
+ while (e.hasNext())
+ ((Color) e.next()).dispose();
+ }
+
+ /**
+ * Return the Color that is stored in the Color table as rgb.
+ */
+ public Color getColor(RGB rgb) {
+ Color color = (Color) fColorTable.get(rgb);
+ if (color == null) {
+ color = new Color(Display.getCurrent(), rgb);
+ fColorTable.put(rgb, color);
+ }
+ return color;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPVariableDetector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPVariableDetector.java
new file mode 100644
index 0000000..b1c4b1b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPVariableDetector.java
@@ -0,0 +1,37 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.util;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.rules.IWordDetector;
+
+/**
+ * A PHP aware variable detector (i.e. a PHP identifier starting with a '$'
+ * character).
+ */
+public class PHPVariableDetector implements IWordDetector {
+
+ /*
+ * (non-Javadoc) Method declared on IWordDetector.
+ */
+ public boolean isWordPart(char character) {
+ return Scanner.isPHPIdentifierPart(character);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWordDetector.
+ */
+ public boolean isWordStart(char character) {
+ return character == '$';
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPWhitespaceDetector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPWhitespaceDetector.java
new file mode 100644
index 0000000..65337cf
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPWhitespaceDetector.java
@@ -0,0 +1,27 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.util;
+
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+
+/**
+ * A java aware white space detector.
+ */
+public class PHPWhitespaceDetector implements IWhitespaceDetector {
+
+ /*
+ * (non-Javadoc) Method declared on IWhitespaceDetector
+ */
+ public boolean isWhitespace(char character) {
+ return Character.isWhitespace(character);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPWordDetector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPWordDetector.java
new file mode 100644
index 0000000..c799309
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/phpeditor/util/PHPWordDetector.java
@@ -0,0 +1,36 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor.util;
+
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.eclipse.jface.text.rules.IWordDetector;
+
+/**
+ * A PHP aware word detector.
+ */
+public class PHPWordDetector implements IWordDetector {
+
+ /*
+ * (non-Javadoc) Method declared on IWordDetector.
+ */
+ public boolean isWordPart(char character) {
+ return Scanner.isPHPIdentifierPart(character);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWordDetector.
+ */
+ public boolean isWordStart(char character) {
+ return Scanner.isPHPIdentOrVarStart(character);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/ColorEditor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/ColorEditor.java
new file mode 100644
index 0000000..5a2cef9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/ColorEditor.java
@@ -0,0 +1,120 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpeclipse.preferences;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.ColorDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A "button" of a certain color determined by the color picker.
+ */
+public class ColorEditor {
+
+ private Point fExtent;
+
+ private Image fImage;
+
+ private RGB fColorValue;
+
+ private Color fColor;
+
+ private Button fButton;
+
+ public ColorEditor(Composite parent) {
+
+ fButton = new Button(parent, SWT.PUSH);
+ fExtent = computeImageSize(parent);
+ fImage = new Image(parent.getDisplay(), fExtent.x, fExtent.y);
+
+ GC gc = new GC(fImage);
+ gc.setBackground(fButton.getBackground());
+ gc.fillRectangle(0, 0, fExtent.x, fExtent.y);
+ gc.dispose();
+
+ fButton.setImage(fImage);
+ fButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ ColorDialog colorDialog = new ColorDialog(fButton.getShell());
+ colorDialog.setRGB(fColorValue);
+ RGB newColor = colorDialog.open();
+ if (newColor != null) {
+ fColorValue = newColor;
+ updateColorImage();
+ }
+ }
+ });
+
+ fButton.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent event) {
+ if (fImage != null) {
+ fImage.dispose();
+ fImage = null;
+ }
+ if (fColor != null) {
+ fColor.dispose();
+ fColor = null;
+ }
+ }
+ });
+ }
+
+ public RGB getColorValue() {
+ return fColorValue;
+ }
+
+ public void setColorValue(RGB rgb) {
+ fColorValue = rgb;
+ updateColorImage();
+ }
+
+ public Button getButton() {
+ return fButton;
+ }
+
+ protected void updateColorImage() {
+
+ Display display = fButton.getDisplay();
+
+ GC gc = new GC(fImage);
+ gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
+ gc.drawRectangle(0, 2, fExtent.x - 1, fExtent.y - 4);
+
+ if (fColor != null)
+ fColor.dispose();
+
+ fColor = new Color(display, fColorValue);
+ gc.setBackground(fColor);
+ gc.fillRectangle(1, 3, fExtent.x - 2, fExtent.y - 5);
+ gc.dispose();
+
+ fButton.setImage(fImage);
+ }
+
+ protected Point computeImageSize(Control window) {
+ GC gc = new GC(window);
+ Font f = JFaceResources.getFontRegistry().get(
+ JFaceResources.DEFAULT_FONT);
+ gc.setFont(f);
+ int height = gc.getFontMetrics().getHeight();
+ gc.dispose();
+ Point p = new Point(height * 3 - 6, height);
+ return p;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/OverlayPreferenceStore.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/OverlayPreferenceStore.java
new file mode 100644
index 0000000..917e813
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/OverlayPreferenceStore.java
@@ -0,0 +1,456 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+package net.sourceforge.phpeclipse.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * An overlaying preference store.
+ */
+public class OverlayPreferenceStore implements IPreferenceStore {
+
+ public static final class TypeDescriptor {
+ private TypeDescriptor() {
+ }
+ };
+
+ public static final TypeDescriptor BOOLEAN = new TypeDescriptor();
+
+ public static final TypeDescriptor DOUBLE = new TypeDescriptor();
+
+ public static final TypeDescriptor FLOAT = new TypeDescriptor();
+
+ public static final TypeDescriptor INT = new TypeDescriptor();
+
+ public static final TypeDescriptor LONG = new TypeDescriptor();
+
+ public static final TypeDescriptor STRING = new TypeDescriptor();
+
+ public static class OverlayKey {
+
+ TypeDescriptor fDescriptor;
+
+ String fKey;
+
+ public OverlayKey(TypeDescriptor descriptor, String key) {
+ fDescriptor = descriptor;
+ fKey = key;
+ }
+ };
+
+ private class PropertyListener implements IPropertyChangeListener {
+
+ /*
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ OverlayKey key = findOverlayKey(event.getProperty());
+ if (key != null)
+ propagateProperty(fParent, key, fStore);
+ }
+ };
+
+ private IPreferenceStore fParent;
+
+ private IPreferenceStore fStore;
+
+ private OverlayKey[] fOverlayKeys;
+
+ private PropertyListener fPropertyListener;
+
+ public OverlayPreferenceStore(IPreferenceStore parent,
+ OverlayKey[] overlayKeys) {
+ fParent = parent;
+ fOverlayKeys = overlayKeys;
+ fStore = new PreferenceStore();
+ }
+
+ private OverlayKey findOverlayKey(String key) {
+ for (int i = 0; i < fOverlayKeys.length; i++) {
+ if (fOverlayKeys[i].fKey.equals(key))
+ return fOverlayKeys[i];
+ }
+ return null;
+ }
+
+ private boolean covers(String key) {
+ return (findOverlayKey(key) != null);
+ }
+
+ private void propagateProperty(IPreferenceStore orgin, OverlayKey key,
+ IPreferenceStore target) {
+
+ if (orgin.isDefault(key.fKey)) {
+ if (!target.isDefault(key.fKey))
+ target.setToDefault(key.fKey);
+ return;
+ }
+
+ TypeDescriptor d = key.fDescriptor;
+ if (BOOLEAN == d) {
+
+ boolean originValue = orgin.getBoolean(key.fKey);
+ boolean targetValue = target.getBoolean(key.fKey);
+ if (targetValue != originValue)
+ target.setValue(key.fKey, originValue);
+
+ } else if (DOUBLE == d) {
+
+ double originValue = orgin.getDouble(key.fKey);
+ double targetValue = target.getDouble(key.fKey);
+ if (targetValue != originValue)
+ target.setValue(key.fKey, originValue);
+
+ } else if (FLOAT == d) {
+
+ float originValue = orgin.getFloat(key.fKey);
+ float targetValue = target.getFloat(key.fKey);
+ if (targetValue != originValue)
+ target.setValue(key.fKey, originValue);
+
+ } else if (INT == d) {
+
+ int originValue = orgin.getInt(key.fKey);
+ int targetValue = target.getInt(key.fKey);
+ if (targetValue != originValue)
+ target.setValue(key.fKey, originValue);
+
+ } else if (LONG == d) {
+
+ long originValue = orgin.getLong(key.fKey);
+ long targetValue = target.getLong(key.fKey);
+ if (targetValue != originValue)
+ target.setValue(key.fKey, originValue);
+
+ } else if (STRING == d) {
+
+ String originValue = orgin.getString(key.fKey);
+ String targetValue = target.getString(key.fKey);
+ if (targetValue != null && originValue != null
+ && !targetValue.equals(originValue))
+ target.setValue(key.fKey, originValue);
+
+ }
+ }
+
+ public void propagate() {
+ for (int i = 0; i < fOverlayKeys.length; i++)
+ propagateProperty(fStore, fOverlayKeys[i], fParent);
+ }
+
+ private void loadProperty(IPreferenceStore orgin, OverlayKey key,
+ IPreferenceStore target, boolean forceInitialization) {
+ TypeDescriptor d = key.fDescriptor;
+ if (BOOLEAN == d) {
+
+ if (forceInitialization)
+ target.setValue(key.fKey, true);
+ target.setValue(key.fKey, orgin.getBoolean(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultBoolean(key.fKey));
+
+ } else if (DOUBLE == d) {
+
+ if (forceInitialization)
+ target.setValue(key.fKey, 1.0D);
+ target.setValue(key.fKey, orgin.getDouble(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultDouble(key.fKey));
+
+ } else if (FLOAT == d) {
+
+ if (forceInitialization)
+ target.setValue(key.fKey, 1.0F);
+ target.setValue(key.fKey, orgin.getFloat(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultFloat(key.fKey));
+
+ } else if (INT == d) {
+
+ if (forceInitialization)
+ target.setValue(key.fKey, 1);
+ target.setValue(key.fKey, orgin.getInt(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultInt(key.fKey));
+
+ } else if (LONG == d) {
+
+ if (forceInitialization)
+ target.setValue(key.fKey, 1L);
+ target.setValue(key.fKey, orgin.getLong(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultLong(key.fKey));
+
+ } else if (STRING == d) {
+
+ if (forceInitialization)
+ target.setValue(key.fKey, "1"); //$NON-NLS-1$
+ target.setValue(key.fKey, orgin.getString(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultString(key.fKey));
+
+ }
+ }
+
+ public void load() {
+ for (int i = 0; i < fOverlayKeys.length; i++)
+ loadProperty(fParent, fOverlayKeys[i], fStore, true);
+ }
+
+ public void loadDefaults() {
+ for (int i = 0; i < fOverlayKeys.length; i++)
+ setToDefault(fOverlayKeys[i].fKey);
+ }
+
+ public void start() {
+ if (fPropertyListener == null) {
+ fPropertyListener = new PropertyListener();
+ fParent.addPropertyChangeListener(fPropertyListener);
+ }
+ }
+
+ public void stop() {
+ if (fPropertyListener != null) {
+ fParent.removePropertyChangeListener(fPropertyListener);
+ fPropertyListener = null;
+ }
+ }
+
+ /*
+ * @see IPreferenceStore#addPropertyChangeListener(IPropertyChangeListener)
+ */
+ public void addPropertyChangeListener(IPropertyChangeListener listener) {
+ fStore.addPropertyChangeListener(listener);
+ }
+
+ /*
+ * @see IPreferenceStore#removePropertyChangeListener(IPropertyChangeListener)
+ */
+ public void removePropertyChangeListener(IPropertyChangeListener listener) {
+ fStore.removePropertyChangeListener(listener);
+ }
+
+ /*
+ * @see IPreferenceStore#firePropertyChangeEvent(String, Object, Object)
+ */
+ public void firePropertyChangeEvent(String name, Object oldValue,
+ Object newValue) {
+ fStore.firePropertyChangeEvent(name, oldValue, newValue);
+ }
+
+ /*
+ * @see IPreferenceStore#contains(String)
+ */
+ public boolean contains(String name) {
+ return fStore.contains(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getBoolean(String)
+ */
+ public boolean getBoolean(String name) {
+ return fStore.getBoolean(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getDefaultBoolean(String)
+ */
+ public boolean getDefaultBoolean(String name) {
+ return fStore.getDefaultBoolean(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getDefaultDouble(String)
+ */
+ public double getDefaultDouble(String name) {
+ return fStore.getDefaultDouble(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getDefaultFloat(String)
+ */
+ public float getDefaultFloat(String name) {
+ return fStore.getDefaultFloat(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getDefaultInt(String)
+ */
+ public int getDefaultInt(String name) {
+ return fStore.getDefaultInt(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getDefaultLong(String)
+ */
+ public long getDefaultLong(String name) {
+ return fStore.getDefaultLong(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getDefaultString(String)
+ */
+ public String getDefaultString(String name) {
+ return fStore.getDefaultString(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getDouble(String)
+ */
+ public double getDouble(String name) {
+ return fStore.getDouble(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getFloat(String)
+ */
+ public float getFloat(String name) {
+ return fStore.getFloat(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getInt(String)
+ */
+ public int getInt(String name) {
+ return fStore.getInt(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getLong(String)
+ */
+ public long getLong(String name) {
+ return fStore.getLong(name);
+ }
+
+ /*
+ * @see IPreferenceStore#getString(String)
+ */
+ public String getString(String name) {
+ return fStore.getString(name);
+ }
+
+ /*
+ * @see IPreferenceStore#isDefault(String)
+ */
+ public boolean isDefault(String name) {
+ return fStore.isDefault(name);
+ }
+
+ /*
+ * @see IPreferenceStore#needsSaving()
+ */
+ public boolean needsSaving() {
+ return fStore.needsSaving();
+ }
+
+ /*
+ * @see IPreferenceStore#putValue(String, String)
+ */
+ public void putValue(String name, String value) {
+ if (covers(name))
+ fStore.putValue(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setDefault(String, double)
+ */
+ public void setDefault(String name, double value) {
+ if (covers(name))
+ fStore.setDefault(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setDefault(String, float)
+ */
+ public void setDefault(String name, float value) {
+ if (covers(name))
+ fStore.setDefault(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setDefault(String, int)
+ */
+ public void setDefault(String name, int value) {
+ if (covers(name))
+ fStore.setDefault(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setDefault(String, long)
+ */
+ public void setDefault(String name, long value) {
+ if (covers(name))
+ fStore.setDefault(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setDefault(String, String)
+ */
+ public void setDefault(String name, String value) {
+ if (covers(name))
+ fStore.setDefault(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setDefault(String, boolean)
+ */
+ public void setDefault(String name, boolean value) {
+ if (covers(name))
+ fStore.setDefault(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setToDefault(String)
+ */
+ public void setToDefault(String name) {
+ fStore.setToDefault(name);
+ }
+
+ /*
+ * @see IPreferenceStore#setValue(String, double)
+ */
+ public void setValue(String name, double value) {
+ if (covers(name))
+ fStore.setValue(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setValue(String, float)
+ */
+ public void setValue(String name, float value) {
+ if (covers(name))
+ fStore.setValue(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setValue(String, int)
+ */
+ public void setValue(String name, int value) {
+ if (covers(name))
+ fStore.setValue(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setValue(String, long)
+ */
+ public void setValue(String name, long value) {
+ if (covers(name))
+ fStore.setValue(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setValue(String, String)
+ */
+ public void setValue(String name, String value) {
+ if (covers(name))
+ fStore.setValue(name, value);
+ }
+
+ /*
+ * @see IPreferenceStore#setValue(String, boolean)
+ */
+ public void setValue(String name, boolean value) {
+ if (covers(name))
+ fStore.setValue(name, value);
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.java
new file mode 100644
index 0000000..1c60d30
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.java
@@ -0,0 +1,42 @@
+package net.sourceforge.phpeclipse.preferences;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class PHPPreferencesMessages {
+
+ private static final String RESOURCE_BUNDLE = PHPPreferencesMessages.class
+ .getName();
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private PHPPreferencesMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * 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 });
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.properties
new file mode 100644
index 0000000..6d1f225
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPPreferencesMessages.properties
@@ -0,0 +1,94 @@
+#########################################
+# PHPProjectLibraryPage
+#########################################
+
+PHPProjectLibraryPage.elementNotIProject=ERROR: Element not IProject
+PHPProjectLibraryPage.project=Project
+PHPProjectLibraryPage.tabName=Projects
+
+
+#########################################
+# Property Pages
+#########################################
+
+PHPProjectPropertyPage.phpProjectClosed=The project selected is a PHP project, but is closed.
+PHPProjectPropertyPage.performOkExceptionDialogTitle=Unable to save
+PHPProjectPropertyPage.performOkExceptionDialogMessage=ERROR: Unable to save project properties.
+
+PHPMiscProjectPreferences.localhost=Localhost
+PHPMiscProjectPreferences.documentroot=DocumentRoot
+PHPMiscProjectPreferences.bookmark=SQL default bookmark:
+
+PHPMiscProjectPreferences.obfuscator=Obfuscator directory:
+
+PHPPreviewProjectPreferences.auto_preview=Refresh PHP browser view when opening editor
+PHPPreviewProjectPreferences.bring_to_top_preview=Show PHP browser view when opening editor
+PHPPreviewProjectPreferences.show_html_files_local=Show HTML files as local resources (no 'http://' url)
+
+#########################################
+# Preference Pages
+#########################################
+PHPBasePreferencePage.description=PHP Preferences
+PHPBasePreferencePage.websettingsGroup=Webserver Settings
+PHPBasePreferencePage.websettingsGroup.localhost=Localhost
+PHPBasePreferencePage.websettingsGroup.docroot=DocumentRoot
+PHPBasePreferencePage.websettingsGroup.browser=External browser command
+PHPBasePreferencePage.websettingsGroup.useexternal=Use external browser
+#PHPBasePreferencePage.websettingsGroup.showexternalpreview=Show preview on editor load (win32 only)
+PHPBasePreferencePage.apacheGroup=Apache Settings
+PHPBasePreferencePage.apacheGroup.xampp_start=XAMPP Start
+PHPBasePreferencePage.apacheGroup.xampp_stop=XAMPP Stop
+PHPBasePreferencePage.apacheGroup.run=Apache
+PHPBasePreferencePage.apacheGroup.httpdconf=httpd.conf
+PHPBasePreferencePage.apacheGroup.etchosts=etc/hosts
+PHPBasePreferencePage.apacheGroup.start=Start Apache
+PHPBasePreferencePage.apacheGroup.start_background=Run in background mode
+PHPBasePreferencePage.apacheGroup.stop=Stop Apache
+PHPBasePreferencePage.apacheGroup.stop_background=Run in background mode
+PHPBasePreferencePage.apacheGroup.restart=Restart Apache
+PHPBasePreferencePage.apacheGroup.restart_background=Run in background mode
+PHPBasePreferencePage.console.php=Run PHP command
+PHPBasePreferencePage.mySQLGroup=MySQL Settings
+PHPBasePreferencePage.mySQLGroup.run=MySQL
+PHPBasePreferencePage.mySQLGroup.start_background=Run in background mode
+PHPBasePreferencePage.mySQLGroup.command=Start MySQL
+PHPBasePreferencePage.parsers=Parsing settings
+PHPBasePreferencePage.parsers.pos=Parse on save
+PHPBasePreferencePage.parsers.external=External
+PHPBasePreferencePage.parsers.internal=Internal
+PHPBasePreferencePage.parsers.extcommand=Parser command
+PHPBasePreferencePage.parsers.choose=Choose PHP Parser
+PHPBasePreferencePage.phpExtensionPrefs=PHP file extensions (internal Parser)
+
+PHPEditorSyntaxPreferencePage.description:PHP Editor Preferences
+PHPEditorSyntaxPreferencePage.background:Background settings
+PHPEditorSyntaxPreferencePage.foreground:Foreground settings
+PHPEditorSyntaxPreferencePage.syntax:Syntax highlighting
+PHPEditorSyntaxPreferencePage.color:Colour
+PHPEditorSyntaxPreferencePage.bold:Bold
+PHPEditorSyntaxPreferencePage.italic:Italic
+PHPEditorSyntaxPreferencePage.underline:Underline
+PHPEditorSyntaxPreferencePage.multiLineComment=Multi-line comment
+PHPEditorSyntaxPreferencePage.singleLineComment=Single-line comment
+PHPEditorSyntaxPreferencePage.tags=PHP Tags
+PHPEditorSyntaxPreferencePage.keywords=Keywords
+PHPEditorSyntaxPreferencePage.variables='$' Variables
+PHPEditorSyntaxPreferencePage.variables_dollar='$_' Variables
+PHPEditorSyntaxPreferencePage.types=Types
+PHPEditorSyntaxPreferencePage.functions=Functions
+PHPEditorSyntaxPreferencePage.constants=Constants
+PHPEditorSyntaxPreferencePage.strings_dq=Double Quoted Strings
+PHPEditorSyntaxPreferencePage.strings_sq=Single Quoted Strings
+PHPEditorSyntaxPreferencePage.others=Others
+PHPEditorSyntaxPreferencePage.syntaxdialog=Custom PHP Syntax File:
+PHPEditorSyntaxPreferencePage.browse=Browse..
+PHPEditorSyntaxPreferencePage.textfont=Text font
+
+PHPLanguagePreferencePage.description=PHP Editor Language
+PHPLanguagePreferencePage.preflingo=PHP Language Preference
+PHPLanguagePreferencePage.choose=Choose Language
+PHPLanguagePreferencePage.english=English
+PHPLanguagePreferencePage.german=German
+PHPLanguagePreferencePage.french=French
+PHPLanguagePreferencePage.spanish=Spanish
+PHPLanguagePreferencePage.japanese=Japanese
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPProjectLibraryPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPProjectLibraryPage.java
new file mode 100644
index 0000000..9922f48
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPProjectLibraryPage.java
@@ -0,0 +1,165 @@
+package net.sourceforge.phpeclipse.preferences;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.core.JavaProject;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.ide.IDE.SharedImages;
+
+public class PHPProjectLibraryPage {
+ protected JavaProject workingProject;
+
+ protected PHPProjectLibraryPage(JavaProject theWorkingProject) {
+ super();
+ workingProject = theWorkingProject;
+ }
+
+ protected Control getControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new FillLayout());
+
+ Table projectsTable = new Table(composite, SWT.CHECK | SWT.BORDER
+ | SWT.MULTI | SWT.FULL_SELECTION);
+ projectsTable.setHeaderVisible(false);
+ projectsTable.setLinesVisible(false);
+ projectsTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+ TableColumn tableColumn = new TableColumn(projectsTable, SWT.NONE);
+ tableColumn.setWidth(200);
+ tableColumn.setText(PHPPreferencesMessages
+ .getString("PHPEditorPreferencePageLibraryPage.project")); //$NON-NLS-1$
+
+ CheckboxTableViewer projectsTableViewer = new CheckboxTableViewer(
+ projectsTable);
+ projectsTableViewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ projectCheckedUnchecked(event);
+ }
+ });
+
+ projectsTableViewer.setContentProvider(getContentProvider());
+ projectsTableViewer.setLabelProvider(getLabelProvider());
+
+ projectsTableViewer.setInput(getWorkspaceProjects());
+ projectsTableViewer.setCheckedElements(workingProject
+ .getReferencedProjects().toArray());
+
+ return composite;
+ }
+
+ protected void projectCheckedUnchecked(CheckStateChangedEvent event) {
+ IProject checkEventProject = (IProject) event.getElement();
+ if (event.getChecked())
+ getWorkingProject().addLoadPathEntry(checkEventProject);
+ else
+ getWorkingProject().removeLoadPathEntry(checkEventProject);
+ }
+
+ protected JavaProject getWorkingProject() {
+ return workingProject;
+ }
+
+ protected List getWorkspaceProjects() {
+ IWorkspaceRoot root = PHPeclipsePlugin.getWorkspace().getRoot();
+ return Arrays.asList(root.getProjects());
+ }
+
+ protected ITableLabelProvider getLabelProvider() {
+ ITableLabelProvider labelProvider = new ITableLabelProvider() {
+ public Image getColumnImage(Object element, int columnIndex) {
+ IWorkbench workbench = WebUI.getDefault()
+ .getWorkbench();
+ return workbench.getSharedImages().getImage(
+ SharedImages.IMG_OBJ_PROJECT);
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ if (element instanceof IProject)
+ return ((IProject) element).getName();
+
+ return PHPPreferencesMessages
+ .getString("PHPEditorPreferencePageLibraryPage.elementNotIProject"); //$NON-NLS-1$
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+ };
+
+ return labelProvider;
+ }
+
+ protected IContentProvider getContentProvider() {
+ IStructuredContentProvider contentProvider = new IStructuredContentProvider() {
+ protected List PHPEditorPreferencePages;
+
+ public Object[] getElements(Object inputElement) {
+ return PHPEditorPreferencePages.toArray();
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput,
+ Object newInput) {
+ PHPEditorPreferencePages = new ArrayList();
+
+ if (!(newInput instanceof List))
+ return;
+
+ Iterator workspaceProjectsIterator = ((List) newInput)
+ .iterator();
+ while (workspaceProjectsIterator.hasNext()) {
+ Object anObject = workspaceProjectsIterator.next();
+ if (anObject instanceof IProject) {
+ IProject project = (IProject) anObject;
+ if (project.getName() != workingProject.getProject()
+ .getName()) {
+ try {
+ if (project
+ .hasNature(PHPeclipsePlugin.PHP_NATURE_ID))
+ PHPEditorPreferencePages.add(project);
+ } catch (CoreException e) {
+ }
+ }
+ }
+ }
+ }
+ };
+
+ return contentProvider;
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPProjectPropertyPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPProjectPropertyPage.java
new file mode 100644
index 0000000..2f3ba51
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/preferences/PHPProjectPropertyPage.java
@@ -0,0 +1,102 @@
+package net.sourceforge.phpeclipse.preferences;
+
+import net.sourceforge.phpdt.internal.core.JavaProject;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.swt.SWT;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+public class PHPProjectPropertyPage extends PropertyPage implements
+ IWorkbenchPropertyPage {
+ protected PHPProjectLibraryPage projectsPage;
+
+ protected JavaProject workingProject;
+
+ public PHPProjectPropertyPage() {
+ }
+
+ protected Control createContents(Composite parent) {
+ noDefaultAndApplyButton();
+
+ workingProject = getPHPProject();
+ if (workingProject == null || !workingProject.getProject().isOpen())
+ return createClosedProjectPageContents(parent);
+
+ return createProjectPageContents(parent);
+ }
+
+ protected JavaProject getPHPProject() {
+ IAdaptable selectedElement = getElement();
+ if (selectedElement == null)
+ return null;
+
+ if (selectedElement instanceof JavaProject)
+ return (JavaProject) selectedElement;
+
+ if (selectedElement instanceof IProject) {
+ IProject simpleProject = (IProject) selectedElement;
+ try {
+ if (simpleProject.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
+ JavaProject phpProject = new JavaProject();
+ phpProject.setProject(simpleProject);
+ return phpProject;
+ }
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+
+ return null;
+ }
+
+ protected Control createClosedProjectPageContents(Composite parent) {
+ Label label = new Label(parent, SWT.NONE);
+ label.setText(PHPPreferencesMessages
+ .getString("PHPProjectPropertyPage.phpProjectClosed")); //$NON-NLS-1$
+
+ return label;
+ }
+
+ protected Control createProjectPageContents(Composite parent) {
+ TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
+ tabFolder.setLayout(new GridLayout());
+ tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
+ tabFolder.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ // tabChanged(e.item);
+ }
+ });
+
+ projectsPage = new PHPProjectLibraryPage(workingProject);
+ TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
+ tabItem.setText(PHPPreferencesMessages
+ .getString("PHPProjectLibraryPage.tabName")); //$NON-NLS-1$
+ // tabItem.setData(projectsPage);
+ tabItem.setControl(projectsPage.getControl(tabFolder));
+
+ return tabFolder;
+ }
+
+ public boolean performOk() {
+ try {
+ projectsPage.getWorkingProject().save();
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ return super.performOk();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/HTMLFileWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/HTMLFileWizard.java
new file mode 100644
index 0000000..b4f5554
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/HTMLFileWizard.java
@@ -0,0 +1,194 @@
+package net.sourceforge.phpeclipse.wizards;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContext;
+import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContextType;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+/**
+ * This wizard creates one file with the extension "html".
+ */
+public class HTMLFileWizard extends Wizard implements INewWizard {
+
+ private HTMLFileWizardPage page;
+
+ private ISelection selection;
+
+ public HTMLFileWizard() {
+ super();
+ setNeedsProgressMonitor(true);
+ setWindowTitle(PHPWizardMessages
+ .getString("WizardNewProjectCreationPage.html.windowTitle"));
+ }
+
+ /**
+ * Adding the page to the wizard.
+ */
+ public void addPages() {
+ page = new HTMLFileWizardPage(selection);
+ addPage(page);
+ }
+
+ /**
+ * This method is called when 'Finish' button is pressed in the wizard. We
+ * will create an operation and run it using wizard as execution context.
+ */
+ public boolean performFinish() {
+ final String containerName = page.getContainerName();
+ final String fileName = page.getFileName();
+ IRunnableWithProgress op = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException {
+ try {
+ doFinish(containerName, fileName, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ try {
+ getContainer().run(true, false, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ Throwable realException = e.getTargetException();
+ MessageDialog.openError(getShell(), PHPWizardMessages
+ .getString("Wizard.error"), realException.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The worker method. It will find the container, create the file if missing
+ * or just replace its contents, and open the editor on the newly created
+ * file.
+ */
+ private void doFinish(String containerName, String fileName,
+ IProgressMonitor monitor) throws CoreException {
+ // create a sample file
+ monitor.beginTask(PHPWizardMessages
+ .getString("Wizard.Monitor.creating")
+ + " " + fileName, 2);
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IResource resource = root.findMember(new Path(containerName));
+ if (!resource.exists() || !(resource instanceof IContainer)) {
+ throwCoreException(PHPWizardMessages
+ .getString("Wizard.Monitor.containerDoesNotExistException"));
+ }
+ IContainer container = (IContainer) resource;
+ final IFile file = container.getFile(new Path(fileName));
+ IProject project = file.getProject();
+ String projectName = project.getName();
+ try {
+ InputStream stream;
+ stream = openContentStream(fileName, projectName);
+ if (file.exists()) {
+ file.setContents(stream, true, true, monitor);
+ } else {
+ file.create(stream, true, monitor);
+ }
+ stream.close();
+ } catch (IOException e) {
+ }
+ monitor.worked(1);
+ monitor.setTaskName(PHPWizardMessages
+ .getString("Wizard.Monitor.openingFile"));
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ try {
+ IDE.openEditor(page, file, true);
+ } catch (PartInitException e) {
+ }
+ }
+ });
+ monitor.worked(1);
+ }
+
+ /**
+ * We will initialize file contents with a sample text.
+ */
+ private InputStream openContentStream(String fileName, String projectname) {
+ try {
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(
+ CodeTemplateContextType.NEWHTML);
+ if (template == null) {
+ return null;
+ }
+ String lineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), null, lineDelimiter);
+ context.setFileNameVariable(fileName, projectname);
+ return new ByteArrayInputStream(StubUtility.evaluateTemplate(
+ context, template).getBytes());
+ } catch (CoreException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private void throwCoreException(String message) throws CoreException {
+ IStatus status = new Status(IStatus.ERROR,
+ "net.sourceforge.phpeclipse.wizards", IStatus.OK, message, null);
+ throw new CoreException(status);
+ }
+
+ /**
+ * We will accept the selection in the workbench to see if we can initialize
+ * from it.
+ *
+ * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+ */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.selection = selection;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/HTMLFileWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/HTMLFileWizardPage.java
new file mode 100644
index 0000000..40f8127
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/HTMLFileWizardPage.java
@@ -0,0 +1,244 @@
+package net.sourceforge.phpeclipse.wizards;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.IDialogPage;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+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.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+/**
+ * The "New" wizard page allows setting the container for the new file as well
+ * as the file name. The page will only accept file name without the extension
+ * OR with the extension that matches the expected one (cs).
+ */
+
+public class HTMLFileWizardPage extends WizardPage {
+ private static final String INITIAL_FILENAME = "file.html";
+
+ private Text containerText;
+
+ private Text fileText;
+
+ private ISelection selection;
+
+ /**
+ * Constructor for SampleNewWizardPage.
+ *
+ * @param pageName
+ */
+ public HTMLFileWizardPage(ISelection selection) {
+ super("wizardPage");
+ setTitle(PHPWizardMessages.getString("WizardPage.html.title"));
+ setDescription(PHPWizardMessages
+ .getString("WizardPage.html.description"));
+ this.selection = selection;
+ }
+
+ /**
+ * @see IDialogPage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ container.setLayout(layout);
+ layout.numColumns = 3;
+ layout.verticalSpacing = 9;
+ Label label = new Label(container, SWT.NULL);
+ label.setText(PHPWizardMessages.getString("WizardPage.containerLabel"));
+
+ containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ containerText.setLayoutData(gd);
+ containerText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+
+ Button button = new Button(container, SWT.PUSH);
+ button.setText(PHPWizardMessages
+ .getString("WizardPage.browseButtonText"));
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+ label = new Label(container, SWT.NULL);
+ label.setText(PHPWizardMessages.getString("WizardPage.fileLabel"));
+
+ fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ fileText.setLayoutData(gd);
+ fileText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+ initialize();
+ dialogChanged();
+ setControl(container);
+ }
+
+ /**
+ * Tests if the current workbench selection is a suitable container to use.
+ */
+
+ private void initialize() {
+ if (selection != null && selection.isEmpty() == false
+ && selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ if (ssel.size() > 1)
+ return;
+ Object obj = ssel.getFirstElement();
+ if (obj instanceof IResource) {
+ IContainer container;
+ if (obj instanceof IContainer)
+ container = (IContainer) obj;
+ else
+ container = ((IResource) obj).getParent();
+ containerText.setText(container.getFullPath().toString());
+ fileText.setFocus();
+ }
+ }
+ fileText.setText(INITIAL_FILENAME);
+ }
+
+ /**
+ * Uses the standard container selection dialog to choose the new value for
+ * the container field.
+ */
+
+ private void handleBrowse() {
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(
+ getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
+ PHPWizardMessages
+ .getString("WizardPage.selectNewFileContainer"));
+ if (dialog.open() == ContainerSelectionDialog.OK) {
+ Object[] result = dialog.getResult();
+ if (result.length == 1) {
+ IContainer container = (IContainer) result[0];
+ containerText.setText(container.getFullPath().toString());
+ }
+ }
+ }
+
+ /**
+ * Ensures that both text fields are set.
+ */
+ private void dialogChanged() {
+ String container = getContainerName();
+ String fileName = getFileName();
+
+ if (container.length() == 0) {
+ updateStatus(PHPWizardMessages
+ .getString("WizardPage.containerMustBeSpecified"));
+ return;
+ }
+ if (fileName.length() == 0) {
+ updateStatus("WizardPage.nameMustBeSpecified");
+ return;
+ }
+
+ updateStatus(null);
+ }
+
+ private void updateStatus(String message) {
+ setErrorMessage(message);
+ setPageComplete(message == null);
+ }
+
+ public String getContainerName() {
+ return containerText.getText();
+ }
+
+ public String getFileName() {
+ return fileText.getText();
+ }
+
+ /**
+ * @see WizardPage#isPageComplete()
+ */
+ public boolean isPageComplete() {
+ return !checkFolderForExistingFile() && super.isPageComplete();
+ }
+
+ /**
+ * Finds the current directory where the file should be created
+ */
+ protected boolean checkFolderForExistingFile() {
+ IContainer container = getFileContainer();
+ if (container != null) {
+ IResource file = container.getFile(new Path(fileText.getText()
+ .trim()));
+ if (file != null && file.exists()) {
+ this.setErrorMessage(PHPWizardMessages
+ .getString("WizardPage.fileAlreadyExists"));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private IContainer getFileContainer() {
+ if (containerText.getText() != null) {
+ IPath containerPath = new Path(containerText.getText().trim());
+ IContainer container;
+ if (containerPath.segmentCount() > 1) {
+ container = ResourcesPlugin.getWorkspace().getRoot().getFolder(
+ containerPath);
+ } else {
+ // this is a project
+ container = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(containerText.getText().trim());
+ }
+ if (container != null && container.exists()) {
+ return container;
+ }
+ }
+ return null;
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ String fileName = fileText.getText().trim();
+ if (getFileContainer() != null
+ && fileName.equalsIgnoreCase(INITIAL_FILENAME)) {
+ fileText.setFocus();
+ fileText.setText(fileName);
+ fileText.setSelection(0, fileName.length()
+ - (new Path(INITIAL_FILENAME)).getFileExtension()
+ .length() - 1);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/NewProjectCreationWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/NewProjectCreationWizard.java
new file mode 100644
index 0000000..28ce603
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/NewProjectCreationWizard.java
@@ -0,0 +1,122 @@
+package net.sourceforge.phpeclipse.wizards;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.ui.actions.OpenPHPPerspectiveAction;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+
+public class NewProjectCreationWizard extends BasicNewResourceWizard implements
+ INewWizard, IExecutableExtension {
+ protected WizardNewProjectCreationPage projectPage;
+
+ protected IConfigurationElement configurationElement;
+
+ protected IProject newProject;
+
+ public NewProjectCreationWizard() {
+ setWindowTitle(PHPWizardMessages
+ .getString("NewProjectCreationWizard.windowTitle"));
+ }
+
+ public boolean performFinish() {
+ IRunnableWithProgress projectCreationOperation = new WorkspaceModifyDelegatingOperation(
+ getProjectCreationRunnable());
+
+ try {
+ getContainer().run(false, true, projectCreationOperation);
+ } catch (Exception e) {
+ PHPeclipsePlugin.log(e);
+ return false;
+ }
+
+ BasicNewProjectResourceWizard.updatePerspective(configurationElement);
+ selectAndReveal(newProject);
+ // open the PHP perspective
+ new OpenPHPPerspectiveAction().run();
+ return true;
+ }
+
+ protected IRunnableWithProgress getProjectCreationRunnable() {
+ return new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ int remainingWorkUnits = 10;
+ monitor
+ .beginTask(
+ PHPWizardMessages
+ .getString("NewProjectCreationWizard.projectCreationMessage"),
+ remainingWorkUnits);
+
+ IWorkspace workspace = PHPeclipsePlugin.getWorkspace();
+ String projectName = projectPage.getProjectHandle().getName();
+ newProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ IProjectDescription description = workspace
+ .newProjectDescription(projectName);
+
+ URI uriPath = (!projectPage.useDefaults()) ? projectPage
+ .getLocationURI() : null;
+ if (uriPath != null) {
+ description.setLocationURI(uriPath);
+ }
+
+ try {
+ if (!newProject.exists()) {
+ newProject.create(description, new SubProgressMonitor(
+ monitor, 1));
+ remainingWorkUnits--;
+ }
+ if (!newProject.isOpen()) {
+ newProject.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1));
+ remainingWorkUnits--;
+ }
+ JavaCore.addPHPNature(newProject, new SubProgressMonitor(
+ monitor, remainingWorkUnits));
+
+ } catch (CoreException e) {
+ System.out.println(e);
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ }
+
+ public void addPages() {
+ super.addPages();
+
+ projectPage = new WizardNewProjectCreationPage(PHPWizardMessages
+ .getString("WizardNewProjectCreationPage.pageName"));
+ projectPage.setTitle(PHPWizardMessages
+ .getString("WizardNewProjectCreationPage.pageTitle"));
+ projectPage.setDescription(PHPWizardMessages
+ .getString("WizardNewProjectCreationPage.pageDescription"));
+
+ addPage(projectPage);
+ }
+
+ public void setInitializationData(IConfigurationElement config,
+ String propertyName, Object data) throws CoreException {
+ configurationElement = config;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPFileWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPFileWizard.java
new file mode 100644
index 0000000..f0306af
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPFileWizard.java
@@ -0,0 +1,242 @@
+package net.sourceforge.phpeclipse.wizards;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContext;
+import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContextType;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+/**
+ * This wizard creates one file with the extension "php".
+ */
+public class PHPFileWizard extends Wizard implements INewWizard {
+
+ private PHPFileWizardPage page;
+
+ private ISelection selection;
+
+ public PHPFileWizard() {
+ super();
+ setNeedsProgressMonitor(true);
+ setWindowTitle(PHPWizardMessages
+ .getString("WizardNewProjectCreationPage.windowTitle"));
+ }
+
+ /**
+ * Adding the page to the wizard.
+ */
+ public void addPages() {
+ page = new PHPFileWizardPage(selection);
+ addPage(page);
+ }
+
+ /**
+ * This method is called when 'Finish' button is pressed in the wizard. We
+ * will create an operation and run it using wizard as execution context.
+ */
+ public boolean performFinish() {
+ final String containerName = page.getContainerName();
+ final String fileName = page.getFileName();
+ IRunnableWithProgress op = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException {
+ try {
+ doFinish(containerName, fileName, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ try {
+ getContainer().run(true, false, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ Throwable realException = e.getTargetException();
+ MessageDialog.openError(getShell(), PHPWizardMessages
+ .getString("Wizard.error"), realException.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The worker method. It will find the container, create the file if missing
+ * or just replace its contents, and open the editor on the newly created
+ * file.
+ */
+ private void doFinish(String containerName, String fileName,
+ IProgressMonitor monitor) throws CoreException {
+ // create a sample file
+ monitor.beginTask(PHPWizardMessages
+ .getString("Wizard.Monitor.creating")
+ + " " + fileName, 2);
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IResource resource = root.findMember(new Path(containerName));
+ if (!resource.exists() || !(resource instanceof IContainer)) {
+ throwCoreException(PHPWizardMessages
+ .getString("Wizard.Monitor.containerDoesNotExistException"));
+ }
+ IContainer container = (IContainer) resource;
+ final IFile file = container.getFile(new Path(fileName));
+ IProject project = file.getProject();
+ String projectName = project.getName();
+ String className = getClassName(fileName);
+
+ try {
+ InputStream stream;
+ if (className == null) {
+ stream = openContentStream(fileName, projectName);
+ } else {
+ stream = openContentStreamClass(className);
+ }
+ if (file.exists()) {
+ file.setContents(stream, true, true, monitor);
+ } else {
+ file.create(stream, true, monitor);
+ }
+ stream.close();
+ } catch (IOException e) {
+ }
+ monitor.worked(1);
+ monitor.setTaskName(PHPWizardMessages
+ .getString("Wizard.Monitor.openingFile"));
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ try {
+ IDE.openEditor(page, file, true);
+ } catch (PartInitException e) {
+ }
+ }
+ });
+ monitor.worked(1);
+ }
+
+ /**
+ * Check if the filename is like this anyname.class.php
+ *
+ * @param fFileName
+ * the filename
+ * @return the anyname or null
+ */
+ private static final String getClassName(final String fileName) {
+ final int lastDot = fileName.lastIndexOf('.');
+ if (lastDot == -1)
+ return null;
+ final int precLastDot = fileName.lastIndexOf('.', lastDot - 1);
+ if (precLastDot == -1)
+ return null;
+ if (!fileName.substring(precLastDot + 1, lastDot).toUpperCase().equals(
+ "CLASS"))
+ return null;
+ return fileName.substring(0, precLastDot);
+ }
+
+ /**
+ * We will initialize file contents for a class
+ *
+ * @param className
+ * the classname
+ */
+ private InputStream openContentStreamClass(final String className) {
+ StringBuffer contents = new StringBuffer("");
+ return new ByteArrayInputStream(contents.toString().getBytes());
+ }
+
+ /**
+ * We will initialize file contents with a sample text.
+ */
+ private InputStream openContentStream(String fileName, String projectname) {
+ try {
+ Template template = WebUI.getDefault()
+ .getCodeTemplateStore().findTemplate(
+ CodeTemplateContextType.NEWTYPE);
+ if (template == null) {
+ return null;
+ }
+ String lineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ CodeTemplateContext context = new CodeTemplateContext(template
+ .getContextTypeId(), null, lineDelimiter);
+ context.setFileNameVariable(fileName, projectname);
+ String content = StubUtility.evaluateTemplate(context, template);
+ if (content == null) {
+ content = "";
+ }
+ return new ByteArrayInputStream(content.getBytes());
+ } catch (CoreException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ }
+
+ private void throwCoreException(String message) throws CoreException {
+ IStatus status = new Status(IStatus.ERROR,
+ "net.sourceforge.phpeclipse.wizards", IStatus.OK, message, null);
+ throw new CoreException(status);
+ }
+
+ /**
+ * We will accept the selection in the workbench to see if we can initialize
+ * from it.
+ *
+ * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+ */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.selection = selection;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPFileWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPFileWizardPage.java
new file mode 100644
index 0000000..f4ac33a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPFileWizardPage.java
@@ -0,0 +1,248 @@
+package net.sourceforge.phpeclipse.wizards;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.IDialogPage;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+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.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+/**
+ * The "New" wizard page allows setting the container for the new file as well
+ * as the file name. The page will only accept file name without the extension
+ * OR with the extension that matches the expected one (cs).
+ */
+
+public class PHPFileWizardPage extends WizardPage {
+ private static final String INITIAL_FILENAME = "file.php";
+
+ private Text containerText;
+
+ private Text fileText;
+
+ private ISelection selection;
+
+ /**
+ * Constructor for SampleNewWizardPage.
+ *
+ * @param pageName
+ */
+ public PHPFileWizardPage(ISelection selection) {
+ super("wizardPage");
+ setTitle(PHPWizardMessages.getString("WizardPage.title"));
+ setDescription(PHPWizardMessages.getString("WizardPage.description"));
+ this.selection = selection;
+ }
+
+ /**
+ * @see IDialogPage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ container.setLayout(layout);
+ layout.numColumns = 3;
+ layout.verticalSpacing = 9;
+ Label label = new Label(container, SWT.NULL);
+ label.setText(PHPWizardMessages.getString("WizardPage.containerLabel"));
+
+ containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ containerText.setLayoutData(gd);
+ containerText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+
+ Button button = new Button(container, SWT.PUSH);
+ button.setText(PHPWizardMessages
+ .getString("WizardPage.browseButtonText"));
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+ label = new Label(container, SWT.NULL);
+ label.setText(PHPWizardMessages.getString("WizardPage.fileLabel"));
+
+ fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ fileText.setLayoutData(gd);
+ fileText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+ initialize();
+ dialogChanged();
+ setControl(container);
+ }
+
+ /**
+ * Tests if the current workbench selection is a suitable container to use.
+ */
+
+ private void initialize() {
+ if (selection != null && selection.isEmpty() == false
+ && selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ if (ssel.size() > 1)
+ return;
+ Object obj = ssel.getFirstElement();
+ if (obj instanceof IResource) {
+ IContainer container;
+ if (obj instanceof IContainer)
+ container = (IContainer) obj;
+ else
+ container = ((IResource) obj).getParent();
+ containerText.setText(container.getFullPath().toString());
+ fileText.setFocus();
+ }
+ }
+ fileText.setText(INITIAL_FILENAME);
+ }
+
+ /**
+ * Uses the standard container selection dialog to choose the new value for
+ * the container field.
+ */
+
+ private void handleBrowse() {
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(
+ getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
+ PHPWizardMessages
+ .getString("WizardPage.selectNewFileContainer"));
+ if (dialog.open() == ContainerSelectionDialog.OK) {
+ Object[] results = dialog.getResult();
+ if (results.length == 1) {
+ Object result = results[0];
+ if (result instanceof IPath) {
+ IPath ipath = (IPath) result;
+ containerText.setText(ipath.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * Ensures that both text fields are set.
+ */
+ private void dialogChanged() {
+ String container = getContainerName();
+ String fileName = getFileName();
+
+ if (container.length() == 0) {
+ updateStatus(PHPWizardMessages
+ .getString("WizardPage.containerMustBeSpecified"));
+ return;
+ }
+ if (fileName.length() == 0) {
+ updateStatus("WizardPage.nameMustBeSpecified");
+ return;
+ }
+
+ updateStatus(null);
+ }
+
+ private void updateStatus(String message) {
+ setErrorMessage(message);
+ setPageComplete(message == null);
+ }
+
+ public String getContainerName() {
+ return containerText.getText();
+ }
+
+ public String getFileName() {
+ return fileText.getText();
+ }
+
+ /**
+ * @see WizardPage#isPageComplete()
+ */
+ public boolean isPageComplete() {
+ return !checkFolderForExistingFile() && super.isPageComplete();
+ }
+
+ /**
+ * Finds the current directory where the file should be created
+ */
+ protected boolean checkFolderForExistingFile() {
+ IContainer container = getFileContainer();
+ if (container != null) {
+ IResource file = container.getFile(new Path(fileText.getText()
+ .trim()));
+ if (file != null && file.exists()) {
+ this.setErrorMessage(PHPWizardMessages
+ .getString("WizardPage.fileAlreadyExists"));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private IContainer getFileContainer() {
+ if (containerText.getText() != null) {
+ IPath containerPath = new Path(containerText.getText().trim());
+ IContainer container = null;
+ if (containerPath.segmentCount() > 1) {
+ container = ResourcesPlugin.getWorkspace().getRoot().getFolder(
+ containerPath);
+ } else {
+ if (containerPath.segmentCount() == 1) {
+ // this is a project
+ container = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(containerText.getText().trim());
+ }
+ }
+ if (container != null && container.exists()) {
+ return container;
+ }
+ }
+ return null;
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ String fileName = fileText.getText().trim();
+ if (getFileContainer() != null
+ && fileName.equalsIgnoreCase(INITIAL_FILENAME)) {
+ fileText.setFocus();
+ fileText.setText(fileName);
+ fileText.setSelection(0, fileName.length()
+ - (new Path(INITIAL_FILENAME)).getFileExtension()
+ .length() - 1);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPWizardMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPWizardMessages.java
new file mode 100644
index 0000000..a95f119
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPWizardMessages.java
@@ -0,0 +1,36 @@
+package net.sourceforge.phpeclipse.wizards;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class PHPWizardMessages {
+
+ private static final String RESOURCE_BUNDLE = PHPWizardMessages.class
+ .getName();//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private PHPWizardMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPWizardMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPWizardMessages.properties
new file mode 100644
index 0000000..355c144
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/PHPWizardMessages.properties
@@ -0,0 +1,34 @@
+###################################
+##
+## PHP wizard strings
+##
+###################################
+
+WizardPage.title=PHP file
+WizardPage.description=This wizard creates a new PHP file.
+WizardPage.html.title=HTML file
+WizardPage.html.description=This wizard creates a new HTML file.
+WizardPage.containerLabel=&Container:
+WizardPage.fileLabel=&File name:
+WizardPage.browseButtonText=Browse...
+WizardPage.fileAlreadyExists=This name is already used by an existing file. Please choose another one.
+WizardPage.mustBePHP=File extension must be "php".
+WizardPage.nameMustBeSpecified=File name must be specified.
+WizardPage.containerMustBeSpecified=File container must be specified.
+WizardPage.selectNewFileContainer=Select new file container.
+
+
+
+Wizard.error=An error occured
+Wizard.Monitor.creating=Creating
+Wizard.Monitor.openingFile=Opening file for editing...
+Wizard.Monitor.containerDoesNotExistException=The given container does not exist.
+
+NewProjectCreationWizard.windowTitle=New PHP project
+NewProjectCreationWizard.projectCreationMessage=Creating new PHP Project
+
+WizardNewProjectCreationPage.windowTitle=New PHP file
+WizardNewProjectCreationPage.html.windowTitle=New HTML file
+WizardNewProjectCreationPage.pageName=Create PHP Project
+WizardNewProjectCreationPage.pageTitle=PHP Project
+WizardNewProjectCreationPage.pageDescription=Create a new PHP Project
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/TempnewPHPProject.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/TempnewPHPProject.java
new file mode 100644
index 0000000..05cace3
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/TempnewPHPProject.java
@@ -0,0 +1,103 @@
+package net.sourceforge.phpeclipse.wizards;
+
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+
+public class TempnewPHPProject extends BasicNewResourceWizard implements
+ INewWizard {
+ /*
+ * This class has been added to cvs to provide a project page that works
+ * correctly and doesn't freezde while i investigate the errors completely
+ */
+ private WizardNewProjectCreationPage phpProjPage;
+
+ private IConfigurationElement fConfigElement;
+
+ public TempnewPHPProject() {
+ setNeedsProgressMonitor(true);
+ setWindowTitle("New Project creation"); //$NON-NLS-1$
+
+ }
+
+ public void addPages() {
+ super.addPages();
+ phpProjPage = new WizardNewProjectCreationPage(
+ "NewProjectCreationWizard"); //$NON-NLS-1$
+ phpProjPage.setTitle(PHPWizardMessages
+ .getString("WizardNewProjectCreationPage.pageTitle")); //$NON-NLS-1$
+ phpProjPage.setDescription(PHPWizardMessages
+ .getString("WizardNewProjectCreationPage.pageDescription")); //$NON-NLS-1$
+ addPage(phpProjPage);
+ }
+
+ public void setInitializationData(IConfigurationElement cfig,
+ String propertyName, Object data) {
+ fConfigElement = cfig;
+ }
+
+ protected void initializeDefaultPageImageDescriptor() {
+ // not used yet
+ }
+
+ protected void finishPage() throws InterruptedException, CoreException {
+ createProject(phpProjPage.getProjectHandle(), phpProjPage
+ .getLocationPath(), new NullProgressMonitor());
+ BasicNewProjectResourceWizard.updatePerspective(fConfigElement);
+ selectAndReveal(phpProjPage.getProjectHandle());
+ }
+
+ protected void handleFinishException(Shell shell,
+ InvocationTargetException e) {
+ ExceptionHandler.handle(e, getShell(), "Error title", "Error message");
+ }
+
+ public boolean performFinish() {
+ try {
+ finishPage();
+ } catch (InterruptedException e) {
+ } catch (CoreException e) {
+ }
+ return true;
+ }
+
+ public void createProject(IProject project, IPath locationPath,
+ IProgressMonitor monitor) throws CoreException {
+ try {
+ if (!project.exists()) {
+ IProjectDescription desc = project.getWorkspace()
+ .newProjectDescription(project.getName());
+ if (Platform.getLocation().equals(locationPath)) {
+ locationPath = null;
+ }
+ desc.setLocation(locationPath);
+ project.create(desc, monitor);
+ monitor = null;
+ }
+ if (!project.isOpen()) {
+ project.open(monitor);
+ monitor = null;
+ }
+ JavaCore.addPHPNature(project, new NullProgressMonitor());
+ } finally {
+ if (monitor != null) {
+ monitor.done();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/EditElementWizard.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/EditElementWizard.java
new file mode 100644
index 0000000..c2be185
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/EditElementWizard.java
@@ -0,0 +1,121 @@
+/*
+ * $Id: EditElementWizard.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * EditElementWizard. TODO: privides extension point element editor. pluggable
+ * element edit page.
+ */
+public class EditElementWizard extends Wizard {
+
+ static Object[] elementEditPages = new Object[] {
+ // "a", AElementWizardPage.class,
+ // "img", ImgElementWizardPage.class,
+ "dl", ListElementWizardPage.class, "ul",
+ ListElementWizardPage.class, "ol", ListElementWizardPage.class,
+ "table", TableElementWizardPage.class };
+
+ String targetElemName;
+
+ ITextEditor htEditor;
+
+ EditElementWizardPage rootPage;
+
+ /**
+ * Second argument specify element name, If specify null, call new element
+ * edit wizard page.
+ */
+ public EditElementWizard(ITextEditor editor, String targetElemName) {
+ htEditor = editor;
+ this.targetElemName = targetElemName;
+
+ setWindowTitle("Edit HTML Element");
+ setDefaultPageImageDescriptor(PHPUiImages
+ .getDescriptor("wizban/editelem_wiz.gif"));
+
+ setForcePreviousAndNextButtons(true);
+ }
+
+ public void addPages() {
+ if (targetElemName == null) {
+ rootPage = new NewElementWizardPage();
+ } else {
+ IDocument doc = getDocument();
+ rootPage = createElementEditPage(targetElemName);
+ rootPage.setEditType(EditElementWizardPage.MODIFY);
+ }
+ addPage(rootPage);
+ }
+
+ public boolean performFinish() {
+ IWizardPage page = rootPage;
+ for (IWizardPage p; (p = page.getNextPage()) != null;) {
+ page = p;
+ }
+ if (page instanceof EditElementWizardPage) {
+ ((EditElementWizardPage) page).performFinish();
+ }
+ return true;
+ }
+
+ public IDocument getDocument() {
+ return htEditor.getDocumentProvider().getDocument(
+ htEditor.getEditorInput());
+ }
+
+ public ITextSelection getSelection() {
+ return (ITextSelection) htEditor.getSelectionProvider().getSelection();
+ }
+
+ public void setSelection(ITextSelection sel) {
+ htEditor.getSelectionProvider().setSelection(sel);
+ }
+
+ public IFile getCurrentEditFile() {
+ IEditorInput input = htEditor.getEditorInput();
+ return (input instanceof IFileEditorInput) ? ((IFileEditorInput) input)
+ .getFile() : null;
+ }
+
+ /**
+ * If not edit target returns UnknownElementWizardPage.
+ */
+ public EditElementWizardPage createElementEditPage(String elementName) {
+ EditElementWizardPage page = null;
+ try {
+ for (int i = 0; i < elementEditPages.length; i += 2) {
+ if (((String) elementEditPages[i])
+ .equalsIgnoreCase(elementName)) {
+ Class klass = (Class) elementEditPages[i + 1];
+ page = (EditElementWizardPage) klass.newInstance();
+ }
+ }
+ } catch (InstantiationException e) {
+ PHPeclipsePlugin.log(e);
+ } catch (IllegalAccessException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ if (page == null) {
+ page = new UnknownElementWizardPage();
+ }
+ page.setElementName(elementName);
+ page.setWizard(this);
+
+ return page;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/EditElementWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/EditElementWizardPage.java
new file mode 100644
index 0000000..44d1a27
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/EditElementWizardPage.java
@@ -0,0 +1,192 @@
+/*
+ * $Id: EditElementWizardPage.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ *
+ */
+public abstract class EditElementWizardPage extends WizardPage implements
+ IPreviewer {
+
+ final public static int NEW = 0, MODIFY = 1;
+
+ private static DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
+ .newInstance();
+
+ Composite extendComp;
+
+ Text preview;
+
+ private String elementName = null;
+
+ int editType = NEW;
+
+ protected EditElementWizardPage(String pageName) {
+ super(pageName);
+ }
+
+ public void createControl(Composite parent) {
+ Composite base = new Composite(parent, SWT.NONE);
+ setControl(base);
+ base.setLayout(new GridLayout(1, false));
+
+ // create child control.
+ Composite childControlBase = new Composite(base, SWT.NONE);
+ childControlBase.setLayoutData(new GridData(GridData.FILL_BOTH));
+ try {
+ createChildControl(childControlBase);
+ } catch (CoreException e) {
+ PHPeclipsePlugin.log(e);
+ return;
+ }
+
+ // preview components.
+ Composite previewBase = new Composite(base, SWT.NONE);
+
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ previewBase.setLayoutData(gd);
+ previewBase.setLayout(new GridLayout(1, false));
+
+ Label labe = new Label(previewBase, SWT.NONE);
+ labe.setText("Preview:");
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ labe.setLayoutData(gd);
+
+ preview = new Text(previewBase, SWT.BORDER | SWT.MULTI | SWT.READ_ONLY
+ | SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 0;
+ gd.heightHint = preview.getLineHeight() * 4;
+ preview.setLayoutData(gd);
+
+ refreshPreview();
+ }
+
+ abstract protected void createChildControl(Composite parent)
+ throws CoreException;
+
+ public abstract String getPreviewText();
+
+ public void refreshPreview() {
+ if (preview != null) {
+ String text = getPreviewText();
+ preview.setText(text == null ? "" : text);
+ }
+ }
+
+ public String getElementName() {
+ return elementName;
+ }
+
+ public void setElementName(String string) {
+ elementName = string;
+ }
+
+ protected IFile getEditFile() {
+ IFile file = null;
+ IWizard wiz = getWizard();
+ if (wiz instanceof EditElementWizard) {
+ file = ((EditElementWizard) wiz).getCurrentEditFile();
+ }
+ return file;
+ }
+
+ protected void performFinish() {
+ EditElementWizard wiz = (EditElementWizard) getWizard();
+ ITextSelection sel = wiz.getSelection();
+ IDocument doc = wiz.getDocument();
+ int offset = sel.getOffset();
+ try {
+ doc.replace(offset, sel.getLength(), getPreviewText());
+ } catch (BadLocationException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ int index = doc.get().indexOf('>', offset);
+ if (index != -1) {
+ wiz.setSelection(new TextSelection(index + 1, 0));
+ }
+ }
+
+ /**
+ * Returns edit type.
+ */
+ public int getEditType() {
+ return editType;
+ }
+
+ /**
+ * Sets edit type that types are EditElementWizardPage.NEW,
+ * EditElementWizardPage.MODIFY. Default value is NEW.
+ */
+ public void setEditType(int i) {
+ editType = i;
+ }
+
+ protected String getSelectionText() {
+ return ((EditElementWizard) getWizard()).getSelection().getText();
+ }
+
+ protected Element getParsedSelectionText() {
+ String selText = getSelectionText();
+ try {
+ InputSource source = new InputSource(new StringReader(selText));
+ Document doc = docBuilderFactory.newDocumentBuilder().parse(source);
+ return doc.getDocumentElement();
+ } catch (SAXException e) {
+ } catch (IOException e) {
+ } catch (ParserConfigurationException e) {
+ }
+ return null;
+
+ }
+
+ protected static String chooseContent(String text) {
+ int b = -1, e = -1, len = text.length();
+ for (int i = 0; i < len; i++) {
+ if (text.charAt(i) == '>') {
+ b = i + 1;
+ break;
+ }
+ }
+ for (int i = len - 1; i >= 0; i--) {
+ if (text.charAt(i) == '<') {
+ e = i;
+ break;
+ }
+ }
+ return (b != -1 && e != -1 && b < len && e < len) ? text
+ .substring(b, e) : "";
+
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/ElementWriter.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/ElementWriter.java
new file mode 100644
index 0000000..8bd46ee
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/ElementWriter.java
@@ -0,0 +1,141 @@
+/*
+ * $Id: ElementWriter.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.HashMap;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+/**
+ * ElementWriter provides destribute xml code.
+ */
+public class ElementWriter {
+
+ final public static int BEGIN_CHANGELINE = 1, END_CHANGELINE = 2;
+
+ boolean trim = true;
+
+ HashMap expandOptions = new HashMap();
+
+ int defaultExpandOption;
+
+ String indent;
+
+ public ElementWriter() {
+ this(0, " ");
+ }
+
+ public ElementWriter(int defaultExpandOption, String indent) {
+ this.defaultExpandOption = defaultExpandOption;
+ this.indent = indent;
+ }
+
+ public void setExpandOption(String elementName, int value) {
+ expandOptions.put(elementName, new Integer(value));
+ }
+
+ public int getExpandOption(String elementName) {
+ if (expandOptions.containsKey(elementName)) {
+ return ((Integer) expandOptions.get(elementName)).intValue();
+ }
+ return defaultExpandOption;
+ }
+
+ boolean isBeginChangeLine(String elementName) {
+ return (getExpandOption(elementName) & BEGIN_CHANGELINE) != 0;
+ }
+
+ boolean isEndChangeLine(String elementName) {
+ return (getExpandOption(elementName) & END_CHANGELINE) != 0;
+ }
+
+ public String expandTag(Element element) {
+ StringBuffer buff = new StringBuffer();
+ expandTag(element, 0, buff);
+ return buff.toString();
+ }
+
+ public void writeTag(Element element, OutputStream out) throws IOException {
+ OutputStreamWriter writer = new OutputStreamWriter(out);
+ try {
+ writer.write("\n\n");
+ writer.write(new ElementWriter().expandTag(element));
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
+ void expandTag(Element element, int level, StringBuffer buff) {
+ expandIndent(level, buff);
+
+ String elementName = element.getNodeName();
+ buff.append('<' + elementName);
+ NamedNodeMap attrs = element.getAttributes();
+ for (int i = 0; i < attrs.getLength(); i++) {
+ Node n = attrs.item(i);
+ String v = n.getNodeValue();
+ if (v != null) {
+ buff.append(' ' + n.getNodeName() + "=\""
+ + HTMLUtilities.escape(v) + "\"");
+ }
+ }
+
+ boolean emptyElem = element.getChildNodes().getLength() == 0;
+ if (emptyElem) {
+ buff.append(" /");
+ }
+ buff.append('>');
+ if (!emptyElem) {
+ NodeList childElements = element.getChildNodes();
+ if (isBeginChangeLine(elementName)) {
+ buff.append('\n');
+ }
+ for (int i = 0; i < childElements.getLength(); i++) {
+ Node node = childElements.item(i);
+ if (node instanceof Element) {
+ expandTag((Element) node, level + 1, buff);
+ } else if (node instanceof Text) {
+ String text = ((Text) node).getNodeValue();
+ if (trim && (text = text.trim()).length() == 0) {
+ continue;
+ }
+ buff.append(text);
+ }
+ }
+ expandIndent(level, buff);
+ buff.append("" + elementName + '>');
+ }
+ // already inserted change line.
+ if (isEndChangeLine(elementName)) {
+ buff.append('\n');
+ }
+ }
+
+ void expandIndent(int level, StringBuffer buff) {
+ if (indent != null) {
+ for (int i = 0; i < level; i++) {
+ buff.append(indent);
+ }
+ }
+ }
+
+ public int getDefaultExpandOption() {
+ return defaultExpandOption;
+ }
+
+ public void setDefaultExpandOption(int i) {
+ defaultExpandOption = i;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/FormElementWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/FormElementWizardPage.java
new file mode 100644
index 0000000..d9ab7e7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/FormElementWizardPage.java
@@ -0,0 +1,66 @@
+/*
+ * $Id: FormElementWizardPage.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ *
+ */
+public class FormElementWizardPage extends EditElementWizardPage {
+
+ Text actionText;
+
+ Button postRadio, getRadio, multipartCheck;
+
+ Combo charsetCombo;
+
+ public FormElementWizardPage() {
+ super("FormElementWizardPage");
+ }
+
+ protected void createChildControl(Composite parent) throws CoreException {
+ postRadio = new Button(parent, SWT.RADIO);
+
+ }
+
+ public String getPreviewText() {
+ boolean controlCreated = actionText != null;
+
+ StringBuffer buff = new StringBuffer("\n");
+
+ return buff.toString();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/HTMLUtilities.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/HTMLUtilities.java
new file mode 100644
index 0000000..8f9db38
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/HTMLUtilities.java
@@ -0,0 +1,29 @@
+/*
+ * $Id: HTMLUtilities.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+/**
+ *
+ */
+public class HTMLUtilities {
+
+ final static String[] specialMarks = { "&", "&", "<", "<", ">",
+ ">", "\"", """, };
+
+ public static String escape(String text) {
+ for (int i = 0; i < specialMarks.length; i += 2) {
+ text = text.replaceAll(specialMarks[i], specialMarks[i + 1]);
+ }
+ return text;
+ }
+
+ public static String unescape(String text) {
+ for (int i = specialMarks.length - 1; i >= 0; i -= 2) {
+ text = text.replaceAll(specialMarks[i], specialMarks[i - 1]);
+ }
+ return text;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/IPreviewer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/IPreviewer.java
new file mode 100644
index 0000000..7f1fc83
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/IPreviewer.java
@@ -0,0 +1,14 @@
+/*
+ * $Id: IPreviewer.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+/**
+ *
+ */
+public interface IPreviewer {
+
+ String getPreviewText();
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/InsertHTMLElementAction.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/InsertHTMLElementAction.java
new file mode 100644
index 0000000..5ca0f4a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/InsertHTMLElementAction.java
@@ -0,0 +1,47 @@
+/*
+ * $Id: InsertHTMLElementAction.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * InsertTagAction
+ */
+public class InsertHTMLElementAction implements IEditorActionDelegate {
+
+ ITextEditor targetEditor = null;
+
+ public InsertHTMLElementAction() {
+ }
+
+ public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+ if (targetEditor instanceof ITextEditor) {
+ this.targetEditor = (ITextEditor) targetEditor;
+ }
+ }
+
+ public void run(IAction action) {
+
+ WizardDialog wizDialog = new WizardDialog(targetEditor.getSite()
+ .getShell(), new EditElementWizard(targetEditor, null)) {
+
+ protected int getShellStyle() {
+ return super.getShellStyle() | SWT.RESIZE;
+ }
+ };
+
+ wizDialog.open();
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/ListElementWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/ListElementWizardPage.java
new file mode 100644
index 0000000..d49f96d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/ListElementWizardPage.java
@@ -0,0 +1,88 @@
+/*
+ * $Id: ListElementWizardPage.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+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.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ *
+ */
+public class ListElementWizardPage extends EditElementWizardPage {
+
+ final static String[] LIST_TYPES = { "ul", "ol", "dl" };
+
+ Combo types;
+
+ public ListElementWizardPage() {
+ super("ListElementWizardPage");
+ setTitle("List");
+ setDescription("Editing list element.");
+ }
+
+ protected void createChildControl(Composite parent) {
+ parent.setLayout(new GridLayout(2, false));
+ Label labe = new Label(parent, SWT.NONE);
+ labe.setText("List &Type:");
+
+ types = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
+
+ for (int i = 0; i < LIST_TYPES.length; i++) {
+ String type = LIST_TYPES[i];
+ types.add(type);
+ if (getElementName().equals(type)) {
+ types.select(i);
+ }
+ }
+
+ types.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ types.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ setElementName(types.getText());
+ refreshPreview();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ public String getPreviewText() {
+ String content = ((EditElementWizard) getWizard()).getSelection()
+ .getText().trim();
+
+ String elemName = getElementName();
+ switch (getEditType()) {
+ case MODIFY:
+ content = chooseContent(content).trim();
+ break;
+
+ case NEW:
+ String[] lines = content.split("\n+");
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < lines.length; i++) {
+ String itemElemName;
+ if (elemName.equals("dl")) {
+ itemElemName = (i % 2 == 0) ? "dt" : "dd";
+ } else {
+ itemElemName = "li";
+ }
+ result.append("<" + itemElemName + ">" + lines[i].trim() + ""
+ + itemElemName + ">\n");
+ }
+ content = result.toString();
+ break;
+ }
+
+ return "<" + elemName + ">\n" + content + "" + elemName + ">\n";
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/NewElementWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/NewElementWizardPage.java
new file mode 100644
index 0000000..933317a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/NewElementWizardPage.java
@@ -0,0 +1,84 @@
+/*
+ * $Id: NewElementWizardPage.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ *
+ */
+public class NewElementWizardPage extends EditElementWizardPage {
+
+ Text elementName;
+
+ EditElementWizardPage nextPage = null;
+
+ public NewElementWizardPage() {
+ super("NewElementPage");
+ setTitle("Create HTML Element");
+ setDescription("Specify new HTML tag (dl,ul,ol or table) and configure that tag.");
+ }
+
+ protected void createChildControl(Composite base) {
+ // create foundation component
+ base.setLayout(new GridLayout(1, false));
+
+ // element input components
+ new Label(base, SWT.NONE).setText("&Element Name:");
+
+ elementName = new Text(base, SWT.BORDER | SWT.SINGLE);
+ elementName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ elementName.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ String eName = elementName.getText();
+ if (eName.indexOf(' ') != -1) {
+ setErrorMessage("Don't contain blink in speicfied element name.");
+ } else if (eName.length() == 0) {
+ setErrorMessage("Need to specify element name.");
+ } else {
+ setErrorMessage(null);
+ nextPage = ((EditElementWizard) getWizard())
+ .createElementEditPage(eName);
+ nextPage.setElementName(eName);
+ if (nextPage instanceof UnknownElementWizardPage) {
+ setMessage("This editor does not known element name.",
+ WARNING);
+ } else {
+ setMessage(null, NONE);
+ }
+ }
+ refreshPreview();
+ getWizard().getContainer().updateButtons();
+ }
+ });
+ }
+
+ public String getPreviewText() {
+ if (nextPage instanceof EditElementWizardPage) {
+ return ((EditElementWizardPage) nextPage).getPreviewText();
+ }
+ return null;
+ }
+
+ public void setErrorMessage(String newMessage) {
+ super.setErrorMessage(newMessage);
+ if (newMessage != null) {
+ nextPage = null;
+ }
+ }
+
+ public IWizardPage getNextPage() {
+ return nextPage;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/NumVerifyListener.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/NumVerifyListener.java
new file mode 100644
index 0000000..6cdfee5
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/NumVerifyListener.java
@@ -0,0 +1,21 @@
+/*
+ * $Id: NumVerifyListener.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+
+public class NumVerifyListener implements VerifyListener {
+
+ Pattern numPattern = Pattern.compile("^\\d+$");
+
+ public void verifyText(VerifyEvent ev) {
+ ev.doit = numPattern.matcher(ev.text).matches()
+ || ev.keyCode == SWT.DEL || ev.character == SWT.BS;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/SomeItemInputDialog.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/SomeItemInputDialog.java
new file mode 100644
index 0000000..fdbfeb0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/SomeItemInputDialog.java
@@ -0,0 +1,130 @@
+/*
+ * $Id: SomeItemInputDialog.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ *
+ */
+public class SomeItemInputDialog extends Dialog {
+
+ String dialogTitle;
+
+ String[] inputMessages;
+
+ IInputValidator[] validators;
+
+ Text[] texts;
+
+ Text error;
+
+ String[] errorMsgs;
+
+ String[] resultValues;
+
+ public SomeItemInputDialog(Shell parentShell, String dialogTitle,
+ String[] inputMessages, IInputValidator[] validators) {
+ super(parentShell);
+ if (inputMessages.length != validators.length) {
+ throw new IllegalArgumentException(
+ "Specify validator counts and input message count is not same.");
+ }
+
+ this.dialogTitle = dialogTitle;
+ this.inputMessages = (String[]) inputMessages.clone();
+ this.validators = (IInputValidator[]) validators.clone();
+ this.errorMsgs = new String[validators.length];
+
+ setShellStyle(SWT.RESIZE | getShellStyle());
+ }
+
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText(dialogTitle);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite base = (Composite) super.createDialogArea(parent);
+ GridLayout gl = new GridLayout(2, false);
+ gl.marginWidth = 4;
+ gl.marginHeight = 6;
+ base.setLayout(gl);
+
+ texts = new Text[inputMessages.length];
+ for (int i = 0; i < inputMessages.length; i++) {
+ new Label(base, SWT.NONE).setText(inputMessages[i] + ":");
+
+ final int index = i;
+ Text t = new Text(base, SWT.BORDER);
+ t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ t.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ refreshValidator(index);
+ }
+ });
+ texts[i] = t;
+ }
+
+ error = new Text(base, SWT.READ_ONLY);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ error.setLayoutData(gd);
+
+ return base;
+ }
+
+ void refreshValidator(int index) {
+ String data = texts[index].getText();
+ IInputValidator validator = validators[index];
+ if (validator != null) {
+ errorMsgs[index] = validator.isValid(data);
+ }
+
+ Button okButton = getButton(IDialogConstants.OK_ID);
+ for (int i = 0; i < errorMsgs.length; i++) {
+ String msg = errorMsgs[i];
+ if (msg != null) {
+ error.setText(msg);
+ okButton.setEnabled(false);
+ return;
+ }
+ }
+ error.setText("");
+ okButton.setEnabled(true);
+ }
+
+ public String[] getValues() {
+ return (String[]) resultValues.clone();
+ }
+
+ protected Point getInitialSize() {
+ Point p = super.getInitialSize();
+ return new Point(p.x * 2, (int) (p.y * 1.25));
+ }
+
+ protected void okPressed() {
+ resultValues = new String[texts.length];
+ for (int i = 0; i < texts.length; i++) {
+ resultValues[i] = texts[i].getText();
+ }
+ super.okPressed();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/StringDivider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/StringDivider.java
new file mode 100644
index 0000000..8439fbc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/StringDivider.java
@@ -0,0 +1,75 @@
+/*
+ * $Id: StringDivider.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+public class StringDivider {
+
+ static Pattern tagNameChoosePattern = Pattern
+ .compile("<[\\s/]*(\\w+)\\s*.*>");
+
+ String[] splitRegexpCandidates = { "\t", ",", "\\s", "\\s+", };
+
+ public StringDivider() {
+ }
+
+ public String[][] divide(String content) {
+ return divide(content, getDivideSuitedRegexp(content));
+ }
+
+ public String[][] divide(String content, String regexp) {
+ String[] lines = content.split("\n");
+ int len = lines.length;
+ String[][] dist = new String[len][];
+
+ int max = Integer.MIN_VALUE;
+ for (int i = 0; i < len; i++) {
+ String line = lines[i];
+ String[] cells = line.split(regexp);
+ dist[i] = cells;
+ if (max < cells.length) {
+ max = cells.length;
+ }
+ }
+ for (int i = 0; i < len; i++) {
+ String[] newArray = new String[max];
+ Arrays.fill(newArray, "");
+ System.arraycopy(dist[i], 0, newArray, 0, dist[i].length);
+ dist[i] = newArray;
+ }
+ return dist;
+ }
+
+ public String getDivideSuitedRegexp(String content) {
+ String[] lines = content.split("\n");
+
+ String resultRegexp = null;
+ int score = Integer.MAX_VALUE, cellCount = Integer.MIN_VALUE;
+
+ for (int i = 0; i < splitRegexpCandidates.length; i++) {
+ String regexp = splitRegexpCandidates[i];
+ int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
+ for (int j = 0; j < lines.length; j++) {
+ String[] vals = lines[j].split(regexp);
+ if (max < vals.length) {
+ max = vals.length;
+ }
+ if (min > vals.length) {
+ min = vals.length;
+ }
+ }
+ int s = max - min;
+ if (score > s || (score == s && max > cellCount)) {
+ cellCount = max;
+ score = s;
+ resultRegexp = regexp;
+ }
+ }
+ return resultRegexp;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementCellModifier.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementCellModifier.java
new file mode 100644
index 0000000..62e767d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementCellModifier.java
@@ -0,0 +1,82 @@
+/*
+ * $Id: TableElementCellModifier.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.swt.widgets.Item;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+/**
+ *
+ */
+public class TableElementCellModifier implements ICellModifier {
+
+ DocumentBuilderFactory builderFactory;
+
+ IPropertyChangeListener listener;
+
+ public TableElementCellModifier(IPropertyChangeListener listener) {
+ builderFactory = DocumentBuilderFactory.newInstance();
+ this.listener = listener;
+ }
+
+ public boolean canModify(Object element, String property) {
+ return getValue(element, property) != null;
+ }
+
+ public Object getValue(Object trElem, String property) {
+ if (trElem instanceof Element) {
+ Element e = (Element) trElem;
+ if (e.getNodeName().equals("tr")) {
+ int v = TableElementModel.toNumeric(property);
+ Element[] cells = TableElementModel.chooseCellElements(e);
+ if (v >= 0 && v < cells.length) {
+ NodeList nodes = cells[v].getChildNodes();
+ if (nodes.getLength() == 1) {
+ Node n = nodes.item(0);
+ if (n instanceof Text) {
+ return n.getNodeValue();
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public void modify(Object element, String property, Object value) {
+ if (element instanceof Item) {
+ element = ((Item) element).getData();
+ }
+ Element trElem = (Element) element;
+ int index = TableElementModel.toNumeric(property);
+ Element cellElem = TableElementModel.chooseCellElements(trElem)[index];
+
+ NodeList nodes = cellElem.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ cellElem.removeChild(nodes.item(i));
+ }
+ Document doc = cellElem.getOwnerDocument();
+
+ if (value instanceof String) {
+ cellElem.appendChild(doc.createTextNode((String) value));
+ }
+ // notify listener
+ if (listener != null) {
+ String oldValue = nodes.item(0).getNodeValue();
+ listener.propertyChange(new PropertyChangeEvent(this, property,
+ (String) value, oldValue));
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementContentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementContentProvider.java
new file mode 100644
index 0000000..8a3ba8c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementContentProvider.java
@@ -0,0 +1,31 @@
+/*
+ * $Id: TableElementContentProvider.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ *
+ */
+public class TableElementContentProvider implements IStructuredContentProvider {
+
+ public TableElementContentProvider() {
+ super();
+ }
+
+ public Object[] getElements(Object inputElement) {
+ TableElementModel model = (TableElementModel) inputElement;
+ return model.getRows();
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementLabelProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementLabelProvider.java
new file mode 100644
index 0000000..7fb1752
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementLabelProvider.java
@@ -0,0 +1,45 @@
+/*
+ * $Id: TableElementLabelProvider.java,v 1.3 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.w3c.dom.Element;
+
+/**
+ *
+ */
+public class TableElementLabelProvider implements ITableLabelProvider {
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ Element[] cells = TableElementModel
+ .chooseCellElements((Element) element);
+ if (columnIndex < cells.length) {
+ Element elem = cells[columnIndex];
+ return elem.toString();
+ } else {
+ throw new IllegalArgumentException("Invalid element:" + element);
+ }
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return TableElementModel.toNumeric(property) != -1;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ public void dispose() {
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementModel.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementModel.java
new file mode 100644
index 0000000..b9aeef8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementModel.java
@@ -0,0 +1,294 @@
+/*
+ * $Id: TableElementModel.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * TableElementModel
+ */
+public class TableElementModel {
+
+ final static char[] CHAR_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+
+ StringDivider stringDivider = new StringDivider();
+
+ ElementWriter writer;
+
+ DocumentBuilder docBuilder;
+
+ Document document;
+
+ Element tableElement;
+
+ String[] columnProperties;
+
+ public TableElementModel(String content, boolean parse)
+ throws FactoryConfigurationError, ParserConfigurationException,
+ SAXException, IOException {
+ docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ if (parse) {
+ initAsParse(content);
+ } else {
+ initModel(content);
+ }
+ columnProperties = createColumnProperties();
+
+ // create elementWriter
+ writer = new ElementWriter(0, null);
+ writer.setExpandOption("caption", ElementWriter.END_CHANGELINE);
+ writer.setExpandOption("table", ElementWriter.BEGIN_CHANGELINE
+ | ElementWriter.END_CHANGELINE);
+ writer.setExpandOption("thead", ElementWriter.BEGIN_CHANGELINE
+ | ElementWriter.END_CHANGELINE);
+ writer.setExpandOption("tfoot", ElementWriter.BEGIN_CHANGELINE
+ | ElementWriter.END_CHANGELINE);
+ writer.setExpandOption("tbody", ElementWriter.BEGIN_CHANGELINE
+ | ElementWriter.END_CHANGELINE);
+ writer.setExpandOption("tr", ElementWriter.END_CHANGELINE);
+ }
+
+ void initModel(String content) throws ParserConfigurationException,
+ SAXException, IOException {
+ StringReader strReader = new StringReader(content);
+ InputSource inputSrc = new InputSource(strReader);
+
+ document = docBuilder.parse(inputSrc);
+ tableElement = document.getDocumentElement();
+
+ Element[] rows = getRows();
+ for (int i = 0; i < rows.length; i++) {
+ Element[] cells = chooseCellElements(rows[i]);
+ for (int j = 0; j < cells.length; j++) {
+ Element cell = cells[j];
+ if (!cell.hasChildNodes()) {
+ cell.appendChild(document.createTextNode(""));
+ }
+ }
+ }
+ }
+
+ public void initAsParse(String content)
+ throws ParserConfigurationException, FactoryConfigurationError {
+ // create new table model.
+ document = docBuilder.newDocument();
+ tableElement = document.createElement("table");
+
+ String[][] cells = stringDivider.divide(content);
+ if (cells.length > 0) {
+ for (int i = 0; i < cells.length; i++) {
+ String[] rows = cells[i];
+ Element tr = document.createElement("tr");
+ for (int j = 0; j < rows.length; j++) {
+ Element e = document.createElement("td");
+ e.appendChild(document.createTextNode(rows[j]));
+ tr.appendChild(e);
+ }
+ tableElement.appendChild(tr);
+ }
+
+ setColumnCount(cells[0].length);
+ } else {
+ Element tr = document.createElement("tr");
+ Element td = document.createElement("td");
+ td.appendChild(document.createTextNode(""));
+ tr.appendChild(td);
+ tableElement.appendChild(tr);
+
+ setColumnCount(1);
+ }
+ }
+
+ String[] createColumnProperties() {
+ int len = getColumnCount();
+ String[] props = new String[len];
+ for (int i = 0; i < len; i++) {
+ props[i] = toColumnName(i);
+ }
+ return props;
+ }
+
+ public void setRowCount(int rowCount) {
+ Element[] rows = getRows();
+ if (rowCount > rows.length) {
+ for (int i = rows.length; i < rowCount; i++) {
+ tableElement.appendChild(createRowElement());
+ }
+ } else if (rowCount < rows.length) {
+ for (int i = rowCount; i < rows.length; i++) {
+ tableElement.removeChild(rows[i]);
+ }
+ }
+ }
+
+ public Element[] getRows() {
+ ArrayList rows = new ArrayList();
+ NodeList nodes = tableElement.getElementsByTagName("tr");
+ for (int i = 0; i < nodes.getLength(); i++) {
+ rows.add(nodes.item(i));
+ }
+ return (Element[]) rows.toArray(new Element[rows.size()]);
+ }
+
+ public int getRowCount() {
+ return getRows().length;
+ }
+
+ Element createRowElement() {
+ Element tr = document.createElement("tr");
+ for (int i = 0, columnCount = getColumnCount(); i < columnCount; i++) {
+ Element td = document.createElement("td");
+ td.appendChild(document.createTextNode(""));
+ tr.appendChild(td);
+ }
+ return tr;
+ }
+
+ public void setColumnCount(int newLength) {
+ NodeList trs = tableElement.getElementsByTagName("tr");
+ for (int i = 0; i < trs.getLength(); i++) {
+ Element tr = (Element) trs.item(i);
+ Element[] cells = chooseCellElements(tr);
+ int colLen = cells.length;
+
+ if (newLength > colLen) {
+ for (int j = 0, len = newLength - colLen; j < len; j++) {
+ Element cell = document.createElement("td");
+ cell.appendChild(document.createTextNode(""));
+ tr.appendChild(cell);
+ }
+ } else if (newLength < colLen) {
+ for (int j = newLength; j < colLen; j++) {
+ tr.removeChild(cells[j]);
+ }
+ }
+ }
+ columnProperties = createColumnProperties();
+ }
+
+ public int getColumnCount() {
+ NodeList trs = tableElement.getElementsByTagName("tr");
+ if (trs.getLength() > 0) {
+ Element tr = (Element) trs.item(0);
+ return chooseCellElements(tr).length;
+ } else {
+ return 0;
+ }
+ }
+
+ public static Element[] chooseCellElements(Element tr) {
+ NodeList nodeList = tr.getChildNodes();
+
+ ArrayList result = new ArrayList();
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node node = nodeList.item(i);
+ if (node instanceof Element) {
+ String nodeName = node.getNodeName();
+ if (nodeName.equals("td") || nodeName.equals("th")) {
+ result.add(node);
+ }
+ }
+ }
+
+ return (Element[]) result.toArray(new Element[result.size()]);
+ }
+
+ public String expandCodes() {
+ return writer.expandTag(tableElement);
+ }
+
+ public static String toColumnName(int i) {
+ StringBuffer buff = new StringBuffer();
+ int u = i / CHAR_TABLE.length;
+ if (u > 0) {
+ buff.append(CHAR_TABLE[u - 1]);
+ }
+ buff.append(CHAR_TABLE[i % CHAR_TABLE.length]);
+ return buff.toString();
+ }
+
+ /**
+ * Return index of char map. If can not parse values return -1.
+ */
+ public static int toNumeric(String code) {
+ int result = -1;
+ for (int i = 0; i < code.length(); i++) {
+ char c = code.charAt(i);
+ int match = Arrays.binarySearch(CHAR_TABLE, c);
+ if (match >= 0) {
+ if (result == -1) {
+ result = 0;
+ }
+ int v = match;
+ int u = code.length() - 1 - i;
+ if (u > 0) {
+ v = CHAR_TABLE.length * u * (v + 1);
+ }
+ result += v;
+ }
+ }
+ return result;
+ }
+
+ public void move(Element tr, int moveCount) {
+ Element[] rows = getRows();
+ int index = -1;
+ for (int i = 0; i < rows.length; i++) {
+ if (tr.equals(rows[i])) {
+ index = i;
+ }
+ }
+ if (index == -1) {
+ throw new IllegalArgumentException(
+ "Invalid row node (not countained in this table):" + tr);
+ }
+ if (moveCount > 0) {
+ // move down;
+ for (int i = index; i < moveCount + index && i < rows.length - 1; i++) {
+ tableElement.insertBefore(rows[i + 1], rows[i]);
+ }
+ } else if (moveCount < 0) {
+ // move up
+ for (int i = index; i >= moveCount + index + 1 && i >= 1; i--) {
+ tableElement.insertBefore(rows[index], rows[i - 1]);
+ }
+ } else {
+ return;
+ }
+ }
+
+ public void insertNewRowBefore(Element tr) {
+ Element newRow = createRowElement();
+ if (tr == null) {
+ tableElement.appendChild(newRow);
+ } else {
+ tableElement.insertBefore(newRow, tr);
+ }
+ }
+
+ public void removeRow(Element tr) {
+ tableElement.removeChild(tr);
+ }
+
+ public String[] getColumnProperties() {
+ return (String[]) columnProperties.clone();
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementWizardPage.java
new file mode 100644
index 0000000..93b35ec
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/TableElementWizardPage.java
@@ -0,0 +1,290 @@
+/*
+ * $Id: TableElementWizardPage.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.CellEditor;
+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.TextCellEditor;
+import org.eclipse.swt.SWT;
+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.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.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+/**
+ * TableElementWizardPage.
+ */
+public class TableElementWizardPage extends EditElementWizardPage {
+
+ final public static int COLUMNS_MAX = 32, ROWS_MAX = 256;
+
+ final static String[] expandStyleLabels = { "Flat", "Table", "Enumerate", };
+
+ TableElementModel model;
+
+ TableViewer viewer;
+
+ CellEditor[] editors;
+
+ Combo expandStyleCombo = null;
+
+ Text colsText, rowsText;
+
+ Button addButton, removeButton, upButton, downButton;
+
+ SelectionListener buttonListener = new SelectionListener() {
+ public void widgetSelected(SelectionEvent ev) {
+ Element e = getCurrentSelection();
+ if (ev.widget == addButton) {
+ model.insertNewRowBefore(e);
+ } else if (ev.widget == removeButton) {
+ model.removeRow(e);
+ } else if (ev.widget == upButton) {
+ model.move(e, -1);
+ } else if (ev.widget == downButton) {
+ model.move(e, 1);
+ }
+ refreshAll();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ };
+
+ ModifyListener cellCountChangeListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ try {
+ if (e.widget == colsText) {
+ int cols = Integer.parseInt(colsText.getText());
+ if (cols < 1)
+ cols = 1;
+ if (cols > COLUMNS_MAX)
+ cols = COLUMNS_MAX;
+ model.setColumnCount(cols);
+ } else if (e.widget == rowsText) {
+ int rows = Integer.parseInt(rowsText.getText());
+ if (rows < 1)
+ rows = 1;
+ if (rows > ROWS_MAX)
+ rows = ROWS_MAX;
+ model.setRowCount(rows);
+ }
+ refreshAll();
+ } catch (NumberFormatException x) {
+ }
+ }
+ };
+
+ public TableElementWizardPage() {
+ super("TableElementWizardPage");
+ setTitle("Table");
+ setDescription("Edit table element and cells modifier.");
+ }
+
+ public String getPreviewText() {
+ if (model == null) {
+ initModel();
+ }
+ return (model != null) ? model.expandCodes() : null;
+ }
+
+ void initModel() {
+ String content = ((EditElementWizard) getWizard()).getSelection()
+ .getText().trim();
+ try {
+ model = new TableElementModel(content, getEditType() == NEW);
+ } catch (ParserConfigurationException e) {
+ PHPeclipsePlugin.log(e);
+ } catch (SAXException e) {
+ PHPeclipsePlugin.log(e);
+ } catch (IOException e) {
+ PHPeclipsePlugin.log(e);
+ }
+ }
+
+ protected void createChildControl(Composite parent) {
+ parent.setLayout(new GridLayout(2, false));
+
+ // table settings
+ viewer = new TableViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION
+ | SWT.BORDER);
+ refreshTableHeaderColumns();
+
+ viewer.setContentProvider(new TableElementContentProvider());
+ viewer.setLabelProvider(new TableElementLabelProvider());
+ viewer.setCellModifier(new TableElementCellModifier(
+ new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ refreshAll();
+ }
+ }));
+
+ viewer.setInput(model);
+ viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ refreshButtonState();
+ refreshPreview();
+ }
+ });
+
+ Table table = viewer.getTable();
+ table.setLinesVisible(true);
+ table.setHeaderVisible(true);
+
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.verticalSpan = 2;
+ table.setLayoutData(gd);
+
+ // text input area setting
+ Composite textInputArea = new Composite(parent, SWT.NONE);
+ textInputArea.setLayout(new GridLayout(1, false));
+ textInputArea.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.VERTICAL_ALIGN_BEGINNING));
+ rowsText = createNumInputText(textInputArea, "&Rows:");
+ colsText = createNumInputText(textInputArea, "&Columns:");
+
+ // button area.
+ Composite buttonArea = new Composite(parent, SWT.NONE);
+ buttonArea.setLayout(new GridLayout(1, false));
+ buttonArea.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.VERTICAL_ALIGN_END));
+ addButton = createButton(buttonArea, "&Add");
+ removeButton = createButton(buttonArea, "&Remove");
+ upButton = createButton(buttonArea, "&Up");
+ downButton = createButton(buttonArea, "&Down");
+
+ // init state
+ TableColumn[] cols = table.getColumns();
+ for (int i = 0; i < cols.length; i++) {
+ cols[i].pack();
+ }
+ refreshTableLengthText();
+ refreshButtonState();
+ }
+
+ Button createButton(Composite parent, String text) {
+ Button button = new Button(parent, SWT.NONE);
+ button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+ button.setText(text);
+ button.addSelectionListener(buttonListener);
+ return button;
+ }
+
+ Text createNumInputText(Composite parent, String label) {
+ Label labe = new Label(parent, SWT.NONE);
+ labe.setText(label);
+
+ Text text = new Text(parent, SWT.BORDER);
+ text.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+ text.setTextLimit(2);
+ text.addVerifyListener(new NumVerifyListener());
+ text.addModifyListener(cellCountChangeListener);
+ return text;
+ }
+
+ void refreshAll() {
+ refreshTableHeaderColumns();
+ refreshTableLengthText();
+ refreshButtonState();
+ refreshPreview();
+ viewer.refresh();
+ }
+
+ void refreshTableHeaderColumns() {
+ if (model == null) {
+ initModel();
+ }
+
+ Table table = viewer.getTable();
+ TableColumn[] cols = table.getColumns();
+ CellEditor[] editors = viewer.getCellEditors();
+
+ String[] props = model.getColumnProperties();
+ viewer.setColumnProperties(props);
+ // modify cell length
+ if (props.length > cols.length) {
+ CellEditor[] newEditors = new CellEditor[props.length];
+ if (editors != null) {
+ System.arraycopy(editors, 0, newEditors, 0, editors.length);
+ }
+ for (int i = cols.length; i < props.length; i++) {
+ TableColumn col = new TableColumn(table, SWT.LEFT);
+ col.setText(TableElementModel.toColumnName(i));
+ newEditors[i] = new TextCellEditor(table);
+ }
+ viewer.setCellEditors(newEditors);
+ } else if (props.length < cols.length) {
+ for (int i = props.length; i < cols.length; i++) {
+ cols[i].dispose();
+ editors[i].dispose();
+ }
+ CellEditor[] newEditors = new CellEditor[props.length];
+ System.arraycopy(editors, 0, newEditors, 0, props.length);
+ viewer.setCellEditors(newEditors);
+ }
+
+ // adjust table fields.
+ viewer.refresh();
+ cols = table.getColumns();
+ for (int i = 0; i < cols.length; i++) {
+ cols[i].pack();
+ }
+ }
+
+ void refreshTableLengthText() {
+ String cols = String.valueOf(model.getColumnCount());
+ if (!cols.equals(colsText.getText())) {
+ colsText.setText(cols);
+ }
+ String rows = String.valueOf(model.getRowCount());
+ if (!rows.equals(rowsText.getText())) {
+ rowsText.setText(rows);
+ }
+ }
+
+ void refreshButtonState() {
+ Element e = getCurrentSelection();
+ boolean enable = (e != null);
+
+ removeButton.setEnabled(enable);
+ int currentIndex = -1;
+ Element[] rows = model.getRows();
+ for (int i = 0; i < rows.length; i++) {
+ if (rows[i].equals(e)) {
+ currentIndex = i;
+ }
+ }
+ upButton.setEnabled(enable && currentIndex > 0);
+ downButton.setEnabled(enable && currentIndex < rows.length - 1);
+ }
+
+ Element getCurrentSelection() {
+ IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
+ return (sel != null) ? (Element) sel.getFirstElement() : null;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/UnknownElementWizardPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/UnknownElementWizardPage.java
new file mode 100644
index 0000000..817451d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/wizards/html/UnknownElementWizardPage.java
@@ -0,0 +1,334 @@
+/*
+ * $Id: UnknownElementWizardPage.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
+ * Copyright Narushima Hironori. All rights reserved.
+ */
+package net.sourceforge.phpeclipse.wizards.html;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+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.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ *
+ *
+ */
+public class UnknownElementWizardPage extends EditElementWizardPage {
+
+ // key of TableCell for attribute editor.
+ final static String NAME = "ColumnProperty-name",
+ VALUE = "ColumnProperty-value";
+
+ Button emptyElementCheck, addButton, removeButton, upButton, downButton;
+
+ TableViewer unknownElementAttrs;
+
+ ArrayList attrs = new ArrayList(), listeners = new ArrayList();
+
+ SelectionListener elemTypeChangeListener = new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ refreshPreview();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ };
+
+ public UnknownElementWizardPage() {
+ super("UnknownElementEditPage");
+ setTitle("Unknown");
+ setDescription("Editor for any HTML element.");
+ }
+
+ static IInputValidator attrValidator = new IInputValidator() {
+ public String isValid(String newText) {
+ if (newText.length() == 0) {
+ return "Need to specify name";
+ }
+ if (newText.indexOf(' ') != -1 || newText.indexOf('\n') != -1
+ || newText.indexOf('\t') != -1) {
+ return "Not contain blank";
+ }
+ return null;
+ }
+ };
+
+ protected void createChildControl(Composite parent) {
+ // empty eleemnt
+ parent.setLayout(new GridLayout(2, false));
+
+ // // attribute editor
+ Label labe = new Label(parent, SWT.NONE);
+ labe.setText("Element &Attribute:");
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ labe.setLayoutData(gd);
+ new Label(parent, SWT.NONE);
+
+ // attribute display table setting
+ unknownElementAttrs = new TableViewer(parent, SWT.BORDER | SWT.SINGLE
+ | SWT.FULL_SELECTION);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = 1;
+ gd.verticalSpan = 4;
+ unknownElementAttrs.getControl().setLayoutData(gd);
+
+ final Table table = unknownElementAttrs.getTable();
+ new TableColumn(table, SWT.LEFT).setText("Name");
+ new TableColumn(table, SWT.LEFT).setText("Value");
+
+ table.setLinesVisible(true);
+ table.setHeaderVisible(true);
+ // modifier setting
+ unknownElementAttrs.setColumnProperties(new String[] { NAME, VALUE });
+ unknownElementAttrs.setContentProvider(new ArrayContentProvider());
+
+ unknownElementAttrs.setCellEditors(new CellEditor[] {
+ new TextCellEditor(table), new TextCellEditor(table) });
+ unknownElementAttrs.setCellModifier(new ICellModifier() {
+ public boolean canModify(Object element, String property) {
+ return true;
+ }
+
+ public Object getValue(Object element, String property) {
+ return ((String[]) element)[property.equals(NAME) ? 0 : 1];
+ }
+
+ public void modify(Object element, String property, Object value) {
+ if (element instanceof Item) {
+ ((String[]) ((Item) element).getData())[property
+ .equals(NAME) ? 0 : 1] = HTMLUtilities
+ .unescape((String) value);
+ refreshPreview();
+ }
+ }
+ });
+
+ unknownElementAttrs.setLabelProvider(new ITableLabelProvider() {
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ return ((String[]) element)[columnIndex];
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return property.equals(NAME) || property.equals(VALUE);
+ }
+ });
+
+ resetAttributes();
+ unknownElementAttrs.setInput(attrs);
+
+ TableColumn[] columns = table.getColumns();
+ for (int i = 0; i < columns.length; i++) {
+ columns[i].pack();
+ }
+
+ // buttonss
+ upButton = createButton(parent, "&Up");
+ upButton.addSelectionListener(new SelectionListener() {
+
+ public void widgetSelected(SelectionEvent e) {
+ int index = getSelectionIndex();
+ if (index > 0) {
+ attrs.add(index - 1, attrs.remove(index));
+ refreshPreview();
+ }
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ downButton = createButton(parent, "&Down");
+ downButton.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ int index = getSelectionIndex();
+ if (index < attrs.size() - 1) {
+ attrs.add(index + 1, attrs.remove(index));
+ refreshPreview();
+ }
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ addButton = createButton(parent, "&Add");
+ addButton.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ int insertIndex = getSelectionIndex();
+ String[] newData = inputValue();
+ if (newData != null) {
+ attrs.add(newData);
+ refreshPreview();
+ }
+ }
+
+ String[] inputValue() {
+ SomeItemInputDialog dialog = new SomeItemInputDialog(
+ getShell(), "Input new attribute", new String[] {
+ "Attribute name", "Attribute value" },
+ new IInputValidator[] { attrValidator, null });
+
+ if (dialog.open() == Window.OK) {
+ return dialog.getValues();
+ }
+ return null;
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ removeButton = createButton(parent, "&Remove");
+ removeButton.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ int index = getSelectionIndex();
+ if (index != -1) {
+ attrs.remove(index);
+ refreshPreview();
+ }
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ emptyElementCheck = new Button(parent, SWT.CHECK);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ emptyElementCheck.setLayoutData(gd);
+ emptyElementCheck.setText("&Empty Element");
+ emptyElementCheck.addSelectionListener(elemTypeChangeListener);
+ emptyElementCheck.setSelection(isEmptyAsText());
+
+ new Label(parent, SWT.NONE);
+ }
+
+ static Button createButton(Composite parent, String text) {
+ Button button = new Button(parent, SWT.PUSH);
+ GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
+ | GridData.HORIZONTAL_ALIGN_END);
+ gd.widthHint = 60;
+ button.setLayoutData(gd);
+ button.setText(text);
+ return button;
+ }
+
+ public String getPreviewText() {
+ String elemName = getElementName();
+ if (elemName == null) {
+ return null;
+ }
+
+ // sets values
+
+ boolean empty = false;
+ if (emptyElementCheck == null) {
+ // ui uninitialized
+ empty = isEmptyAsText();
+ } else {
+ // ui initialized
+ empty = emptyElementCheck.getSelection();
+ }
+
+ String content = getSelectionText();
+ if (!empty && getEditType() == MODIFY) {
+ content = chooseContent(content);
+ }
+
+ String previewText = "<" + elemName + attrsCode();
+ if (empty) {
+ previewText += " />";
+ } else {
+ previewText += ">" + content + "" + elemName + ">";
+ }
+ return previewText;
+ }
+
+ boolean isEmptyAsText() {
+ String selText = getSelectionText();
+ if (getEditType() == MODIFY) {
+ int len = selText.length();
+ return selText.substring(len - 2, len).equals("/>");
+ }
+ return false;
+ }
+
+ void resetAttributes() {
+ attrs.clear();
+
+ Element elem = getParsedSelectionText();
+ if (elem != null) {
+ NamedNodeMap as = elem.getAttributes();
+ for (int i = 0; i < as.getLength(); i++) {
+ Node n = as.item(i);
+ attrs.add(new String[] { n.getNodeName(), n.getNodeValue() });
+ }
+ }
+ }
+
+ String attrsCode() {
+ StringBuffer buff = new StringBuffer();
+ Object[] as = attrs.toArray();
+ for (int i = 0; i < as.length; i++) {
+ String[] a = (String[]) as[i];
+ buff.append(" " + a[0] + "=\"" + HTMLUtilities.escape(a[1]) + "\"");
+ }
+ return buff.toString();
+ }
+
+ int getSelectionIndex() {
+ Object sel = unknownElementAttrs.getSelection();
+ if (sel instanceof IStructuredSelection) {
+ Object item = ((IStructuredSelection) sel).getFirstElement();
+ return attrs.indexOf(item);
+ } else {
+ return -1;
+ }
+ }
+
+ public void refreshPreview() {
+ unknownElementAttrs.refresh();
+ super.refreshPreview();
+ }
+
+ public void setElementName(String elemName) {
+ super.setElementName(elemName);
+ setTitle("\"" + elemName + "\" Element");
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/XMLPlugin.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/XMLPlugin.java
new file mode 100644
index 0000000..d886c5a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/XMLPlugin.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLPlugin.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui;
+
+import java.net.URL;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpeclipse.xml.ui.text.DTDTextTools;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class XMLPlugin extends AbstractUIPlugin {
+ public static final String ICON_ELEMENT = "element_obj.gif"; //$NON-NLS-1$
+
+ // The shared instance.
+ private static XMLPlugin plugin;
+
+ // Resource bundle.
+ private ResourceBundle resources;
+
+ private XMLTextTools xmlTextTools;
+
+ private DTDTextTools dtdTextTools;
+
+ /**
+ * The constructor.
+ */
+ public XMLPlugin() {
+ plugin = this;
+
+ try {
+ resources = ResourceBundle
+ .getBundle("net.sourceforge.phpeclipse.xml.ui.XMLPluginResources"); //$NON-NLS-1$
+ } catch (MissingResourceException x) {
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ try {
+ if (xmlTextTools != null) {
+ xmlTextTools.dispose();
+ xmlTextTools = null;
+ }
+
+ if (dtdTextTools != null) {
+ dtdTextTools.dispose();
+ dtdTextTools = null;
+ }
+ } finally {
+ super.stop(context);
+ }
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static XMLPlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns the string from the plugin's resource bundle, or 'key' if not
+ * found.
+ */
+ public static String getResourceString(String key) {
+ ResourceBundle bundle = XMLPlugin.getDefault().getResourceBundle();
+ try {
+ return bundle.getString(key);
+ } catch (MissingResourceException e) {
+ return key;
+ }
+ }
+
+ /**
+ * Returns the plugin's resource bundle.
+ */
+ public ResourceBundle getResourceBundle() {
+ return resources;
+ }
+
+ /**
+ * Returns instance of text tools for XML.
+ */
+ public XMLTextTools getXMLTextTools() {
+ if (xmlTextTools == null) {
+ xmlTextTools = new XMLTextTools(getPreferenceStore());
+ }
+ return xmlTextTools;
+ }
+
+ /**
+ * Returns instance of text tools for DTD.
+ */
+ public DTDTextTools getDTDTextTools() {
+ if (dtdTextTools == null) {
+ dtdTextTools = new DTDTextTools(getPreferenceStore());
+ }
+ return dtdTextTools;
+ }
+
+ /*
+ * @see AbstractUIPlugin#initializeImageRegistry(ImageRegistry)
+ */
+ protected void initializeImageRegistry(ImageRegistry reg) {
+ reg.put(ICON_ELEMENT, getImageDescriptor(ICON_ELEMENT));
+ }
+
+ /**
+ * Returns an image descriptor for the image corresponding to the specified
+ * key (which is the name of the image file).
+ *
+ * @param key
+ * The key of the image
+ * @return The descriptor for the requested image, or null
if
+ * the image could not be found
+ */
+ private ImageDescriptor getImageDescriptor(String key) {
+ try {
+ URL url = getBundle().getEntry("/icons/" + key); //$NON-NLS-1$
+ return ImageDescriptor.createFromURL(url);
+ } catch (IllegalStateException e) {
+ return null;
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/XMLPluginResources.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/XMLPluginResources.properties
new file mode 100644
index 0000000..3b08588
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/XMLPluginResources.properties
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2003 Christopher Lenz and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# Igor Malinin - initial english resources
+#
+# $Id: XMLPluginResources.properties,v 1.1 2004-09-02 18:28:04 jsurfer Exp $
+#
+
+####
+# XML Syntax Highlighting Preferences
+####
+
+XmlSyntaxPreferencePage.others=Others
+XmlSyntaxPreferencePage.PI=Precessing Instruction
+XmlSyntaxPreferencePage.Declaration=Declaration
+XmlSyntaxPreferencePage.Comment=Comment
+XmlSyntaxPreferencePage.Tag=Tag Name
+XmlSyntaxPreferencePage.AttName=Attribute Name
+XmlSyntaxPreferencePage.AttValue=Attribute Value
+XmlSyntaxPreferencePage.Entity=XML Entity
+XmlSyntaxPreferencePage.CDATA=CDATA Section
+XmlSyntaxPreferencePage.SmartyTag=Smarty Tag Name
+XmlSyntaxPreferencePage.Conditional=Conditional Section
+
+
+XmlSyntaxPreferencePage.description=XML Syntax Colors
+XmlSyntaxPreferencePage.backgroundColor=Background Color
+XmlSyntaxPreferencePage.systemDefault=System Default
+XmlSyntaxPreferencePage.custom=Custom
+XmlSyntaxPreferencePage.foreground=Foreground
+XmlSyntaxPreferencePage.color=Color
+XmlSyntaxPreferencePage.bold=Bold
+XmlSyntaxPreferencePage.italic=Italic
+XmlSyntaxPreferencePage.preview=Preview
+
+DTDMergeViewer.title=DTD Source Compare
+XMLMergeViewer.title=XML Source Compare
+
+## Actions ##
+
+ContentAssistProposal.label=Content Assist@Ctrl+SPACE
+ContentAssistProposal.tooltip=Content Assist
+ContentAssistProposal.image=
+ContentAssistProposal.description=Content Assist
+
+CompletionProcessor.ContextInfo.display.pattern=proposal {0} at position {1}
+CompletionProcessor.ContextInfo.value.pattern=proposal {0} valid from {1} to {2}
+CompletionProcessor.Proposal.ContextInfo.pattern={0} valid 5 characters around insertion point
+CompletionProcessor.Proposal.hoverinfo.pattern=Java keyword: {0}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/DTDMergeViewer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/DTDMergeViewer.java
new file mode 100644
index 0000000..a833e92
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/DTDMergeViewer.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: DTDMergeViewer.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.compare;
+
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.DTDConfiguration;
+import net.sourceforge.phpeclipse.xml.ui.text.DTDTextTools;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+/**
+ * @author Igor Malinin
+ */
+public class DTDMergeViewer extends TextMergeViewer {
+
+ /**
+ * The preference store.
+ */
+ private IPreferenceStore preferenceStore;
+
+ /**
+ * The listener for changes to the preference store.
+ */
+ private IPropertyChangeListener propertyChangeListener;
+
+ /**
+ * The DTD text tools.
+ */
+ private DTDTextTools textTools;
+
+ /*
+ * @see TextMergeViewer#TextMergeViewer(Composite, int,
+ * CompareConfiguration)
+ */
+ public DTDMergeViewer(Composite parent, int style,
+ CompareConfiguration configuration) {
+ super(parent, style, configuration);
+ }
+
+ // TextMergeViewer Implementation ------------------------------------------
+
+ /*
+ * @see TextMergeViewer#configureTextViewer()
+ */
+ protected void configureTextViewer(TextViewer textViewer) {
+ XMLPlugin plugin = XMLPlugin.getDefault();
+
+ preferenceStore = plugin.getPreferenceStore();
+ if (preferenceStore != null) {
+ propertyChangeListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ handlePreferenceStoreChanged(event);
+ }
+ };
+ preferenceStore.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ textTools = plugin.getDTDTextTools();
+
+ if (textViewer instanceof SourceViewer) {
+ SourceViewer sourceViewer = (SourceViewer) textViewer;
+ sourceViewer.configure(new DTDConfiguration(textTools));
+ }
+
+ updateBackgroundColor();
+ }
+
+ /*
+ * @see TextMergeViewer#getDocumentPartitioner()
+ */
+ protected IDocumentPartitioner getDocumentPartitioner() {
+ return textTools.createDTDPartitioner();
+ }
+
+ /*
+ * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getTitle()
+ */
+ public String getTitle() {
+ return XMLPlugin.getResourceString("DTDMergeViewer.title"); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ContentViewer#handleDispose(org.eclipse.swt.events.DisposeEvent)
+ */
+ protected void handleDispose(DisposeEvent event) {
+ if (propertyChangeListener != null) {
+ if (preferenceStore != null) {
+ preferenceStore
+ .removePropertyChangeListener(propertyChangeListener);
+ }
+
+ propertyChangeListener = null;
+ }
+
+ super.handleDispose(event);
+ }
+
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ String p = event.getProperty();
+
+ if (p.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)
+ || p
+ .equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
+ updateBackgroundColor();
+ } else if (textTools.affectsBehavior(event)) {
+ invalidateTextPresentation();
+ }
+ }
+
+ private void updateBackgroundColor() {
+ boolean defaultBackgroundColor = preferenceStore
+ .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT);
+
+ if (defaultBackgroundColor) {
+ setBackgroundColor(null);
+ } else {
+ RGB backgroundColor = PreferenceConverter.getColor(preferenceStore,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND);
+ setBackgroundColor(backgroundColor);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/DTDMergeViewerCreator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/DTDMergeViewerCreator.java
new file mode 100644
index 0000000..6eeb9fc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/DTDMergeViewerCreator.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: DTDMergeViewerCreator.java,v 1.1 2004-09-02 18:28:05 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.compare;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.IViewerCreator;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * @author Igor Malinin
+ */
+public class DTDMergeViewerCreator implements IViewerCreator {
+
+ /*
+ * @see IViewerCreator#createViewer(Composite, CompareConfiguration)
+ */
+ public Viewer createViewer(Composite parent, CompareConfiguration config) {
+ return new DTDMergeViewer(parent, SWT.NULL, config);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/XMLMergeViewer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/XMLMergeViewer.java
new file mode 100644
index 0000000..7947a8e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/XMLMergeViewer.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLMergeViewer.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.compare;
+
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLConfiguration;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+/**
+ * @author Igor Malinin
+ */
+public class XMLMergeViewer extends TextMergeViewer {
+
+ /**
+ * The preference store.
+ */
+ private IPreferenceStore preferenceStore;
+
+ /**
+ * The listener for changes to the preference store.
+ */
+ private IPropertyChangeListener propertyChangeListener;
+
+ /**
+ * The XML text tools.
+ */
+ private XMLTextTools textTools;
+
+ /*
+ * @see TextMergeViewer#TextMergeViewer(Composite, int,
+ * CompareConfiguration)
+ */
+ public XMLMergeViewer(Composite parent, int style,
+ CompareConfiguration configuration) {
+ super(parent, style, configuration);
+ }
+
+ // TextMergeViewer Implementation
+ // ------------------------------------------
+
+ /*
+ * @see TextMergeViewer#configureTextViewer()
+ */
+ protected void configureTextViewer(TextViewer textViewer) {
+ XMLPlugin plugin = XMLPlugin.getDefault();
+
+ preferenceStore = plugin.getPreferenceStore();
+ if (preferenceStore != null) {
+ propertyChangeListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ handlePreferenceStoreChanged(event);
+ }
+ };
+ preferenceStore.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ textTools = plugin.getXMLTextTools();
+
+ if (textViewer instanceof SourceViewer) {
+ SourceViewer sourceViewer = (SourceViewer) textViewer;
+ sourceViewer.configure(new XMLConfiguration(textTools));
+ }
+
+ updateBackgroundColor();
+ }
+
+ /*
+ * @see TextMergeViewer#getDocumentPartitioner()
+ */
+ protected IDocumentPartitioner getDocumentPartitioner() {
+ return textTools.createXMLPartitioner();
+ }
+
+ /*
+ * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getTitle()
+ */
+ public String getTitle() {
+ return XMLPlugin.getResourceString("XMLMergeViewer.title"); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ContentViewer#handleDispose(org.eclipse.swt.events.DisposeEvent)
+ */
+ protected void handleDispose(DisposeEvent event) {
+ if (propertyChangeListener != null) {
+ if (preferenceStore != null) {
+ preferenceStore
+ .removePropertyChangeListener(propertyChangeListener);
+ }
+
+ propertyChangeListener = null;
+ }
+
+ super.handleDispose(event);
+ }
+
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ String p = event.getProperty();
+
+ if (p.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)
+ || p
+ .equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
+ updateBackgroundColor();
+ } else if (textTools.affectsBehavior(event)) {
+ invalidateTextPresentation();
+ }
+ }
+
+ private void updateBackgroundColor() {
+ boolean defaultBackgroundColor = preferenceStore
+ .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT);
+
+ if (defaultBackgroundColor) {
+ setBackgroundColor(null);
+ } else {
+ RGB backgroundColor = PreferenceConverter.getColor(preferenceStore,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND);
+ setBackgroundColor(backgroundColor);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/XMLMergeViewerCreator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/XMLMergeViewerCreator.java
new file mode 100644
index 0000000..60f84c0
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/compare/XMLMergeViewerCreator.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLMergeViewerCreator.java,v 1.1 2004-09-02 18:28:05 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.compare;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.IViewerCreator;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * @author Igor Malinin
+ */
+public class XMLMergeViewerCreator implements IViewerCreator {
+
+ /*
+ * @see IViewerCreator#createViewer(Composite, CompareConfiguration)
+ */
+ public Viewer createViewer(Composite parent, CompareConfiguration config) {
+ return new XMLMergeViewer(parent, SWT.NULL, config);
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/DTDEditor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/DTDEditor.java
new file mode 100644
index 0000000..43f76d7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/DTDEditor.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: DTDEditor.java,v 1.3 2006-10-21 23:14:14 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.DTDConfiguration;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.DTDDocumentProvider;
+import net.sourceforge.phpeclipse.xml.ui.text.DTDTextTools;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+
+/**
+ * DTD Editor.
+ *
+ * @author Igor Malinin
+ */
+public class DTDEditor extends TextEditor {
+
+ public DTDEditor() {
+ setPreferenceStore(XMLPlugin.getDefault().getPreferenceStore());
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.TextEditor#initializeEditor()
+ */
+ protected void initializeEditor() {
+ super.initializeEditor();
+
+ DTDTextTools dtdTextTools = XMLPlugin.getDefault().getDTDTextTools();
+
+ setSourceViewerConfiguration(new DTDConfiguration(dtdTextTools));
+
+ setDocumentProvider(new DTDDocumentProvider());
+ }
+
+ protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+ return XMLPlugin.getDefault().getDTDTextTools().affectsBehavior(event);
+ }
+
+ protected void createActions() {
+ super.createActions();
+
+ IAction action = new ContentAssistAction(XMLEditorMessages
+ .getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$
+ action
+ .setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ setAction("ContentAssistProposal", action); //$NON-NLS-1$
+ markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
+
+ // IAction action= new TextOperationAction(
+ // TemplateMessages.getResourceBundle(),
+ // "Editor." + TEMPLATE_PROPOSALS + ".", //$NON-NLS-1$ //$NON-NLS-2$
+ // this,
+ // ISourceViewer.CONTENTASSIST_PROPOSALS);
+ // action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ // setAction(TEMPLATE_PROPOSALS, action);
+ // markAsStateDependentAction(TEMPLATE_PROPOSALS, true);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLDocumentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLDocumentProvider.java
new file mode 100644
index 0000000..999fd08
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLDocumentProvider.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2003-2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLDocumentProvider.java,v 1.3 2006-10-21 23:14:14 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.editor;
+
+import java.net.MalformedURLException;
+
+import net.sourceforge.phpeclipse.xml.core.internal.model.XMLDocument;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.ui.editors.text.TextFileDocumentProvider;
+
+/**
+ * Document provider for XML files.
+ *
+ * TODO Merge the encoding detection support from I18NDocumentProvider and
+ * AbstractDocumentProvider into this class
+ *
+ * TODO This class currently doubles as a model manager which will need to be
+ * moved into core at some point, and would make this class pretty much useless
+ */
+public class XMLDocumentProvider extends TextFileDocumentProvider {
+
+ // Inner Classes -----------------------------------------------------------
+
+ private class XMLFileInfo extends FileInfo {
+ IXMLDocument xmlDocument;
+ }
+
+ // TestFileDocumentProvider Implementation ---------------------------------
+
+ /*
+ * @see TextFileDocumentProvider#createEmptyFileInfo()
+ */
+ protected FileInfo createEmptyFileInfo() {
+ return new XMLFileInfo();
+ }
+
+ /*
+ * @see TextFileDocumentProvider#createFileInfo(Object)
+ */
+ protected FileInfo createFileInfo(Object element) throws CoreException {
+ FileInfo fileInfo = super.createFileInfo(element);
+ if (!(fileInfo instanceof XMLFileInfo)) {
+ return null;
+ }
+
+ IDocument document = fileInfo.fTextFileBuffer.getDocument();
+
+ String systemId = null;
+ try {
+ systemId = getSystemFile(fileInfo).toURL().toString();
+ } catch (MalformedURLException e) {
+ }
+
+ IXMLDocument xmlDocument = createModel(document, systemId);
+ if (xmlDocument instanceof IDocumentListener) {
+ document.addDocumentListener((IDocumentListener) xmlDocument);
+ }
+
+ XMLFileInfo xmlFileInfo = (XMLFileInfo) fileInfo;
+ xmlFileInfo.xmlDocument = xmlDocument;
+
+ return xmlFileInfo;
+ }
+
+ /*
+ * @see TextFileDocumentProvider#disposeFileInfo(Object,
+ * TextFileDocumentProvider.FileInfo)
+ */
+ protected void disposeFileInfo(Object element, FileInfo info) {
+ if (info instanceof XMLFileInfo) {
+ IDocument document = getDocument(element);
+ if (document != null) {
+ IXMLDocument xmlDocument = ((XMLFileInfo) info).xmlDocument;
+ if (xmlDocument instanceof IDocumentListener) {
+ document
+ .removeDocumentListener((IDocumentListener) xmlDocument);
+ }
+ }
+ }
+
+ super.disposeFileInfo(element, info);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Creates the XML document model object corresponding to the specified
+ * document.
+ *
+ * @param document
+ * the document to parse
+ * @param systemId
+ * the system ID of the document
+ * @return the document model object
+ */
+ public IXMLDocument createModel(IDocument document, String systemId) {
+ return new XMLDocument(document, systemId);
+ }
+
+ /**
+ * Returns the XML document model associated with the specified element.
+ *
+ * @param element
+ * the element
+ * @return the document model associated with the element
+ */
+ public IXMLDocument getModel(Object element) {
+ FileInfo info = getFileInfo(element);
+ if (info instanceof XMLFileInfo) {
+ XMLFileInfo xmlFileInfo = (XMLFileInfo) info;
+ return xmlFileInfo.xmlDocument;
+ }
+
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLDocumentSetupParticipant.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLDocumentSetupParticipant.java
new file mode 100644
index 0000000..40fa9a4
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLDocumentSetupParticipant.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial implementation
+ *
+ * $Id: XMLDocumentSetupParticipant.java,v 1.3 2006-10-21 23:14:14 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+
+/**
+ * Document setup participant that sets up the CSS specific partitioning.
+ */
+public class XMLDocumentSetupParticipant implements IDocumentSetupParticipant {
+
+ /*
+ * @see IDocumentSetupParticipant#setup(IDocument)
+ */
+ public void setup(IDocument document) {
+ if (document != null) {
+ XMLTextTools tools = XMLPlugin.getDefault().getXMLTextTools();
+ IDocumentPartitioner partitioner = tools.createXMLPartitioner();
+ partitioner.connect(document);
+ document.setDocumentPartitioner(partitioner);
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditor.java
new file mode 100644
index 0000000..bd096c2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditor.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ * Christopher Lenz - integrated outline page
+ *
+ * $Id: XMLEditor.java,v 1.4 2006-10-21 23:14:14 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.editor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.ui.editor.ShowExternalPreviewAction;
+import net.sourceforge.phpeclipse.ui.text.IReconcilingParticipant;
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.internal.outline.XMLOutlinePage;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLConfiguration;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * XML Editor.
+ *
+ * @author Igor Malinin
+ */
+public class XMLEditor extends TextEditor implements IReconcilingParticipant {
+
+ /**
+ * Listens to changes to the selection in the outline page, and changes the
+ * selection and highlight range in the editor accordingly.
+ */
+ private class OutlineSelectionChangedListener implements
+ ISelectionChangedListener {
+
+ /*
+ * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) event
+ .getSelection();
+ if (selection.isEmpty()) {
+ resetHighlightRange();
+ } else {
+ ISourceReference element = (ISourceReference) selection
+ .getFirstElement();
+ highlightElement(element, true);
+ }
+ }
+
+ }
+
+ /**
+ * The associated outline page.
+ */
+ XMLOutlinePage outlinePage;
+
+ int fType;
+
+ /**
+ * Listens to changes in the outline page's selection to update the editor
+ * selection and highlight range.
+ */
+ private ISelectionChangedListener outlineSelectionChangedListener;
+
+ public XMLEditor() {
+ this(ShowExternalPreviewAction.XML_TYPE);
+ }
+
+ /**
+ * Constructor.
+ */
+ public XMLEditor(int type) {
+ fType = type;
+ List stores = new ArrayList(3);
+
+ stores.add(XMLPlugin.getDefault().getPreferenceStore());
+ stores.add(EditorsUI.getPreferenceStore());
+
+ setPreferenceStore(new ChainedPreferenceStore(
+ (IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores
+ .size()])));
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter.equals(IContentOutlinePage.class)) {
+ if (outlinePage == null) {
+ outlinePage = new XMLOutlinePage(this);
+ outlineSelectionChangedListener = new OutlineSelectionChangedListener();
+ outlinePage
+ .addSelectionChangedListener(outlineSelectionChangedListener);
+ }
+
+ return outlinePage;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+ /*
+ * @see IReconcilingParticipant#reconciled()
+ */
+ public void reconciled() {
+ Shell shell = getSite().getShell();
+ if ((shell != null) && !shell.isDisposed()) {
+ shell.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (outlinePage != null) {
+ outlinePage.update();
+ }
+ }
+ });
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.editors.text.TextEditor#initializeEditor()
+ */
+ protected void initializeEditor() {
+ super.initializeEditor();
+
+ XMLTextTools xmlTextTools = XMLPlugin.getDefault().getXMLTextTools();
+ setSourceViewerConfiguration(new XMLConfiguration(xmlTextTools, this));
+ setDocumentProvider(new XMLDocumentProvider());
+
+ ShowExternalPreviewAction fShowExternalPreviewAction = ShowExternalPreviewAction
+ .getInstance();
+ fShowExternalPreviewAction.setEditor(this);
+ fShowExternalPreviewAction.update();
+ if (fShowExternalPreviewAction != null)
+ fShowExternalPreviewAction.doRun(fType);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
+ */
+ protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+ return XMLPlugin.getDefault().getXMLTextTools().affectsBehavior(event);
+ }
+
+ void highlightElement(ISourceReference element, boolean moveCursor) {
+ if (element != null) {
+ IRegion highlightRegion = element.getSourceRegion();
+ setHighlightRange(highlightRegion.getOffset(), highlightRegion
+ .getLength(), moveCursor);
+ } else {
+ resetHighlightRange();
+ }
+ }
+
+ protected void createActions() {
+ super.createActions();
+
+ IAction action = new ContentAssistAction(XMLEditorMessages
+ .getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$
+ action
+ .setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ setAction("ContentAssistProposal", action); //$NON-NLS-1$
+ markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
+
+ // IAction action= new TextOperationAction(
+ // TemplateMessages.getResourceBundle(),
+ // "Editor." + TEMPLATE_PROPOSALS + ".", //$NON-NLS-1$ //$NON-NLS-2$
+ // this,
+ // ISourceViewer.CONTENTASSIST_PROPOSALS);
+ // action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ // setAction(TEMPLATE_PROPOSALS, action);
+ // markAsStateDependentAction(TEMPLATE_PROPOSALS, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorSaved()
+ */
+ protected void editorSaved() {
+ super.editorSaved();
+ ShowExternalPreviewAction a = ShowExternalPreviewAction.getInstance();
+ if (a != null) {
+ a.refresh(fType);
+ }
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorActionContributor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorActionContributor.java
new file mode 100644
index 0000000..8d65d7c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorActionContributor.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xml.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.ui.editor.ShowExternalPreviewAction;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.texteditor.BasicTextEditorActionContributor;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Common base class for action contributors for Java editors.
+ */
+public class XMLEditorActionContributor extends
+ BasicTextEditorActionContributor {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IEditorActionBarContributor#setActiveEditor(org.eclipse.ui.IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart part) {
+ super.setActiveEditor(part);
+ ITextEditor textEditor = null;
+ if (part instanceof ITextEditor)
+ textEditor = (ITextEditor) part;
+
+ if (textEditor != null) {
+ IFile file = null;
+ IEditorInput editorInput = textEditor.getEditorInput();
+
+ if (editorInput instanceof IFileEditorInput) {
+ file = ((IFileEditorInput) editorInput).getFile();
+ }
+
+ ShowExternalPreviewAction fShowExternalPreviewAction = ShowExternalPreviewAction
+ .getInstance();
+ fShowExternalPreviewAction.setEditor(textEditor);
+ fShowExternalPreviewAction.update();
+ if (fShowExternalPreviewAction != null)
+ fShowExternalPreviewAction
+ .doRun(ShowExternalPreviewAction.PHP_TYPE);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorMessages.java
new file mode 100644
index 0000000..906e74b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorMessages.java
@@ -0,0 +1,46 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.xml.ui.internal.editor;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class XMLEditorMessages {
+
+ private static final String RESOURCE_BUNDLE = "net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLEditorMessages";//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle = ResourceBundle
+ .getBundle(RESOURCE_BUNDLE);
+
+ private XMLEditorMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * 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);
+ }
+
+ public static ResourceBundle getResourceBundle() {
+ return fgResourceBundle;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorMessages.properties
new file mode 100644
index 0000000..bea66ef
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/editor/XMLEditorMessages.properties
@@ -0,0 +1,10 @@
+#############################################################
+#
+# (c) Copyright IBM Corp. 2000, 2001.
+# All Rights Reserved.
+#
+#############################################################
+ContentAssistProposal.label=Content Assist@Ctrl+SPACE
+ContentAssistProposal.tooltip=Content Assist
+ContentAssistProposal.image=
+ContentAssistProposal.description=Content Assist
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlineContentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlineContentProvider.java
new file mode 100644
index 0000000..4484e94
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlineContentProvider.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLOutlineContentProvider.java,v 1.3 2006-10-21 23:14:14 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.outline;
+
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLElement;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Content provider for the XML outline page.
+ */
+public class XMLOutlineContentProvider implements ITreeContentProvider {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The parsed XML document.
+ */
+ private IXMLDocument document;
+
+ // ITreeContentProvider Implementation -------------------------------------
+
+ /*
+ * ITreeContentProvider#getChildren(Object)
+ */
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof IXMLElement) {
+ return ((IXMLElement) parentElement).getChildren();
+ }
+ return new Object[0];
+ }
+
+ /*
+ * @see ITreeContentProvider#getParent(Object)
+ */
+ public Object getParent(Object element) {
+ if (element instanceof IXMLElement) {
+ return ((IXMLElement) element).getParent();
+ }
+ return null;
+ }
+
+ /*
+ * @see ITreeContentProvider#hasChildren(Object)
+ */
+ public boolean hasChildren(Object element) {
+ return getChildren(element).length > 0;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ if ((document != null) && (document.getRoot() != null)) {
+ return new Object[] { document.getRoot() };
+ }
+ return new Object[0];
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ document = null;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer,
+ * Object, Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (oldInput != newInput) {
+ if (oldInput instanceof IXMLDocument) {
+ document = null;
+ }
+ if (newInput instanceof IXMLDocument) {
+ document = (IXMLDocument) newInput;
+ }
+ }
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlineLabelProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlineLabelProvider.java
new file mode 100644
index 0000000..38fd25c
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlineLabelProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLOutlineLabelProvider.java,v 1.3 2006-10-21 23:14:14 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.outline;
+
+import net.sourceforge.phpeclipse.xml.core.model.IXMLElement;
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Label provider for the XML outline page.
+ */
+public class XMLOutlineLabelProvider extends LabelProvider {
+
+ // LabelProvider Implementation --------------------------------------------
+
+ /**
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ if (element instanceof IXMLElement) {
+ return XMLPlugin.getDefault().getImageRegistry().get(
+ XMLPlugin.ICON_ELEMENT);
+ }
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ if (element instanceof IXMLElement) {
+ IXMLElement xmlElement = (IXMLElement) element;
+ StringBuffer buf = new StringBuffer();
+ if (xmlElement.getPrefix() != null) {
+ buf.append(xmlElement.getPrefix());
+ buf.append(':');
+ }
+ buf.append(xmlElement.getLocalName());
+ return buf.toString();
+ }
+ return null;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlinePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlinePage.java
new file mode 100644
index 0000000..0daae7d
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/outline/XMLOutlinePage.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLOutlinePage.java,v 1.3 2006-10-21 23:14:14 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.outline;
+
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.ui.views.outline.ProblemsLabelDecorator;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLDocumentProvider;
+import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLEditor;
+
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+/**
+ * Implements the outline page associated with the XML editor.
+ */
+public class XMLOutlinePage extends ContentOutlinePage {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated editor.
+ */
+ private XMLEditor editor;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param editor
+ * The associated text editor
+ */
+ public XMLOutlinePage(XMLEditor editor) {
+ this.editor = editor;
+ }
+
+ // ContentOutlinePage Implementation ---------------------------------------
+
+ /*
+ * @see org.eclipse.ui.part.IPage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ TreeViewer viewer = getTreeViewer();
+ viewer.setContentProvider(new XMLOutlineContentProvider());
+ viewer.setLabelProvider(new DecoratingLabelProvider(
+ new XMLOutlineLabelProvider(), new ProblemsLabelDecorator(
+ editor)));
+ viewer.setInput(getDocument());
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Selects a specific element in the outline page.
+ *
+ * @param element
+ * the element to select
+ */
+ public void select(ISourceReference element) {
+ TreeViewer viewer = getTreeViewer();
+ if (viewer != null) {
+ ISelection selection = viewer.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ List elements = structuredSelection.toList();
+ if (!elements.contains(element)) {
+ if (element == null) {
+ selection = StructuredSelection.EMPTY;
+ } else {
+ selection = new StructuredSelection(element);
+ }
+ viewer.setSelection(selection, true);
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates the outline page.
+ */
+ public void update() {
+ IXMLDocument document = getDocument();
+ if (document != null) {
+ TreeViewer viewer = getTreeViewer();
+ if (viewer != null) {
+ Control control = viewer.getControl();
+ if ((control != null) && !control.isDisposed()) {
+ control.setRedraw(false);
+ viewer.setInput(document);
+ viewer.expandAll();
+ control.setRedraw(true);
+ }
+ }
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the parsed model of the XML document that is loaded into the
+ * associated editor.
+ *
+ * @return the parsed XML document
+ */
+ private IXMLDocument getDocument() {
+ IDocumentProvider provider = editor.getDocumentProvider();
+ if (provider instanceof XMLDocumentProvider) {
+ XMLDocumentProvider xmlProvider = (XMLDocumentProvider) provider;
+ return xmlProvider.getModel(editor.getEditorInput());
+ }
+ return null;
+ }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/ContentAssistPreference.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/ContentAssistPreference.java
new file mode 100644
index 0000000..25b27d1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/ContentAssistPreference.java
@@ -0,0 +1,65 @@
+package net.sourceforge.phpeclipse.xml.ui.internal.preferences;
+
+import net.sourceforge.phpeclipse.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.ui.templates.template.BasicCompletionProcessor;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLPartitionScanner;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+
+public class ContentAssistPreference {
+ /** Preference key for html content assist auto activation triggers */
+ private final static String AUTOACTIVATION_TRIGGERS_HTML = PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_HTML;
+
+ /** Preference key for alphabetic ordering of proposals */
+ private final static String ORDER_PROPOSALS = PreferenceConstants.CODEASSIST_ORDER_PROPOSALS;
+
+ private static BasicCompletionProcessor getHTMLProcessor(
+ ContentAssistant assistant) {
+ IContentAssistProcessor p = assistant
+ .getContentAssistProcessor(XMLPartitionScanner.XML_TAG);
+ if (p instanceof BasicCompletionProcessor)
+ return (BasicCompletionProcessor) p;
+ return null;
+ }
+
+ private static void configureHTMLProcessor(ContentAssistant assistant,
+ IPreferenceStore store) {
+ BasicCompletionProcessor hcp = getHTMLProcessor(assistant);
+ if (hcp == null)
+ return;
+
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_HTML);
+ if (triggers != null)
+ hcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+
+ boolean enabled;
+ // boolean enabled = store.getBoolean(CASE_SENSITIVITY);
+ // jdcp.restrictProposalsToMatchingCases(enabled);
+
+ enabled = store.getBoolean(ORDER_PROPOSALS);
+ // hcp.orderProposalsAlphabetically(enabled);
+ }
+
+ private static void changeHTMLProcessor(ContentAssistant assistant,
+ IPreferenceStore store, String key) {
+ BasicCompletionProcessor jdcp = getHTMLProcessor(assistant);
+ if (jdcp == null)
+ return;
+
+ if (AUTOACTIVATION_TRIGGERS_HTML.equals(key)) {
+ String triggers = store.getString(AUTOACTIVATION_TRIGGERS_HTML);
+ if (triggers != null)
+ jdcp.setCompletionProposalAutoActivationCharacters(triggers
+ .toCharArray());
+ // } else if (CASE_SENSITIVITY.equals(key)) {
+ // boolean enabled = store.getBoolean(CASE_SENSITIVITY);
+ // jdcp.restrictProposalsToMatchingCases(enabled);
+ } else if (ORDER_PROPOSALS.equals(key)) {
+ boolean enable = store.getBoolean(ORDER_PROPOSALS);
+ // jdcp.orderProposalsAlphabetically(enable);
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/XMLPreferenceInitializer.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/XMLPreferenceInitializer.java
new file mode 100644
index 0000000..4b6aefb
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/XMLPreferenceInitializer.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2002-2004 Roberto Gonzalez Rocha and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Roberto Gonzalez Rocha - Initial version
+ * Igor Malinin - refactoring, minor changes
+ *
+ * $Id: XMLPreferenceInitializer.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+package net.sourceforge.phpeclipse.xml.ui.internal.preferences;
+
+/*import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.PropertyResourceBundle;
+*/
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpeclipse.ui.IPreferenceConstants;
+
+import net.sourceforge.phpeclipse.phpeditor.PHPSyntaxRdr;
+import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.preferences.ITextStylePreferences;
+//import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.text.IXMLSyntaxConstants;
+
+//import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+/**
+ * @author Igor Malinin
+ */
+public class XMLPreferenceInitializer extends AbstractPreferenceInitializer implements IPreferenceConstants {
+ /*
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ public void initializeDefaultPreferences() {
+ final IPreferenceStore store = /*XMLPlugin*/WebUI.getDefault()
+ .getPreferenceStore();
+ final Display display = Display.getDefault();
+
+ // TODO: ChainedPreferenceStore does not work for preferences preview
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ PreferenceConverter.setDefault(store,
+ AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND, display
+ .getSystemColor(SWT.COLOR_LIST_FOREGROUND)
+ .getRGB());
+ }
+ });
+
+ store.setDefault(
+ AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT,
+ true);
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ PreferenceConverter.setDefault(store,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND, display
+ .getSystemColor(SWT.COLOR_LIST_BACKGROUND)
+ .getRGB());
+ }
+ });
+
+ store.setDefault(
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT,
+ true);
+
+ // end of common preferences
+
+ setDefault(store, IXMLSyntaxConstants.XML_DEFAULT, "0,0,0",
+ ITextStylePreferences.STYLE_NORMAL);
+
+ setDefault(store, IXMLSyntaxConstants.XML_TAG, "127,0,127",
+ ITextStylePreferences.STYLE_NORMAL);
+
+ setDefault(store, IXMLSyntaxConstants.XML_ATT_NAME, "0,127,0",
+ ITextStylePreferences.STYLE_NORMAL);
+
+ setDefault(store, IXMLSyntaxConstants.XML_ATT_VALUE, "0,0,255",
+ ITextStylePreferences.STYLE_NORMAL);
+
+ setDefault(store, IXMLSyntaxConstants.XML_ENTITY, "127,127,0",
+ ITextStylePreferences.STYLE_NORMAL);
+
+ setDefault(store, IXMLSyntaxConstants.XML_CDATA, "127,127,0",
+ ITextStylePreferences.STYLE_NORMAL);
+
+ setDefault(store, IXMLSyntaxConstants.XML_PI, "127,127,127",
+ ITextStylePreferences.STYLE_BOLD);
+
+ setDefault(store, IXMLSyntaxConstants.XML_COMMENT, "127,0,0",
+ ITextStylePreferences.STYLE_NORMAL);
+
+ setDefault(store, IXMLSyntaxConstants.XML_DECL, "127,0,127",
+ ITextStylePreferences.STYLE_BOLD);
+
+ setDefault(store, IXMLSyntaxConstants.XML_SMARTY, "255,0,127",
+ ITextStylePreferences.STYLE_BOLD);
+
+ setDefault(store, IXMLSyntaxConstants.DTD_CONDITIONAL, "127,127,0",
+ ITextStylePreferences.STYLE_BOLD);
+
+ String operatingSystem = Platform.getOS();
+ // maxosx, linux, solaris, win32,...
+ try {
+ /*InputStream is = getDefault()
+ .openStream(
+ new Path("prefs/default_" + operatingSystem
+ + ".properties"));
+ PropertyResourceBundle resourceBundle = new PropertyResourceBundle(
+ is);
+ Enumeration e = resourceBundle.getKeys();
+ String key;
+ while (e.hasMoreElements()) {
+ key = (String) e.nextElement();
+ store.setDefault(key, resourceBundle.getString(key));
+ }*/
+ } catch (Exception e) {
+ // no default properties found
+ if (operatingSystem.equals(Platform.OS_WIN32)) {
+ // store.setDefault(PHP_RUN_PREF, "c:\\apache\\php\\php.exe");
+ // store.setDefault(EXTERNAL_PARSER_PREF, "c:\\apache\\php\\php
+ // -l -f {0}");
+ // store.setDefault(MYSQL_RUN_PREF,
+ // "c:\\apache\\mysql\\bin\\mysqld-nt.exe");
+ // store.setDefault(APACHE_RUN_PREF, "c:\\apache\\apache.exe");
+ // store.setDefault(XAMPP_START_PREF,
+ // "c:\\xampp\\xampp_start.exe");
+ // store.setDefault(XAMPP_STOP_PREF,
+ // "c:\\xampp\\xampp_stop.exe");
+ // store.setDefault(
+ // ETC_HOSTS_PATH_PREF,
+ // "c:\\windows\\system32\\drivers\\etc\\hosts");
+ } else {
+ // store.setDefault(PHP_RUN_PREF, "/apache/php/php");
+ // store.setDefault(EXTERNAL_PARSER_PREF, "/apache/php/php -l -f
+ // {0}");
+ // store.setDefault(MYSQL_RUN_PREF, "/apache/mysql/bin/mysqld");
+ // store.setDefault(APACHE_RUN_PREF, "/apache/apache");
+ // store.setDefault(XAMPP_START_PREF, "xamp/xampp_start");
+ // store.setDefault(XAMPP_STOP_PREF, "xampp/xampp_stop");
+ }
+ // store.setDefault(MYSQL_PREF, "--standalone");
+ // store.setDefault(APACHE_START_PREF, "-c \"DocumentRoot
+ // \"{0}\"\"");
+ // store.setDefault(APACHE_STOP_PREF, "-k shutdown");
+ // store.setDefault(APACHE_RESTART_PREF, "-k restart");
+ // store.setDefault(MYSQL_START_BACKGROUND, "true");
+ // store.setDefault(APACHE_START_BACKGROUND, "true");
+ // store.setDefault(APACHE_STOP_BACKGROUND, "true");
+ // store.setDefault(APACHE_RESTART_BACKGROUND, "true");
+ }
+ store.setDefault(PHP_USERDEF_XMLFILE, "");
+ PreferenceConverter.setDefault(store, PHP_TAG, PHPColorProvider.TAG);
+ PreferenceConverter.setDefault(store, PHP_KEYWORD,
+ PHPColorProvider.KEYWORD);
+ PreferenceConverter.setDefault(store, PHP_VARIABLE,
+ PHPColorProvider.VARIABLE);
+ PreferenceConverter.setDefault(store, PHP_VARIABLE_DOLLAR,
+ PHPColorProvider.VARIABLE);
+ /*PreferenceConverter.setDefault(store, PHP_FUNCTIONNAME,
+ PHPColorProvider.FUNCTION_NAME);*/
+
+ setDefault(store, PHP_FUNCTIONNAME, PHPColorProvider.FUNCTION_NAME,
+ ITextStylePreferences.STYLE_BOLD);
+
+ PreferenceConverter.setDefault(store, PHP_CONSTANT,
+ PHPColorProvider.CONSTANT);
+ PreferenceConverter.setDefault(store, PHP_TYPE, PHPColorProvider.TYPE);
+ PreferenceConverter.setDefault(store, PHP_DEFAULT,
+ PHPColorProvider.DEFAULT);
+ PreferenceConverter.setDefault(store, PHPDOC_KEYWORD,
+ PHPColorProvider.PHPDOC_KEYWORD);
+
+ PreferenceConverter.setDefault(store, PHPDOC_TAG,
+ PHPColorProvider.PHPDOC_TAG);
+ PreferenceConverter.setDefault(store, PHPDOC_LINK,
+ PHPColorProvider.PHPDOC_LINK);
+ PreferenceConverter.setDefault(store, PHPDOC_DEFAULT,
+ PHPColorProvider.PHPDOC_DEFAULT);
+
+ PreferenceConverter.setDefault(store, EDITOR_PHP_KEYWORD_RETURN_COLOR,
+ new RGB(127, 0, 85));
+ store.setDefault(EDITOR_PHP_KEYWORD_RETURN_BOLD, true);
+ store.setDefault(EDITOR_PHP_KEYWORD_RETURN_ITALIC, false);
+
+ PreferenceConverter.setDefault(store, EDITOR_PHP_OPERATOR_COLOR,
+ new RGB(0, 0, 0));
+ store.setDefault(EDITOR_PHP_OPERATOR_BOLD, false);
+ store.setDefault(EDITOR_PHP_OPERATOR_ITALIC, false);
+
+ PreferenceConverter.setDefault(store, EDITOR_PHP_BRACE_OPERATOR_COLOR,
+ new RGB(0, 0, 0));
+ store.setDefault(EDITOR_PHP_BRACE_OPERATOR_BOLD, false);
+ store.setDefault(EDITOR_PHP_BRACE_OPERATOR_ITALIC, false);
+
+
+ PreferenceConverter.setDefault(store, EDITOR_PHP_KEYWORD_RETURN_COLOR,
+ new RGB(127, 0, 85));
+ store.setDefault(EDITOR_PHP_KEYWORD_RETURN_BOLD, true);
+ store.setDefault(EDITOR_PHP_KEYWORD_RETURN_ITALIC, false);
+
+ PreferenceConverter.setDefault(store, EDITOR_PHP_OPERATOR_COLOR,
+ new RGB(0, 0, 0));
+ store.setDefault(EDITOR_PHP_OPERATOR_BOLD, false);
+ store.setDefault(EDITOR_PHP_OPERATOR_ITALIC, false);
+
+ PreferenceConverter.setDefault(store, EDITOR_PHP_BRACE_OPERATOR_COLOR,
+ new RGB(0, 0, 0));
+ store.setDefault(EDITOR_PHP_BRACE_OPERATOR_BOLD, false);
+ store.setDefault(EDITOR_PHP_BRACE_OPERATOR_ITALIC, false);
+
+ // this will initialize the static fields in the syntaxrdr class
+ new PHPSyntaxRdr();
+ JavaCore.initializeDefaultPluginPreferences();
+ PreferenceConstants.initializeDefaultValues(store);
+ }
+
+ private static void setDefault(IPreferenceStore store, String constant,
+ String color, String style) {
+ store.setDefault(constant + ITextStylePreferences.SUFFIX_FOREGROUND,
+ color);
+ store.setDefault(constant + ITextStylePreferences.SUFFIX_STYLE, style);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/XMLSyntaxPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/XMLSyntaxPreferencePage.java
new file mode 100644
index 0000000..e855df2
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/XMLSyntaxPreferencePage.java
@@ -0,0 +1,587 @@
+/*
+ * Copyright (c) 2002-2004 Roberto Gonzalez Rocha and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Roberto Gonzalez Rocha - Initial version
+ * Igor Malinin - refactoring, minor changes
+ *
+ * $Id: XMLSyntaxPreferencePage.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.preferences;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import net.sourceforge.phpeclipse.ui.ColorEditor;
+import net.sourceforge.phpeclipse.ui.preferences.ITextStylePreferences;
+import net.sourceforge.phpeclipse.ui.preferences.OverlayPreferenceStore;
+import net.sourceforge.phpeclipse.ui.preferences.PreferenceDescriptor;
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLConfiguration;
+import net.sourceforge.phpeclipse.xml.ui.text.IXMLSyntaxConstants;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+/**
+ * The XMLSyntaxPreferencePage is a preference page that handles setting the
+ * colors used by the XML editors.
+ */
+public class XMLSyntaxPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage {
+
+ public final PreferenceDescriptor[] fKeys = new PreferenceDescriptor[] {
+ new PreferenceDescriptor(
+ PreferenceDescriptor.BOOLEAN,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_DEFAULT
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_DEFAULT
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_TAG
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_TAG
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_ATT_NAME
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_ATT_NAME
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_ATT_VALUE
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_ATT_VALUE
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_ENTITY
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_ENTITY
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_CDATA
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_CDATA
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_PI
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_PI
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_COMMENT
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_COMMENT
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_DECL
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_DECL
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_SMARTY
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.XML_SMARTY
+ + ITextStylePreferences.SUFFIX_STYLE),
+
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.DTD_CONDITIONAL
+ + ITextStylePreferences.SUFFIX_FOREGROUND),
+ new PreferenceDescriptor(PreferenceDescriptor.STRING,
+ IXMLSyntaxConstants.DTD_CONDITIONAL
+ + ITextStylePreferences.SUFFIX_STYLE), };
+
+ OverlayPreferenceStore overlay;
+
+ final String[][] fSyntaxColorListModel = new String[][] {
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.others"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_DEFAULT },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Tag"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_TAG },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.AttName"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_ATT_NAME },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.AttValue"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_ATT_VALUE },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Entity"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_ENTITY },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.CDATA"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_CDATA },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.PI"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_PI },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Comment"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_COMMENT },
+ {
+ XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.Declaration"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_DECL },
+ {
+ XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.Conditional"), //$NON-NLS-1$
+ IXMLSyntaxConstants.XML_SMARTY },
+ { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.SmartyTag"), //$NON-NLS-1$
+ IXMLSyntaxConstants.DTD_CONDITIONAL }, };
+
+ private XMLTextTools xmlTextTools;
+
+ private Color bgColor;
+
+ Button bgDefault;
+
+ Button bgCustom;
+
+ ColorEditor bgColorEditor;
+
+ List colors;
+
+ ColorEditor fgColorEditor;
+
+ Button fgBold;
+
+ SourceViewer preview;
+
+ /**
+ * Constructor for XMLSyntaxPreferencePage.
+ */
+ public XMLSyntaxPreferencePage() {
+ setDescription(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.description")); //$NON-NLS-1$
+
+ setPreferenceStore(XMLPlugin.getDefault().getPreferenceStore());
+
+ overlay = new OverlayPreferenceStore(getPreferenceStore(), fKeys);
+ }
+
+ protected Control createContents(Composite parent) {
+ overlay.load();
+ overlay.start();
+
+ Composite colorComposite = new Composite(parent, SWT.NULL);
+ colorComposite.setLayout(new GridLayout());
+
+ Group backgroundComposite = new Group(colorComposite,
+ SWT.SHADOW_ETCHED_IN);
+
+ backgroundComposite.setLayout(new RowLayout());
+ backgroundComposite.setText(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.backgroundColor")); //$NON-NLS-1$
+
+ SelectionListener backgroundSelectionListener = new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean custom = bgCustom.getSelection();
+ bgColorEditor.getButton().setEnabled(custom);
+ overlay
+ .setValue(
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT,
+ !custom);
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ };
+
+ bgDefault = new Button(backgroundComposite, SWT.RADIO | SWT.LEFT);
+ bgDefault.setText(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.systemDefault")); //$NON-NLS-1$
+ bgDefault.addSelectionListener(backgroundSelectionListener);
+
+ bgCustom = new Button(backgroundComposite, SWT.RADIO | SWT.LEFT);
+ bgCustom.setText(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.custom")); //$NON-NLS-1$
+ bgCustom.addSelectionListener(backgroundSelectionListener);
+
+ bgColorEditor = new ColorEditor(backgroundComposite);
+
+ Label label = new Label(colorComposite, SWT.LEFT);
+ label.setText(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.foreground")); //$NON-NLS-1$
+ label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Composite editorComposite = new Composite(colorComposite, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ editorComposite.setLayoutData(gd);
+
+ colors = new List(editorComposite, SWT.SINGLE | SWT.V_SCROLL
+ | SWT.BORDER);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = convertHeightInCharsToPixels(5);
+ colors.setLayoutData(gd);
+
+ Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ label = new Label(stylesComposite, SWT.LEFT);
+ label.setText(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.color")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gd);
+
+ fgColorEditor = new ColorEditor(stylesComposite);
+
+ Button fgColorButton = fgColorEditor.getButton();
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ fgColorButton.setLayoutData(gd);
+
+ label = new Label(stylesComposite, SWT.LEFT);
+ label.setText(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.bold")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gd);
+
+ fgBold = new Button(stylesComposite, SWT.CHECK);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalAlignment = GridData.BEGINNING;
+ fgBold.setLayoutData(gd);
+
+ label = new Label(colorComposite, SWT.LEFT);
+ label.setText(XMLPlugin
+ .getResourceString("XmlSyntaxPreferencePage.preview")); //$NON-NLS-1$
+ label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Control previewer = createPreviewer(colorComposite);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = convertWidthInCharsToPixels(20);
+ gd.heightHint = convertHeightInCharsToPixels(5);
+ previewer.setLayoutData(gd);
+
+ colors.addSelectionListener(new SelectionListener() {
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ handleSyntaxColorListSelection();
+ }
+ });
+
+ bgColorEditor.getButton().addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ PreferenceConverter.setValue(overlay,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND,
+ bgColorEditor.getColorValue());
+ }
+ });
+
+ fgColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ int i = colors.getSelectionIndex();
+
+ String key = fSyntaxColorListModel[i][1];
+
+ PreferenceConverter.setValue(overlay, key
+ + ITextStylePreferences.SUFFIX_FOREGROUND,
+ fgColorEditor.getColorValue());
+ }
+ });
+
+ fgBold.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ int i = colors.getSelectionIndex();
+
+ String key = fSyntaxColorListModel[i][1];
+
+ String value = (fgBold.getSelection()) ? ITextStylePreferences.STYLE_BOLD
+ : ITextStylePreferences.STYLE_NORMAL;
+
+ overlay.setValue(key + ITextStylePreferences.SUFFIX_STYLE,
+ value);
+ }
+ });
+
+ initialize();
+
+ return colorComposite;
+ }
+
+ private Control createPreviewer(Composite parent) {
+ xmlTextTools = new XMLTextTools(overlay); // REVISIT: DTD
+
+ preview = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL
+ | SWT.BORDER);
+
+ preview.configure(new XMLConfiguration(xmlTextTools));
+ preview.getTextWidget().setFont(
+ JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT));
+ preview.setEditable(false);
+
+ initializeViewerColors(preview);
+
+ String content = loadPreviewContentFromFile("preview.xml"); //$NON-NLS-1$
+ IDocument document = new Document(content);
+
+ // REVISIT: DTD
+ IDocumentPartitioner partitioner = xmlTextTools.createXMLPartitioner();
+
+ partitioner.connect(document);
+ document.setDocumentPartitioner(partitioner);
+
+ preview.setDocument(document);
+
+ overlay.addPropertyChangeListener(new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ String p = event.getProperty();
+ if (p.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)
+ || p
+ .equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
+ initializeViewerColors(preview);
+ }
+
+ preview.invalidateTextPresentation();
+ }
+ });
+
+ return preview.getControl();
+ }
+
+ /**
+ * Initializes the given viewer's colors.
+ *
+ * @param viewer
+ * the viewer to be initialized
+ */
+ void initializeViewerColors(ISourceViewer viewer) {
+ if (overlay != null) {
+ StyledText styledText = viewer.getTextWidget();
+
+ // ---------- background color ----------------------
+ Color color = null;
+ if (!overlay
+ .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
+ color = createColor(overlay,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND,
+ styledText.getDisplay());
+ }
+
+ styledText.setBackground(color);
+
+ if (bgColor != null) {
+ bgColor.dispose();
+ }
+
+ bgColor = color;
+ }
+ }
+
+ /**
+ * Creates a color from the information stored in the given preference
+ * store. Returns null
if there is no such information
+ * available.
+ */
+ private Color createColor(IPreferenceStore store, String key,
+ Display display) {
+ RGB rgb = null;
+
+ if (store.contains(key)) {
+ if (store.isDefault(key)) {
+ rgb = PreferenceConverter.getDefaultColor(store, key);
+ } else {
+ rgb = PreferenceConverter.getColor(store, key);
+ }
+
+ if (rgb != null) {
+ return new Color(display, rgb);
+ }
+ }
+
+ return null;
+ }
+
+ void handleSyntaxColorListSelection() {
+ int i = colors.getSelectionIndex();
+
+ String key = fSyntaxColorListModel[i][1];
+
+ RGB rgb = PreferenceConverter.getColor(overlay, key
+ + ITextStylePreferences.SUFFIX_FOREGROUND);
+
+ fgColorEditor.setColorValue(rgb);
+
+ // REVISIT
+ fgBold.setSelection(overlay.getString(
+ key + ITextStylePreferences.SUFFIX_STYLE).indexOf(
+ ITextStylePreferences.STYLE_BOLD) >= 0);
+ }
+
+ private String loadPreviewContentFromFile(String filename) {
+ StringBuffer string = new StringBuffer(512);
+
+ try {
+ char[] buf = new char[512];
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(XMLSyntaxPreferencePage.class
+ .getResourceAsStream(filename)));
+
+ try {
+ while (true) {
+ int n = reader.read(buf);
+ if (n < 0) {
+ break;
+ }
+
+ string.append(buf, 0, n);
+ }
+ } finally {
+ reader.close();
+ }
+ } catch (IOException e) {
+ }
+
+ return string.toString();
+ }
+
+ /**
+ *
+ */
+ private void initialize() {
+ initializeFields();
+
+ for (int i = 0; i < fSyntaxColorListModel.length; i++) {
+ colors.add(fSyntaxColorListModel[i][0]);
+ }
+
+ colors.getDisplay().asyncExec(new Runnable() {
+
+ public void run() {
+ colors.select(0);
+ handleSyntaxColorListSelection();
+ }
+ });
+ }
+
+ private void initializeFields() {
+ RGB rgb = PreferenceConverter.getColor(overlay,
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND);
+ bgColorEditor.setColorValue(rgb);
+
+ boolean def = overlay
+ .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT);
+ bgDefault.setSelection(def);
+ bgCustom.setSelection(!def);
+ bgColorEditor.getButton().setEnabled(!def);
+ }
+
+ /*
+ * @see IWorkbenchPreferencePage#init(IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * @see PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ overlay.loadDefaults();
+ // initializeFields();
+ handleSyntaxColorListSelection();
+
+ super.performDefaults();
+
+ preview.invalidateTextPresentation();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ overlay.propagate();
+ XMLPlugin.getDefault().savePluginPreferences();
+
+ return true;
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.IDialogPage#dispose()
+ */
+ public void dispose() {
+ if (xmlTextTools != null) {
+ xmlTextTools.dispose();
+ xmlTextTools = null;
+ }
+
+ if (overlay != null) {
+ overlay.stop();
+ overlay = null;
+ }
+
+ super.dispose();
+ }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/preview.xml b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/preview.xml
new file mode 100644
index 0000000..2fc0edc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/preferences/preview.xml
@@ -0,0 +1,18 @@
+
+
+
+
+]>
+
+
+
+
+
+ <text>
+ ]]>
+
+
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/AbstractDocumentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/AbstractDocumentProvider.java
new file mode 100644
index 0000000..10d4fee
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/AbstractDocumentProvider.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: AbstractDocumentProvider.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import net.sourceforge.phpeclipse.ui.editor.I18NDocumentProvider;
+
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public abstract class AbstractDocumentProvider extends I18NDocumentProvider {
+ protected IWhitespaceDetector detector = new WhitespaceDetector();
+
+ /*
+ * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#getDefaultEncoding()
+ */
+ public String getDefaultEncoding() {
+ return "UTF-8";
+ }
+
+ public String getDeclaredEncoding(InputStream in) throws IOException {
+ if (!in.markSupported()) {
+ in = new BufferedInputStream(in, 512);
+ }
+
+ in.mark(512);
+ String encoding = super.getDeclaredEncoding(in);
+ if (encoding != null) {
+ return encoding;
+ }
+
+ in.reset();
+
+ // check Prolog-Start ':
+ state = STATE_DEFAULT;
+ return getToken(XML_TAG);
+
+ case '"':
+ case '\'':
+ while (true) {
+ int ch = read();
+
+ if (ch == quot) {
+ state = STATE_TAG;
+ return getToken(XML_ATTRIBUTE);
+ }
+
+ switch (ch) {
+ case '<':
+ unread();
+
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(XML_ATTRIBUTE);
+ }
+ }
+ default:
+ unread();
+ }
+
+ while (true) {
+ switch (read()) {
+ case '<':
+ unread();
+
+ case ICharacterScanner.EOF:
+ case '>':
+ state = STATE_DEFAULT;
+ return getToken(XML_TAG);
+
+ case '"':
+ case '\'':
+ unread();
+
+ state = STATE_TAG;
+ return getToken(XML_TAG);
+ }
+ }
+ }
+
+ private IToken nextDeclToken() {
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
+
+ case '<':
+ if (parsedtd || isInternal()) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(isInternal() ? DTD_INTERNAL : null);
+
+ case '!':
+ case '?':
+ unread();
+ break;
+
+ default:
+ continue loop;
+ }
+ }
+
+ unread();
+
+ case '>':
+ state &= STATE_INTERNAL;
+ return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
+
+ case '[': //
+ if (!isInternal()) {
+ state = STATE_INTERNAL;
+ return getToken(XML_DECL);
+ }
+ }
+ }
+ }
+
+ private IToken nextCommentToken() {
+ state &= STATE_INTERNAL;
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '-': // - -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '-': // -- -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ case '>':
+ break loop;
+ }
+
+ unread();
+ continue loop;
+ }
+ }
+ }
+
+ return getToken(isInternal() ? DTD_INTERNAL_COMMENT : XML_COMMENT);
+ }
+
+ private IToken nextCDATAToken() {
+ state = STATE_DEFAULT;
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case ']': // ] ]]>
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case ']': // ]] ]]>
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ case '>': // ]]>
+ break loop;
+ }
+
+ unread();
+ unread();
+ continue loop;
+ }
+ }
+ }
+
+ return getToken(XML_CDATA);
+ }
+
+ private IToken nextConditionalToken() {
+ state = STATE_DEFAULT;
+
+ int level = 1;
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '<': // - -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '!': // -- -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '[':
+ ++level;
+ continue loop;
+ }
+
+ unread();
+ continue loop;
+ }
+
+ unread();
+ continue loop;
+
+ case ']': // - -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case ']': // -- -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ case '>':
+ if (--level == 0) {
+ break loop;
+ }
+
+ continue loop;
+ }
+
+ unread();
+ unread();
+ continue loop;
+ }
+ }
+ }
+
+ return getToken(DTD_CONDITIONAL);
+ }
+
+ private IToken getToken(String type) {
+ length = position - offset;
+
+ if (length == 0) {
+ return Token.EOF;
+ }
+
+ if (type == null) {
+ return Token.UNDEFINED;
+ }
+
+ IToken token = (IToken) tokens.get(type);
+ if (token == null) {
+ token = new Token(type);
+ tokens.put(type, token);
+ }
+
+ return token;
+ }
+
+ private boolean isInternal() {
+ return (state & STATE_INTERNAL) != 0;
+ }
+
+ private int read() {
+ if (position >= end) {
+ return ICharacterScanner.EOF;
+ }
+
+ try {
+ return document.getChar(position++);
+ } catch (BadLocationException e) {
+ --position;
+ return ICharacterScanner.EOF;
+ }
+ }
+
+ private void unread() {
+ --position;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
+ */
+ public int getTokenOffset() {
+ Assert.isTrue(offset >= 0, Integer.toString(offset));
+ return offset;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
+ */
+ public int getTokenLength() {
+ return length;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int,
+ * int)
+ */
+ public void setRange(IDocument document, int offset, int length) {
+ this.document = document;
+ this.end = offset + length;
+
+ this.offset = offset;
+ this.position = offset;
+ this.length = 0;
+
+ this.state = STATE_DEFAULT;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
+ */
+ // public void setPartialRange(IDocument document, int offset, int length,
+ // String contentType, int partitionOffset) {
+ // state = STATE_DEFAULT;
+ // if (partitionOffset > -1) {
+ // int delta = offset - partitionOffset;
+ // if (delta > 0) {
+ // setRange(document, partitionOffset, length + delta);
+ // return;
+ // }
+ // }
+ // setRange(document, partitionOffset, length);
+ // }
+ /*
+ * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
+ */
+ public void setPartialRange(IDocument document, int offset, int length,
+ String contentType, int partitionOffset) {
+ // boolean flag = false;
+ this.document = document;
+ this.end = offset + length;
+
+ // NB! Undocumented value: -1
+ if (partitionOffset >= 0) {
+ offset = partitionOffset;
+ // flag = true;
+ }
+
+ this.offset = offset;
+ this.position = offset;
+ this.length = 0;
+
+ // if (flag) {
+ // state = STATE_DEFAULT;
+ // return;
+ // }
+ if (contentType == XML_ATTRIBUTE) {
+ state = STATE_TAG;
+ return;
+ }
+
+ if (contentType == XML_TAG) {
+ state = isContinuationPartition() ? STATE_TAG : STATE_DEFAULT;
+ return;
+ }
+
+ if (contentType == XML_DECL) {
+ state = isContinuationPartition() ? STATE_DECL : STATE_DEFAULT;
+ return;
+ }
+
+ if (contentType == DTD_INTERNAL || contentType == DTD_INTERNAL_DECL
+ || contentType == DTD_INTERNAL_COMMENT) {
+ state = STATE_INTERNAL;
+ return;
+ }
+
+ state = STATE_DEFAULT;
+ }
+
+ private boolean isContinuationPartition() {
+ try {
+ String type = document.getContentType(offset - 1);
+
+ if (type != IDocument.DEFAULT_CONTENT_TYPE) {
+ return true;
+ }
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/SimpleDoubleClickStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/SimpleDoubleClickStrategy.java
new file mode 100644
index 0000000..3eb545a
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/SimpleDoubleClickStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: SimpleDoubleClickStrategy.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import net.sourceforge.phpeclipse.ui.text.TextDoubleClickStrategy;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITypedRegion;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class SimpleDoubleClickStrategy extends TextDoubleClickStrategy {
+ /*
+ * @see org.eclipse.jface.text.ITextDoubleClickStrategy#doubleClicked(ITextViewer)
+ */
+ public void doubleClicked(ITextViewer viewer) {
+ int offset = viewer.getSelectedRange().x;
+ if (offset < 0) {
+ return;
+ }
+
+ try {
+ IDocument document = viewer.getDocument();
+
+ ITypedRegion region = document.getPartition(offset);
+
+ int start = region.getOffset();
+ int length = region.getLength();
+
+ if (offset == start) {
+ viewer.setSelectedRange(start, length);
+ return;
+ }
+
+ int end = start + length - 1;
+
+ if (offset == end && document.getChar(end) == '>') {
+ viewer.setSelectedRange(start, length);
+ return;
+ }
+
+ super.doubleClicked(viewer);
+ } catch (BadLocationException e) {
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/SingleTokenScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/SingleTokenScanner.java
new file mode 100644
index 0000000..b78c796
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/SingleTokenScanner.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: SingleTokenScanner.java,v 1.1 2004-09-02 18:28:03 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.Map;
+
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ * @author Igor Malinin
+ */
+public class SingleTokenScanner extends RuleBasedScanner {
+
+ /**
+ * Creates a single token scanner.
+ */
+ public SingleTokenScanner(Map tokens, String property) {
+ setDefaultReturnToken((Token) tokens.get(property));
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/TagDoubleClickStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/TagDoubleClickStrategy.java
new file mode 100644
index 0000000..3e70d8f
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/TagDoubleClickStrategy.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: TagDoubleClickStrategy.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import net.sourceforge.phpeclipse.ui.text.TextDoubleClickStrategy;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITypedRegion;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class TagDoubleClickStrategy extends TextDoubleClickStrategy {
+ /*
+ * @see org.eclipse.jface.text.ITextDoubleClickStrategy#doubleClicked(ITextViewer)
+ */
+ public void doubleClicked(ITextViewer viewer) {
+ int offset = viewer.getSelectedRange().x;
+ if (offset < 0) {
+ return;
+ }
+
+ try {
+ IDocument document = viewer.getDocument();
+
+ ITypedRegion region = document.getPartition(offset);
+
+ int start = region.getOffset();
+
+ if (offset == start && document.getChar(offset) == '<') {
+ region = document.getPartition(offset);
+ offset = region.getOffset() + region.getLength();
+
+ if (document.getChar(offset - 1) != '>') {
+ while (true) {
+ if (offset >= document.getLength()) {
+ break;
+ }
+
+ region = document.getPartition(offset);
+ offset = region.getOffset() + region.getLength();
+
+ if (XMLPartitionScanner.XML_ATTRIBUTE.equals(region
+ .getType())) {
+ continue;
+ }
+
+ if (XMLPartitionScanner.XML_TAG
+ .equals(region.getType())) {
+ if (document.getChar(region.getOffset()) == '<') {
+ break;
+ }
+
+ if (document.getChar(offset - 1) == '>') {
+ break;
+ }
+
+ continue;
+ }
+
+ offset = region.getOffset();
+ break;
+ }
+ }
+
+ viewer.setSelectedRange(start, offset - start);
+ return;
+ }
+
+ int end = start + region.getLength();
+
+ if (offset == end - 1 && document.getChar(offset) == '>') {
+ region = document.getPartition(offset);
+ offset = region.getOffset();
+
+ if (document.getChar(offset) != '<') {
+ while (true) {
+ if (offset <= 0) {
+ break;
+ }
+
+ region = document.getPartition(offset - 1);
+ offset = region.getOffset();
+
+ if (XMLPartitionScanner.XML_ATTRIBUTE.equals(region
+ .getType())) {
+ continue;
+ }
+
+ if (XMLPartitionScanner.XML_TAG
+ .equals(region.getType())) {
+ if (document.getChar(offset) == '<') {
+ break;
+ }
+
+ continue;
+ }
+
+ offset += region.getLength();
+ break;
+ }
+ }
+
+ viewer.setSelectedRange(offset, end - offset);
+ return;
+ }
+
+ super.doubleClicked(viewer);
+ } catch (BadLocationException e) {
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/TextScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/TextScanner.java
new file mode 100644
index 0000000..3ef9542
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/TextScanner.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: TextScanner.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.xml.ui.text.IXMLSyntaxConstants;
+
+import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ * @author Igor Malinin
+ */
+public class TextScanner extends BufferedRuleBasedScanner {
+
+ /**
+ * Creates a color scanner for XML text or attribute value.
+ */
+ public TextScanner(Map tokens, char startEntity, String defaultProperty) {
+ setDefaultReturnToken((Token) tokens.get(defaultProperty));
+
+ IToken entity = (Token) tokens.get(IXMLSyntaxConstants.XML_ENTITY);
+
+ IRule[] rules = { new EntityRule(startEntity, entity) };
+
+ setRules(rules);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/WhitespaceDetector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/WhitespaceDetector.java
new file mode 100644
index 0000000..3efcc3e
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/WhitespaceDetector.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: WhitespaceDetector.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+
+/**
+ * XML white-space detector.
+ *
+ * @author Igor Malinin
+ */
+public class WhitespaceDetector implements IWhitespaceDetector {
+
+ /**
+ * @see IWhitespaceDetector#isWhitespace(char)
+ */
+ public boolean isWhitespace(char ch) {
+ switch (ch) {
+ case 0x09:
+ case 0x0A:
+ case 0x0D:
+ case 0x20:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotation.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotation.java
new file mode 100644
index 0000000..fb371b8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotation.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLAnnotation.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import org.eclipse.jface.text.source.Annotation;
+
+/**
+ * @author Igor Malinin
+ */
+public class XMLAnnotation extends Annotation {
+ public static final String TYPE_ERROR = "org.eclipse.ui.workbench.texteditor.warning"; //$NON-NLS-1$
+
+ public static final String TYPE_WARNING = "org.eclipse.ui.workbench.texteditor.error"; //$NON-NLS-1$
+
+ public static final String TYPE_INFO = "org.eclipse.ui.workbench.texteditor.info"; //$NON-NLS-1$
+
+ public XMLAnnotation(String type, boolean persistent, String text) {
+ super(type, persistent, text);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotationHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotationHover.java
new file mode 100644
index 0000000..3e38663
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotationHover.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2003-2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLAnnotationHover.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+
+/**
+ * Implements simple annotation hover to show the associated messages.
+ */
+public class XMLAnnotationHover implements IAnnotationHover {
+ /*
+ * @see org.eclipse.jface.text.source.IAnnotationHover#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer,
+ * int)
+ */
+ public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
+ List annotations = getAnnotationsForLine(sourceViewer, lineNumber);
+ if (annotations != null) {
+ List messages = new ArrayList();
+
+ Iterator e = annotations.iterator();
+ while (e.hasNext()) {
+ Annotation annotation = (Annotation) e.next();
+
+ String message = annotation.getText();
+ if (message != null) {
+ message = message.trim();
+ if (message.length() > 0) {
+ messages.add(message);
+ }
+ }
+ }
+
+ if (messages.size() == 1) {
+ return (String) messages.get(0);
+ }
+
+ if (messages.size() > 1) {
+ return formatMessages(messages);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Formats multiple annotation messages for display.
+ */
+ private String formatMessages(List messages) {
+ StringBuffer buffer = new StringBuffer();
+
+ Iterator e = messages.iterator();
+ while (e.hasNext()) {
+ buffer.append("- "); //$NON-NLS-1$
+ buffer.append(e.next());
+ buffer.append('\n');
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns annotations for the ruler's line of activity.
+ */
+ private List getAnnotationsForLine(ISourceViewer viewer, int line) {
+ IDocument document = viewer.getDocument();
+
+ IAnnotationModel model = viewer.getAnnotationModel();
+ if (model == null) {
+ return null;
+ }
+
+ List retVal = new ArrayList();
+
+ Iterator e = new XMLAnnotationIterator(model, true);
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+
+ Position position = model.getPosition(a);
+ if (position != null) {
+ try {
+ int annotationLine = document.getLineOfOffset(position
+ .getOffset());
+ if (annotationLine == line) {
+ retVal.add(a);
+ }
+ } catch (BadLocationException e1) {
+ // ignore
+ }
+ }
+ }
+
+ return retVal;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotationIterator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotationIterator.java
new file mode 100644
index 0000000..b86dea6
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLAnnotationIterator.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLAnnotationIterator.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.Iterator;
+
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+
+/**
+ * @author Igor Malinin
+ */
+public class XMLAnnotationIterator implements Iterator {
+ private boolean skipIrrelevants;
+
+ private Iterator iterator;
+
+ private Annotation next;
+
+ public XMLAnnotationIterator(IAnnotationModel model, boolean skipIrrelevants) {
+ this.skipIrrelevants = skipIrrelevants;
+
+ iterator = model.getAnnotationIterator();
+ skip();
+ }
+
+ private void skip() {
+ while (iterator.hasNext()) {
+ Annotation next = (Annotation) iterator.next();
+ if (next instanceof XMLAnnotation) {
+ if (skipIrrelevants) {
+ if (!next.isMarkedDeleted()) {
+ this.next = next;
+ return;
+ }
+ } else {
+ this.next = next;
+ return;
+ }
+ }
+ }
+
+ this.next = null;
+ }
+
+ /*
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return (next != null);
+ }
+
+ /*
+ * @see java.util.Iterator#next()
+ */
+ public Object next() {
+ try {
+ return next;
+ } finally {
+ skip();
+ }
+ }
+
+ /*
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLCDATAScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLCDATAScanner.java
new file mode 100644
index 0000000..848f207
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLCDATAScanner.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLCDATAScanner.java,v 1.4 2007-06-03 11:39:00 toshihiro Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.xml.ui.text.IXMLSyntaxConstants;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.ITokenScanner;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ * @author Igor Malinin
+ */
+public class XMLCDATAScanner implements ITokenScanner {
+
+ private Map tokens;
+
+ private IDocument document;
+
+ private int begin;
+
+ private int end;
+
+ private int offset;
+
+ private int length;
+
+ private int position;
+
+ public XMLCDATAScanner(Map tokens) {
+ this.tokens = tokens;
+ }
+
+ /*
+ * @see ITokenScanner#setRange(IDocument, int, int)
+ */
+ public void setRange(IDocument document, int offset, int length) {
+ this.document = document;
+
+ this.begin = offset;
+ this.end = offset + length;
+
+ this.offset = offset;
+ this.position = offset;
+ this.length = 0;
+ }
+
+ /*
+ * @see ITokenScanner#nextToken()
+ */
+ public IToken nextToken() {
+ offset += length;
+
+ if (position == begin) {
+
+ try {
+ if (document.get(position, 9).equals("")) {
+ if (position == p) {
+ position = end;
+ return getToken(IXMLSyntaxConstants.XML_CDATA);
+ }
+ position = p;
+ } else {
+ position = end;
+ }
+ } catch (BadLocationException e) {
+ }
+
+ return getToken(IXMLSyntaxConstants.XML_DEFAULT);
+ }
+
+ private IToken getToken(String type) {
+ length = position - offset;
+
+ if (length == 0) {
+ return Token.EOF;
+ }
+
+ if (type == null) {
+ return Token.UNDEFINED;
+ }
+
+ IToken token = (IToken) tokens.get(type);
+ if (token == null) {
+ return Token.UNDEFINED;
+ }
+
+ return token;
+ }
+
+ /*
+ * @see ITokenScanner#getTokenOffset()
+ */
+ public int getTokenOffset() {
+ return offset;
+ }
+
+ /*
+ * @see ITokenScanner#getTokenLength()
+ */
+ public int getTokenLength() {
+ return length;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLConfiguration.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLConfiguration.java
new file mode 100644
index 0000000..14a17c9
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLConfiguration.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLConfiguration.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import net.sourceforge.phpeclipse.ui.templates.template.BasicCompletionProcessor;
+import net.sourceforge.phpeclipse.ui.text.TextDoubleClickStrategy;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * XML editor configuration.
+ *
+ * @author Igor Malinin
+ */
+public class XMLConfiguration extends TextSourceViewerConfiguration {
+ protected XMLTextTools xmlTextTools;
+
+ private ITextDoubleClickStrategy dcsDefault;
+
+ private ITextDoubleClickStrategy dcsSimple;
+
+ private ITextDoubleClickStrategy dcsTag;
+
+ private ITextDoubleClickStrategy dcsAttValue;
+
+ /** The associated editor. */
+ private ITextEditor editor;
+
+ public XMLConfiguration(XMLTextTools tools) {
+ this(tools, null);
+ }
+
+ public XMLConfiguration(XMLTextTools tools, ITextEditor editor) {
+ xmlTextTools = tools;
+ this.editor = editor;
+ dcsDefault = new TextDoubleClickStrategy();
+ dcsSimple = new SimpleDoubleClickStrategy();
+ dcsTag = new TagDoubleClickStrategy();
+ dcsAttValue = new AttValueDoubleClickStrategy();
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getAnnotationHover(ISourceViewer)
+ */
+ public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+ return new XMLAnnotationHover();
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getTextHover(ISourceViewer, String)
+ */
+ public ITextHover getTextHover(ISourceViewer sourceViewer,
+ String contentType) {
+ if (editor != null) {
+ IDocumentProvider provider = editor.getDocumentProvider();
+ IEditorInput input = editor.getEditorInput();
+ IAnnotationModel model = provider.getAnnotationModel(input);
+ return new XMLTextHover(model);
+ }
+
+ return super.getTextHover(sourceViewer, contentType);
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer,
+ * String)
+ */
+ public ITextDoubleClickStrategy getDoubleClickStrategy(
+ ISourceViewer sourceViewer, String contentType) {
+ if (XMLPartitionScanner.XML_COMMENT.equals(contentType)) {
+ return dcsSimple;
+ }
+
+ if (XMLPartitionScanner.XML_PI.equals(contentType)) {
+ return dcsSimple;
+ }
+
+ if (XMLPartitionScanner.XML_TAG.equals(contentType)) {
+ return dcsTag;
+ }
+
+ if (XMLPartitionScanner.XML_ATTRIBUTE.equals(contentType)) {
+ return dcsAttValue;
+ }
+
+ if (XMLPartitionScanner.XML_CDATA.equals(contentType)) {
+ return dcsSimple;
+ }
+
+ if (contentType.startsWith(XMLPartitionScanner.DTD_INTERNAL)) {
+ return dcsSimple;
+ }
+
+ return dcsDefault;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredContentTypes(ISourceViewer)
+ */
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ return new String[] { IDocument.DEFAULT_CONTENT_TYPE,
+ XMLPartitionScanner.XML_PI, XMLPartitionScanner.XML_COMMENT,
+ XMLPartitionScanner.XML_DECL, XMLPartitionScanner.XML_TAG,
+ XMLPartitionScanner.XML_ATTRIBUTE,
+ XMLPartitionScanner.XML_CDATA,
+ XMLPartitionScanner.DTD_INTERNAL,
+ XMLPartitionScanner.DTD_INTERNAL_PI,
+ XMLPartitionScanner.DTD_INTERNAL_COMMENT,
+ XMLPartitionScanner.DTD_INTERNAL_DECL, };
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getPresentationReconciler(ISourceViewer)
+ */
+ public IPresentationReconciler getPresentationReconciler(
+ ISourceViewer sourceViewer) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+
+ DefaultDamagerRepairer dr;
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getXMLTextScanner());
+ reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getDTDTextScanner());
+ reconciler.setDamager(dr, XMLPartitionScanner.DTD_INTERNAL);
+ reconciler.setRepairer(dr, XMLPartitionScanner.DTD_INTERNAL);
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getXMLPIScanner());
+
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_PI);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_PI);
+ reconciler.setDamager(dr, XMLPartitionScanner.DTD_INTERNAL_PI);
+ reconciler.setRepairer(dr, XMLPartitionScanner.DTD_INTERNAL_PI);
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getXMLCommentScanner());
+
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_COMMENT);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_COMMENT);
+ reconciler.setDamager(dr, XMLPartitionScanner.DTD_INTERNAL_COMMENT);
+ reconciler.setRepairer(dr, XMLPartitionScanner.DTD_INTERNAL_COMMENT);
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getXMLDeclScanner());
+
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_DECL);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_DECL);
+ reconciler.setDamager(dr, XMLPartitionScanner.DTD_INTERNAL_DECL);
+ reconciler.setRepairer(dr, XMLPartitionScanner.DTD_INTERNAL_DECL);
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getXMLTagScanner());
+
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_TAG);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_TAG);
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getXMLAttributeScanner());
+
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_ATTRIBUTE);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_ATTRIBUTE);
+
+ dr = new DefaultDamagerRepairer(xmlTextTools.getXMLCDATAScanner());
+
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_CDATA);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_CDATA);
+
+ return reconciler;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getReconciler(ISourceViewer)
+ */
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ if ((editor != null) && editor.isEditable()) {
+ MonoReconciler reconciler = new MonoReconciler(
+ new XMLReconcilingStrategy(editor), false);
+ reconciler.setProgressMonitor(new NullProgressMonitor());
+ reconciler.setDelay(500);
+ return reconciler;
+ }
+
+ return null;
+ }
+
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+ ContentAssistant assistant = new ContentAssistant();
+ assistant
+ .setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+ IContentAssistProcessor processor = new BasicCompletionProcessor();
+ assistant.setContentAssistProcessor(processor,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.XML_TAG);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.XML_PI);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.XML_COMMENT);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.XML_DECL);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.XML_TAG);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.XML_ATTRIBUTE);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.XML_CDATA);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.DTD_INTERNAL);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.DTD_INTERNAL_PI);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.DTD_INTERNAL_COMMENT);
+ assistant.setContentAssistProcessor(processor,
+ XMLPartitionScanner.DTD_INTERNAL_DECL);
+ assistant
+ .setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
+ assistant
+ .setInformationControlCreator(getInformationControlCreator(sourceViewer));
+
+ return assistant;
+ }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLPartitionScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLPartitionScanner.java
new file mode 100644
index 0000000..eca1657
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLPartitionScanner.java
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLPartitionScanner.java,v 1.5 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class XMLPartitionScanner implements IPartitionTokenScanner {
+ public static final String XML_PI = "__xml_processing_instruction";
+
+ public static final String XML_COMMENT = "__xml_comment";
+
+ public static final String XML_DECL = "__xml_declaration";
+
+ public static final String XML_TAG = "__xml_tag";
+
+ public static final String XML_ATTRIBUTE = "__xml_attribute";
+
+ public static final String XML_CDATA = "__xml_cdata";
+
+ public static final String DTD_INTERNAL = "__dtd_internal";
+
+ public static final String DTD_INTERNAL_PI = "__dtd_internal_pi";
+
+ public static final String DTD_INTERNAL_COMMENT = "__dtd_internal_comment";
+
+ public static final String DTD_INTERNAL_DECL = "__dtd_internal_declaration";
+
+ public static final String DTD_CONDITIONAL = "__dtd_conditional";
+
+ public static final int STATE_DEFAULT = 0;
+
+ public static final int STATE_TAG = 1;
+
+ public static final int STATE_DECL = 2;
+
+ public static final int STATE_CDATA = 4;
+
+ public static final int STATE_INTERNAL = 8;
+
+ protected IDocument document;
+
+ protected int end;
+
+ protected int offset;
+
+ protected int length;
+
+ protected int position;
+
+ protected int state;
+
+ protected boolean parsedtd;
+
+ protected Map tokens = new HashMap();
+
+ public XMLPartitionScanner(boolean parsedtd) {
+ this.parsedtd = parsedtd;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
+ */
+ public IToken nextToken() {
+ offset += length;
+
+ switch (state) {
+ case STATE_TAG:
+ return nextTagToken();
+
+ case STATE_DECL:
+ return nextDeclToken();
+
+ case STATE_CDATA:
+ return nextCDATAToken();
+ }
+
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '<':
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ if (parsedtd || isInternal()) {
+ break;
+ }
+
+ state = STATE_DEFAULT;
+ return getToken(XML_TAG);
+
+ case '?': // ':
+ state = STATE_DEFAULT;
+ return getToken(XML_TAG);
+
+ case '"':
+ case '\'':
+ while (true) {
+ int ch = read();
+
+ if (ch == quot) {
+ state = STATE_TAG;
+ return getToken(XML_ATTRIBUTE);
+ }
+
+ switch (ch) {
+ case '<':
+ unread();
+
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(XML_ATTRIBUTE);
+ }
+ }
+ default:
+ unread();
+ }
+
+ while (true) {
+ switch (read()) {
+ case '<':
+ unread();
+
+ case ICharacterScanner.EOF:
+ case '>':
+ state = STATE_DEFAULT;
+ return getToken(XML_TAG);
+
+ case '"':
+ case '\'':
+ unread();
+
+ state = STATE_TAG;
+ return getToken(XML_TAG);
+ }
+ }
+ }
+
+ private IToken nextDeclToken() {
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
+
+ case '<':
+ if (parsedtd || isInternal()) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(isInternal() ? DTD_INTERNAL : null);
+
+ case '!':
+ case '?':
+ unread();
+ break;
+
+ default:
+ continue loop;
+ }
+ }
+
+ unread();
+
+ case '>':
+ state &= STATE_INTERNAL;
+ return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
+
+ case '[': //
+ if (!isInternal()) {
+ state = STATE_INTERNAL;
+ return getToken(XML_DECL);
+ }
+ }
+ }
+ }
+
+ private IToken nextCommentToken() {
+ state &= STATE_INTERNAL;
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '-': // - -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '-': // -- -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ case '>':
+ break loop;
+ }
+
+ unread();
+ continue loop;
+ }
+ }
+ }
+
+ return getToken(isInternal() ? DTD_INTERNAL_COMMENT : XML_COMMENT);
+ }
+
+ private IToken nextPIToken() {
+ state &= STATE_INTERNAL;
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '?': // ? ?>
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ case '>':
+ break loop;
+ }
+
+ unread();
+ }
+ }
+
+ return getToken(isInternal() ? DTD_INTERNAL_PI : XML_PI);
+ }
+
+ private IToken nextCDATAToken() {
+ state = STATE_DEFAULT;
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case ']': // ] ]]>
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case ']': // ]] ]]>
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ case '>': // ]]>
+ break loop;
+ }
+
+ unread();
+ unread();
+ continue loop;
+ }
+ }
+ }
+
+ return getToken(XML_CDATA);
+ }
+
+ private IToken nextConditionalToken() {
+ state = STATE_DEFAULT;
+
+ int level = 1;
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '<': // - -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '!': // -- -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case '[':
+ ++level;
+ continue loop;
+ }
+
+ unread();
+ continue loop;
+ }
+
+ unread();
+ continue loop;
+
+ case ']': // - -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ break loop;
+
+ case ']': // -- -->
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ case '>':
+ if (--level == 0) {
+ break loop;
+ }
+
+ continue loop;
+ }
+
+ unread();
+ unread();
+ continue loop;
+ }
+ }
+ }
+
+ return getToken(DTD_CONDITIONAL);
+ }
+
+ private IToken getToken(String type) {
+ length = position - offset;
+
+ if (length == 0) {
+ return Token.EOF;
+ }
+
+ if (type == null) {
+ return Token.UNDEFINED;
+ }
+
+ IToken token = (IToken) tokens.get(type);
+ if (token == null) {
+ token = new Token(type);
+ tokens.put(type, token);
+ }
+
+ return token;
+ }
+
+ private boolean isInternal() {
+ return (state & STATE_INTERNAL) != 0;
+ }
+
+ private int read() {
+ if (position >= end) {
+ return ICharacterScanner.EOF;
+ }
+
+ try {
+ return document.getChar(position++);
+ } catch (BadLocationException e) {
+ --position;
+ return ICharacterScanner.EOF;
+ }
+ }
+
+ private void unread() {
+ --position;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
+ */
+ public int getTokenOffset() {
+ Assert.isTrue(offset >= 0, Integer.toString(offset));
+ return offset;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
+ */
+ public int getTokenLength() {
+ return length;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int,
+ * int)
+ */
+ public void setRange(IDocument document, int offset, int length) {
+ this.document = document;
+ this.end = offset + length;
+
+ this.offset = offset;
+ this.position = offset;
+ this.length = 0;
+
+ this.state = STATE_DEFAULT;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
+ */
+ // public void setPartialRange(IDocument document, int offset, int length,
+ // String contentType, int partitionOffset) {
+ // state = STATE_DEFAULT;
+ // if (partitionOffset > -1) {
+ // int delta = offset - partitionOffset;
+ // if (delta > 0) {
+ // setRange(document, partitionOffset, length + delta);
+ // return;
+ // }
+ // }
+ // setRange(document, partitionOffset, length);
+ // }
+ /*
+ * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
+ */
+ public void setPartialRange(IDocument document, int offset, int length,
+ String contentType, int partitionOffset) {
+ // boolean flag = false;
+ this.document = document;
+ this.end = offset + length;
+
+ // NB! Undocumented value: -1
+ if (partitionOffset >= 0) {
+ offset = partitionOffset;
+ // flag = true;
+ }
+
+ this.offset = offset;
+ this.position = offset;
+ this.length = 0;
+
+ // if (flag) {
+ // state = STATE_DEFAULT;
+ // return;
+ // }
+ if (contentType == XML_ATTRIBUTE) {
+ state = STATE_TAG;
+ return;
+ }
+
+ if (contentType == XML_TAG) {
+ state = isContinuationPartition() ? STATE_TAG : STATE_DEFAULT;
+ return;
+ }
+
+ if (contentType == XML_DECL) {
+ state = isContinuationPartition() ? STATE_DECL : STATE_DEFAULT;
+ return;
+ }
+
+ if (contentType == DTD_INTERNAL || contentType == DTD_INTERNAL_PI
+ || contentType == DTD_INTERNAL_DECL
+ || contentType == DTD_INTERNAL_COMMENT) {
+ state = STATE_INTERNAL;
+ return;
+ }
+
+ state = STATE_DEFAULT;
+ }
+
+ private boolean isContinuationPartition() {
+ try {
+ String type = document.getContentType(offset - 1);
+
+ if (type != IDocument.DEFAULT_CONTENT_TYPE) {
+ return true;
+ }
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLReconcileStep.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLReconcileStep.java
new file mode 100644
index 0000000..4bfbac7
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLReconcileStep.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2003-2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLReconcileStep.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+import net.sourceforge.phpeclipse.xml.core.parser.IProblem;
+import net.sourceforge.phpeclipse.xml.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLDocumentProvider;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.AbstractReconcileStep;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilableModel;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Implementation of a reconcile step for building the XML parse tree on changes
+ * to the editor content.
+ */
+public class XMLReconcileStep extends AbstractReconcileStep {
+
+ // Inner Classes -----------------------------------------------------------
+
+ /**
+ * Adapts an IXMLDocument
to the
+ * IReconcilableModel
interface.
+ */
+ private class XMLDocumentAdapter implements IReconcilableModel {
+ private IXMLDocument document;
+
+ public XMLDocumentAdapter(IXMLDocument document) {
+ this.document = document;
+ }
+
+ public IXMLDocument getDocument() {
+ return document;
+ }
+
+ }
+
+ /**
+ * Implementation of the problem collector interface for creating problem
+ * annotations when there are problems parsing the style sheet.
+ */
+ private class ProblemCollector implements IProblemCollector {
+ /**
+ * The list of problems added to this collector.
+ */
+ private List collectedProblems = new ArrayList();
+
+ /**
+ * @see IProblemCollector#addProblem(IProblem)
+ */
+ public void addProblem(IProblem problem) {
+ collectedProblems.add(problem);
+ }
+
+ /**
+ * Returns the list of problems collected while the CSS source has been
+ * parsed, in the order they were reported. The list returned is
+ * immutable.
+ *
+ * @return the list of collected problems (of type {@link IProblem})
+ */
+ public List getProblems() {
+ return Collections.unmodifiableList(collectedProblems);
+ }
+ }
+
+ /**
+ * Adapter that adapts an {@link IProblem} to an {@link Annotation}.
+ */
+ private class ProblemAdapter extends AnnotationAdapter {
+ private IProblem problem;
+
+ private Position position;
+
+ public ProblemAdapter(IProblem problem) {
+ this.problem = problem;
+ }
+
+ public Position getPosition() {
+ if (position == null) {
+ position = createPositionFromProblem();
+ }
+
+ return position;
+ }
+
+ public Annotation createAnnotation() {
+ int start = problem.getSourceStart();
+ if (start < 0) {
+ return null;
+ }
+
+ int length = problem.getSourceEnd() - start + 1;
+ if (length < 0) {
+ return null;
+ }
+
+ String type;
+ if (problem.isWarning()) {
+ type = XMLAnnotation.TYPE_ERROR;
+ } else if (problem.isError()) {
+ type = XMLAnnotation.TYPE_WARNING;
+ } else {
+ type = XMLAnnotation.TYPE_INFO;
+ }
+
+ return new XMLAnnotation(type, false, problem.getMessage());
+ }
+
+ private Position createPositionFromProblem() {
+ int start = problem.getSourceStart();
+ if (start < 0) {
+ return null;
+ }
+
+ int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
+ if (length < 0) {
+ return null;
+ }
+
+ return new Position(start, length);
+ }
+
+ }
+
+ // Instance Variables ------------------------------------------------------
+
+ private ITextEditor editor;
+
+ private XMLDocumentAdapter xmlDocumentAdapter;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public XMLReconcileStep(ITextEditor editor) {
+ this.editor = editor;
+
+ xmlDocumentAdapter = new XMLDocumentAdapter(getXMLDocument());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param step
+ * the step to add to the pipe
+ * @param editor
+ * the associated text editor
+ */
+ public XMLReconcileStep(IReconcileStep step, ITextEditor editor) {
+ super(step);
+
+ this.editor = editor;
+
+ xmlDocumentAdapter = new XMLDocumentAdapter(getXMLDocument());
+ }
+
+ // AbstractReconcileStep Implementation ------------------------------------
+
+ /*
+ * @see AbstractReconcileStep#reconcileModel(DirtyRegion, IRegion)
+ */
+ protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion,
+ IRegion subRegion) {
+ IXMLDocument model = xmlDocumentAdapter.getDocument();
+
+ IEditorInput editorInput = null;
+ IFile file = null;
+ if (editor != null) {
+ editorInput = editor.getEditorInput();
+ }
+
+ if (editorInput instanceof IFileEditorInput)
+ file = ((IFileEditorInput) editorInput).getFile();
+ ProblemCollector problemCollector = new ProblemCollector();
+ model.reconcile(problemCollector, file);
+
+ List problems = problemCollector.getProblems();
+ IReconcileResult[] retVal = new IReconcileResult[problems.size()];
+ for (int i = 0; i < problems.size(); i++) {
+ IProblem problem = (IProblem) problems.get(i);
+ retVal[i] = new ProblemAdapter(problem);
+ }
+
+ return retVal;
+ }
+
+ /*
+ * @see AbstractReconcileStep#getModel()
+ */
+ public IReconcilableModel getModel() {
+ return xmlDocumentAdapter;
+ }
+
+ // Private Methods Implementation ------------------------------------------
+
+ /**
+ * Retrieve the style sheet associated with the editor input.
+ */
+ private IXMLDocument getXMLDocument() {
+ IDocumentProvider documentProvider = editor.getDocumentProvider();
+ if (documentProvider instanceof XMLDocumentProvider) {
+ XMLDocumentProvider xmlDocumentProvider = (XMLDocumentProvider) documentProvider;
+ return xmlDocumentProvider.getModel(editor.getEditorInput());
+ }
+
+ return null;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLReconcilingStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLReconcilingStrategy.java
new file mode 100644
index 0000000..47a7798
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLReconcilingStrategy.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2003-2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLReconcilingStrategy.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Iterator;
+
+import net.sourceforge.phpeclipse.ui.text.IReconcilingParticipant;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Reconciling strategy for XML document. This class is responsible for keeping
+ * the parsed model in sync with the text.
+ */
+public class XMLReconcilingStrategy implements IReconcilingStrategy,
+ IReconcilingStrategyExtension {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated text editor.
+ */
+ private ITextEditor editor;
+
+ /**
+ * A progress monitor that should be used for long-running operations.
+ */
+ IProgressMonitor progressMonitor;
+
+ /**
+ * The first (and only) reconcile step is the parsing of the style sheet.
+ */
+ private IReconcileStep firstStep;
+
+ // Constructors ------------------------------------------------------------
+
+ public XMLReconcilingStrategy(ITextEditor editor) {
+ this.editor = editor;
+ firstStep = new XMLReconcileStep(editor);
+ }
+
+ // IReconcilingStrategy Implementation -------------------------------------
+
+ /**
+ * @see IReconcilingStrategy#reconcile(DirtyRegion, IRegion)
+ */
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ removeTemporaryAnnotations();
+ process(firstStep.reconcile(dirtyRegion, subRegion));
+ }
+
+ /**
+ * @see IReconcilingStrategy#reconcile(IRegion)
+ */
+ public void reconcile(IRegion partition) {
+ removeTemporaryAnnotations();
+ process(firstStep.reconcile(partition));
+ }
+
+ /**
+ * @see IReconcilingStrategy#setDocument(IDocument)
+ */
+ public void setDocument(IDocument document) {
+ // FIXME
+ firstStep.setInputModel(null); // new DocumentAdapter(document);
+ }
+
+ // IReconcilingStrategyExtension Implementation ----------------------------
+
+ /**
+ * @see IReconcilingStrategyExtension#initialReconcile()
+ */
+ public void initialReconcile() {
+ process(firstStep.reconcile(null));
+ }
+
+ /**
+ * @see IReconcilingStrategyExtension#setProgressMonitor(IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ firstStep.setProgressMonitor(monitor);
+ progressMonitor = monitor;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the annotation model for the editor input.
+ *
+ * @return the annotation model
+ */
+ IAnnotationModel getAnnotationModel() {
+ IEditorInput input = editor.getEditorInput();
+ return editor.getDocumentProvider().getAnnotationModel(input);
+ }
+
+ /**
+ * Adds results of the reconcilation to the annotation model.
+ */
+ private void process(final IReconcileResult[] results) {
+ if (results == null) {
+ return;
+ }
+
+ IRunnableWithProgress runnable = new WorkspaceModifyOperation() {
+ protected void execute(IProgressMonitor monitor) {
+ for (int i = 0; i < results.length; i++) {
+ if ((progressMonitor != null)
+ && (progressMonitor.isCanceled())) {
+ return;
+ }
+
+ if (results[i] instanceof AnnotationAdapter) {
+ AnnotationAdapter result = (AnnotationAdapter) results[i];
+ Position pos = result.getPosition();
+ Annotation annotation = result.createAnnotation();
+ getAnnotationModel().addAnnotation(annotation, pos);
+ }
+ }
+ }
+ };
+
+ try {
+ runnable.run(null);
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ if (editor instanceof IReconcilingParticipant) {
+ ((IReconcilingParticipant) editor).reconciled();
+ }
+ }
+
+ /*
+ * TODO A "real" implementation must be smarter, i.e. don't remove and add
+ * the annotations which are the same.
+ */
+ private void removeTemporaryAnnotations() {
+ Iterator i = getAnnotationModel().getAnnotationIterator();
+ while (i.hasNext()) {
+ Annotation annotation = (Annotation) i.next();
+ if (!annotation.isPersistent()) {
+ getAnnotationModel().removeAnnotation(annotation);
+ }
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTagRule.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTagRule.java
new file mode 100644
index 0000000..da8fa87
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTagRule.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLTagRule.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ * Rule detecting XML tag brackets and name.
+ *
+ * @author Igor Malinin
+ */
+public class XMLTagRule implements IRule {
+
+ private IToken token;
+
+ public XMLTagRule(IToken token) {
+ this.token = token;
+ }
+
+ public IToken evaluate(ICharacterScanner scanner) {
+ int ch = scanner.read();
+ if (ch == '>') {
+ return token;
+ }
+ if (ch == '/') {
+ ch = scanner.read();
+ if (ch == '>') {
+ return token;
+ }
+
+ scanner.unread();
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+ if (ch == '<') {
+ ch = scanner.read();
+ if (ch == '/') {
+ ch = scanner.read();
+ }
+ loop: while (true) {
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ case 0x09:
+ case 0x0A:
+ case 0x0D:
+ case 0x20:
+ break loop;
+ }
+
+ ch = scanner.read();
+ }
+
+ scanner.unread();
+ return token;
+ }
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTagScanner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTagScanner.java
new file mode 100644
index 0000000..f0ef3d1
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTagScanner.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLTagScanner.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.xml.ui.text.IXMLSyntaxConstants;
+
+import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WordRule;
+
+/**
+ * @author Igor Malinin
+ */
+public class XMLTagScanner extends BufferedRuleBasedScanner {
+
+ /**
+ * Creates a color token scanner.
+ */
+ public XMLTagScanner(Map tokens) {
+ setDefaultReturnToken((Token) tokens
+ .get(IXMLSyntaxConstants.XML_DEFAULT));
+
+ IToken tag = (Token) tokens.get(IXMLSyntaxConstants.XML_TAG);
+ IToken attribute = (Token) tokens.get(IXMLSyntaxConstants.XML_ATT_NAME);
+
+ IRule[] rules = { new XMLTagRule(tag),
+ new WordRule(new NameDetector(), attribute), };
+
+ setRules(rules);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTextHover.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTextHover.java
new file mode 100644
index 0000000..998f415
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLTextHover.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2003-2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Christopher Lenz - initial API and implementation
+ *
+ * $Id: XMLTextHover.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import java.util.Iterator;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+
+/**
+ * Implements simple annotation hover to show the associated messages.
+ */
+public class XMLTextHover implements ITextHover {
+ /**
+ * This hovers annotation model.
+ */
+ private IAnnotationModel model;
+
+ /**
+ * Creates a new annotation hover.
+ *
+ * @param model
+ * this hover's annotation model
+ */
+ public XMLTextHover(IAnnotationModel model) {
+ this.model = model;
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion region) {
+ Iterator e = new XMLAnnotationIterator(model, true);
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+
+ Position p = model.getPosition(a);
+ if (p.overlapsWith(region.getOffset(), region.getLength())) {
+ String text = a.getText();
+ if ((text != null) && (text.trim().length() > 0)) {
+ return text;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /*
+ * @see ITextHover#getHoverRegion(ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ return XMLWordFinder.findWord(textViewer.getDocument(), offset);
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLWordFinder.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLWordFinder.java
new file mode 100644
index 0000000..4e2fbd8
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/internal/text/XMLWordFinder.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial implementation
+ *
+ * $Id: XMLWordFinder.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+package net.sourceforge.phpeclipse.xml.ui.internal.text;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class XMLWordFinder {
+ public static IRegion findWord(IDocument document, int offset) {
+ int length = document.getLength();
+
+ try {
+ int pos = offset;
+
+ while (pos >= 0) {
+ if (!Character.isUnicodeIdentifierPart(document.getChar(pos))) {
+ break;
+ }
+ --pos;
+ }
+
+ int start = pos;
+
+ pos = offset;
+
+ while (pos < length) {
+ if (!Character.isUnicodeIdentifierPart(document.getChar(pos))) {
+ break;
+ }
+ ++pos;
+ }
+
+ int end = pos;
+
+ if (start == offset) {
+ return new Region(start, end - start);
+ }
+
+ return new Region(start + 1, end - start - 1);
+ } catch (BadLocationException x) {
+ return null;
+ }
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/DTDTextTools.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/DTDTextTools.java
new file mode 100644
index 0000000..bb2fbbc
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/DTDTextTools.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: DTDTextTools.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.text;
+
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.ui.text.AbstractTextTools;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.DeclScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.SingleTokenScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.TextScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLPartitionScanner;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.DefaultPartitioner;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class DTDTextTools extends AbstractTextTools {
+ private static final String[] TOKENS = { IXMLSyntaxConstants.XML_DEFAULT,
+ IXMLSyntaxConstants.XML_ATT_NAME,
+ IXMLSyntaxConstants.XML_ATT_VALUE, IXMLSyntaxConstants.XML_ENTITY,
+ IXMLSyntaxConstants.XML_PI, IXMLSyntaxConstants.XML_COMMENT,
+ IXMLSyntaxConstants.XML_DECL, IXMLSyntaxConstants.DTD_CONDITIONAL, };
+
+ private static final String[] TYPES = { XMLPartitionScanner.XML_PI,
+ XMLPartitionScanner.XML_COMMENT, XMLPartitionScanner.XML_DECL,
+ XMLPartitionScanner.DTD_CONDITIONAL, };
+
+ /** The DTD partitions scanner */
+ private XMLPartitionScanner dtdPartitionScanner;
+
+ /** The DTD text scanner */
+ private TextScanner dtdTextScanner;
+
+ /** The DTD conditional sections scanner */
+ private SingleTokenScanner dtdConditionalScanner;
+
+ /** The XML processing instructions scanner */
+ private SingleTokenScanner xmlPIScanner;
+
+ /** The XML comments scanner */
+ private SingleTokenScanner xmlCommentScanner;
+
+ /** The XML declarations scanner */
+ private DeclScanner xmlDeclScanner;
+
+ /**
+ * Creates a new DTD text tools collection.
+ */
+ public DTDTextTools(IPreferenceStore store) {
+ super(store, TOKENS);
+
+ dtdPartitionScanner = new XMLPartitionScanner(true);
+
+ Map tokens = getTokens();
+
+ dtdTextScanner = new TextScanner(tokens, '%',
+ IXMLSyntaxConstants.XML_DEFAULT);
+
+ dtdConditionalScanner = new SingleTokenScanner(tokens,
+ IXMLSyntaxConstants.DTD_CONDITIONAL); // cond
+
+ xmlPIScanner = new SingleTokenScanner(tokens,
+ IXMLSyntaxConstants.XML_PI);
+
+ xmlCommentScanner = new SingleTokenScanner(tokens,
+ IXMLSyntaxConstants.XML_COMMENT);
+
+ xmlDeclScanner = new DeclScanner(tokens);
+ }
+
+ /**
+ *
+ */
+ public IDocumentPartitioner createDTDPartitioner() {
+ return new DefaultPartitioner(dtdPartitionScanner, TYPES);
+ }
+
+ /**
+ *
+ */
+ public IPartitionTokenScanner getDTDPartitionScanner() {
+ return dtdPartitionScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan DTD text.
+ *
+ * @return an DTD text scanner
+ */
+ public RuleBasedScanner getDTDTextScanner() {
+ return dtdTextScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan DTD conditional sections.
+ *
+ * @return an DTD conditional section scanner
+ */
+ public RuleBasedScanner getDTDConditionalScanner() {
+ return dtdConditionalScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML processing
+ * instructions.
+ *
+ * @return an XML processing instruction scanner
+ */
+ public RuleBasedScanner getXMLPIScanner() {
+ return xmlPIScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML comments.
+ *
+ * @return an XML comment scanner
+ */
+ public RuleBasedScanner getXMLCommentScanner() {
+ return xmlCommentScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML declarations.
+ *
+ * @return an XML declaration scanner
+ */
+ public RuleBasedScanner getXMLDeclScanner() {
+ return xmlDeclScanner;
+ }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/IXMLSyntaxConstants.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/IXMLSyntaxConstants.java
new file mode 100644
index 0000000..7f3e194
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/IXMLSyntaxConstants.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: IXMLSyntaxConstants.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.text;
+
+/**
+ * @author Igor Malinin
+ */
+public interface IXMLSyntaxConstants {
+
+ /**
+ * Note: This constant is for internal use only. Clients should not use this
+ * constant. The prefix all color constants start with.
+ */
+ String PREFIX = "xml_"; //$NON-NLS-1$
+
+ /** The style key for XML text. */
+ String XML_DEFAULT = PREFIX + "text"; //$NON-NLS-1$
+
+ /** The style key for XML tag names. */
+ String XML_TAG = PREFIX + "tag"; //$NON-NLS-1$
+
+ /** The style key for XML attribute names. */
+ String XML_ATT_NAME = PREFIX + "attribute"; //$NON-NLS-1$
+
+ /** The style key for XML attribute values. */
+ String XML_ATT_VALUE = PREFIX + "string"; //$NON-NLS-1$
+
+ /** The style key for XML entities. */
+ String XML_ENTITY = PREFIX + "entity"; //$NON-NLS-1$
+
+ /** The style key for XML processing instructions. */
+ String XML_PI = PREFIX + "processing_instruction"; //$NON-NLS-1$
+
+ /** The style key for XML CDATA sections. */
+ String XML_CDATA = PREFIX + "cdata"; //$NON-NLS-1$
+
+ /** The style key for XML comments. */
+ String XML_COMMENT = PREFIX + "comment"; //$NON-NLS-1$
+
+ /** The style key for XML declaration. */
+ String XML_DECL = PREFIX + "declaration"; //$NON-NLS-1$
+
+ /** The style key for external DTD conditional sections. */
+ String DTD_CONDITIONAL = PREFIX + "conditional"; //$NON-NLS-1$
+
+ /** The style key for SMARTY tag names. */
+ String XML_SMARTY = PREFIX + "smarty"; //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/XMLTextTools.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/XMLTextTools.java
new file mode 100644
index 0000000..5c6d32b
--- /dev/null
+++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/xml/ui/text/XMLTextTools.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial contribution
+ *
+ * $Id: XMLTextTools.java,v 1.4 2006-10-21 23:14:13 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.ui.text;
+
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.ui.text.AbstractTextTools;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.DeclScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.PHPXMLPartitionScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.SingleTokenScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.TextScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLCDATAScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLPartitionScanner;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLTagScanner;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.DefaultPartitioner;
+import org.eclipse.jface.text.rules.ITokenScanner;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class XMLTextTools extends AbstractTextTools {
+ /** Text Attributes for XML editors */
+ public static final String[] TOKENS = { IXMLSyntaxConstants.XML_DEFAULT,
+ IXMLSyntaxConstants.XML_TAG, IXMLSyntaxConstants.XML_ATT_NAME,
+ IXMLSyntaxConstants.XML_ATT_VALUE, IXMLSyntaxConstants.XML_ENTITY,
+ IXMLSyntaxConstants.XML_PI, IXMLSyntaxConstants.XML_CDATA,
+ IXMLSyntaxConstants.XML_COMMENT, IXMLSyntaxConstants.XML_SMARTY,
+ IXMLSyntaxConstants.XML_DECL, };
+
+ /** Content types for XML editors */
+ public static final String[] TYPES = { XMLPartitionScanner.XML_PI,
+ XMLPartitionScanner.XML_COMMENT, XMLPartitionScanner.XML_DECL,
+ XMLPartitionScanner.XML_TAG, XMLPartitionScanner.XML_ATTRIBUTE,
+ XMLPartitionScanner.XML_CDATA, XMLPartitionScanner.DTD_INTERNAL,
+ XMLPartitionScanner.DTD_INTERNAL_PI,
+ XMLPartitionScanner.DTD_INTERNAL_COMMENT,
+ XMLPartitionScanner.DTD_INTERNAL_DECL, };
+
+ /** The XML partitions scanner */
+ private XMLPartitionScanner xmlPartitionScanner;
+
+ private PHPXMLPartitionScanner phpXMLPartitionScanner;
+
+ /** The XML text scanner */
+ private TextScanner xmlTextScanner;
+
+ /** The DTD text scanner */
+ private TextScanner dtdTextScanner;
+
+ /** The XML tags scanner */
+ private XMLTagScanner xmlTagScanner;
+
+ /** The XML attributes scanner */
+ private TextScanner xmlAttributeScanner;
+
+ /** The XML CDATA sections scanner */
+ private XMLCDATAScanner xmlCDATAScanner;
+
+ /** The XML processing instructions scanner */
+ private SingleTokenScanner xmlPIScanner;
+
+ /** The XML comments scanner */
+ private SingleTokenScanner xmlCommentScanner;
+
+ /** The XML declarations scanner */
+ private DeclScanner xmlDeclScanner;
+
+ public XMLTextTools(IPreferenceStore store) {
+ this(store, TOKENS);
+ }
+
+ /**
+ * Creates a new XML text tools collection.
+ */
+ public XMLTextTools(IPreferenceStore store, String[] strTokens) {
+ super(store, strTokens);
+
+ xmlPartitionScanner = new XMLPartitionScanner(false);
+ phpXMLPartitionScanner = new PHPXMLPartitionScanner(false);
+ Map tokens = getTokens();
+
+ xmlTextScanner = new TextScanner(tokens, '&',
+ IXMLSyntaxConstants.XML_DEFAULT);
+
+ dtdTextScanner = new TextScanner(tokens, '%',
+ IXMLSyntaxConstants.XML_DEFAULT);
+
+ xmlPIScanner = new SingleTokenScanner(tokens,
+ IXMLSyntaxConstants.XML_PI);
+
+ xmlCommentScanner = new SingleTokenScanner(tokens,
+ IXMLSyntaxConstants.XML_COMMENT);
+
+ xmlDeclScanner = new DeclScanner(tokens);
+
+ xmlTagScanner = new XMLTagScanner(tokens);
+
+ xmlAttributeScanner = new TextScanner(tokens, '&',
+ IXMLSyntaxConstants.XML_ATT_VALUE);
+
+ xmlCDATAScanner = new XMLCDATAScanner(tokens);
+ }
+
+ /**
+ *
+ */
+ public IDocumentPartitioner createXMLPartitioner() {
+ return new DefaultPartitioner(xmlPartitionScanner, TYPES);
+ }
+
+ public IDocumentPartitioner createPHPXMLPartitioner() {
+ return new DefaultPartitioner(phpXMLPartitionScanner, TYPES);
+ }
+
+ /**
+ *
+ */
+ // public IPartitionTokenScanner getXMLPartitionScanner() {
+ // return xmlPartitionScanner;
+ // }
+ /**
+ * Returns a scanner which is configured to scan XML text.
+ *
+ * @return an XML text scanner
+ */
+ public RuleBasedScanner getXMLTextScanner() {
+ return xmlTextScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan DTD text.
+ *
+ * @return an DTD text scanner
+ */
+ public RuleBasedScanner getDTDTextScanner() {
+ return dtdTextScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML tags.
+ *
+ * @return an XML tag scanner
+ */
+ public RuleBasedScanner getXMLTagScanner() {
+ return xmlTagScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML tag attributes.
+ *
+ * @return an XML tag attribute scanner
+ */
+ public RuleBasedScanner getXMLAttributeScanner() {
+ return xmlAttributeScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML CDATA sections.
+ *
+ * @return an XML CDATA section scanner
+ */
+ public ITokenScanner getXMLCDATAScanner() {
+ return xmlCDATAScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML processing
+ * instructions.
+ *
+ * @return an XML processing instruction scanner
+ */
+ public RuleBasedScanner getXMLPIScanner() {
+ return xmlPIScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML comments.
+ *
+ * @return an XML comment scanner
+ */
+ public RuleBasedScanner getXMLCommentScanner() {
+ return xmlCommentScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan XML declarations.
+ *
+ * @return an XML declaration scanner
+ */
+ public RuleBasedScanner getXMLDeclScanner() {
+ return xmlDeclScanner;
+ }
+}