### Eclipse Workspace Patch 1.0
#P org.codehaus.groovy.eclipse.ui
Index: src/org/codehaus/groovy/eclipse/editor/FoldingPositionProvider.java
===================================================================
--- src/org/codehaus/groovy/eclipse/editor/FoldingPositionProvider.java	(revision 0)
+++ src/org/codehaus/groovy/eclipse/editor/FoldingPositionProvider.java	(revision 0)
@@ -0,0 +1,217 @@
+package org.codehaus.groovy.eclipse.editor;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ImportNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.eclipse.GroovyPlugin;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+
+/**
+ * Provides and updates positions for folding positions.
+ * 
+ * @author km
+ */
+public class FoldingPositionProvider {
+	private IDocument document;
+	private Set positions = new HashSet();
+	private Set removedPositions = new HashSet();
+	private Set addedPositions = new HashSet();
+	private Set oldPositions;
+
+	private class FoldingStructureVisitor extends ClassCodeVisitorSupport {
+		public void visitClass(ClassNode node) {
+			super.visitClass(node);
+			addPosition(node);
+		}
+
+		public void visitMethod(MethodNode node) {
+			super.visitMethod(node);
+			addPosition(node);
+		}
+
+		protected SourceUnit getSourceUnit() {
+			return null;
+		}
+	}
+
+	/**
+	 * @param document
+	 *            document for which to provide folding positions (must
+	 *            implement {@link IDocumentExtension3}).
+	 * @param oldPositions
+	 *            list of previous position (of type {@link Position}).
+	 */
+	public FoldingPositionProvider(IDocument document, Collection oldPositions) {
+		super();
+		assert document instanceof IDocumentExtension3;
+		this.document = document;
+		this.oldPositions = new HashSet(oldPositions);
+	}
+
+	public Set getAddedPositions() {
+		return Collections.unmodifiableSet(addedPositions);
+	}
+
+	/**
+	 * After calling {@link #updatePositions} this method returns the list of
+	 * folding positions that need to be removed.
+	 * 
+	 * @return List of removed folding position (of type {@link Position}).
+	 */
+	public Set getRemovedPositions() {
+		return Collections.unmodifiableSet(removedPositions);
+	}
+
+	public Set getPositions() {
+		return Collections.unmodifiableSet(positions);
+	}
+
+	/**
+	 * Updates the folding positions with the given list of module nodes (of
+	 * type {@link ModuleNode}).
+	 * 
+	 * @param moduleNodes
+	 *            List of module nodes for updating the folding positions (of
+	 *            type {@link ModuleNode}).
+	 */
+	public void updatePositions(final List moduleNodes) {
+		positions = new HashSet();
+		final FoldingStructureVisitor foldingStructureVisitor = new FoldingStructureVisitor();
+		for (Iterator moduleNodeIter = moduleNodes.iterator(); moduleNodeIter
+				.hasNext();) {
+			final ModuleNode moduleNode = (ModuleNode) moduleNodeIter.next();
+			final List classes = moduleNode.getClasses();
+			List importNodes = moduleNode.getImports();
+			addImportPositions(importNodes);
+			for (Iterator classNodeIter = classes.iterator(); classNodeIter
+					.hasNext();) {
+				final ClassNode classNode = (ClassNode) classNodeIter.next();
+				foldingStructureVisitor.visitClass(classNode);
+			}
+		}
+		addPositionsForMultilineCommentPartitions();
+		removedPositions = new HashSet(oldPositions);
+		removedPositions.removeAll(positions);
+		addedPositions = new HashSet(positions);
+		addedPositions.removeAll(oldPositions);
+	}
+
+	/**
+	 * Only import nodes with a type have a line number, so folding just works
+	 * with type imports!
+	 * 
+	 * @param importNodes
+	 *            belong to the same module node, so determining min and max
+	 *            line number is sufficient
+	 */
+	private void addImportPositions(List importNodes) {
+		if (importNodes.size() > 1) {
+			int startLineNo = 0;
+			int endLineNo = 0;
+			boolean firstPass = true;
+			for (Iterator importNodeIter = importNodes.iterator(); importNodeIter
+					.hasNext();) {
+				ImportNode importNode = (ImportNode) importNodeIter.next();
+				if (importNode.getType() != null) {
+					int lineNo = convertAntlrLineNoToEclipseLineNo(importNode
+							.getType().getLineNumber());
+					if (firstPass) {
+						startLineNo = endLineNo = lineNo;
+					} else {
+						boolean newImportFoldingRequired = lineNo - endLineNo > 1;
+						if (newImportFoldingRequired) {
+							addPosition(startLineNo, endLineNo);
+							startLineNo = endLineNo = lineNo;
+						} else {
+							endLineNo = lineNo;
+						}
+					}
+				}
+				firstPass = false;
+			}
+			addPosition(startLineNo, endLineNo);
+		}
+	}
+
+	private void addPositionsForMultilineCommentPartitions() {
+		final IDocumentPartitioner documentPartitioner = getDocumentExtension3()
+				.getDocumentPartitioner(GroovyPlugin.GROOVY_PARTITIONING);
+		final ITypedRegion[] partitions = documentPartitioner
+				.computePartitioning(0, document.getLength());
+		for (int i = 0; i < partitions.length; i++) {
+			final ITypedRegion typedRegion = partitions[i];
+			final String type = typedRegion.getType();
+			if (GroovyPartitionScanner.GROOVY_MULTILINE_COMMENT.equals(type)) {
+				try {
+					int startLineNo = document.getLineOfOffset(typedRegion
+							.getOffset());
+					int endLineNo = document.getLineOfOffset(typedRegion
+							.getOffset()
+							+ typedRegion.getLength());
+					addPosition(startLineNo, endLineNo);
+				} catch (BadLocationException e) {
+					GroovyPlugin.getDefault().logException(
+							"Exception in updating folding:", e);
+				}
+			}
+		}
+	}
+
+	private IDocumentExtension3 getDocumentExtension3() {
+		return (IDocumentExtension3) document;
+	}
+
+	private void addPosition(final ASTNode node) {
+		int lineNumber = convertAntlrLineNoToEclipseLineNo(node.getLineNumber());
+		int lastLineNumber = convertAntlrLineNoToEclipseLineNo(node
+				.getLastLineNumber());
+		addPosition(lineNumber, lastLineNumber);
+	}
+
+	/**
+	 * Projection supports code folding based on line numbers.
+	 * 
+	 * @param startLineNo
+	 * @param endLineNo
+	 * @return
+	 */
+	private void addPosition(int startLineNo, int endLineNo) {
+		if (startLineNo < endLineNo) {
+			try {
+				int startOffset = document.getLineOffset(startLineNo);
+				int endOffset = document.getLineOffset(endLineNo)
+						+ document.getLineLength(endLineNo);
+				int length = endOffset - startOffset;
+				Position position = new Position(startOffset, length);
+				positions.add(position);
+			} catch (BadLocationException e) {
+			}
+		}
+	}
+
+	/**
+	 * Antlr line numbers start with 1, eclipse line numbers with 0.
+	 * 
+	 * @param antlrLineNo
+	 * @return
+	 */
+	private int convertAntlrLineNoToEclipseLineNo(int antlrLineNo) {
+		return antlrLineNo - 1;
+	}
+}
Index: src/org/codehaus/groovy/eclipse/editor/GroovySourceViewer.java
===================================================================
--- src/org/codehaus/groovy/eclipse/editor/GroovySourceViewer.java	(revision 12158)
+++ src/org/codehaus/groovy/eclipse/editor/GroovySourceViewer.java	(working copy)
@@ -4,15 +4,18 @@
 import org.eclipse.jface.text.reconciler.MonoReconciler;
 import org.eclipse.jface.text.source.IOverviewRuler;
 import org.eclipse.jface.text.source.IVerticalRuler;
-import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
 import org.eclipse.swt.widgets.Composite;
 
-public class GroovySourceViewer extends SourceViewer {
-	
-	public GroovySourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean showAnnotationsOverview, int styles) {
-		super(parent, verticalRuler, overviewRuler, showAnnotationsOverview, styles);
+public class GroovySourceViewer extends ProjectionViewer {
+
+	public GroovySourceViewer(Composite parent, IVerticalRuler verticalRuler,
+			IOverviewRuler overviewRuler, boolean showAnnotationsOverview,
+			int styles) {
+		super(parent, verticalRuler, overviewRuler, showAnnotationsOverview,
+				styles);
 	}
-	
+
 	public void setDocument(IDocument document) {
 		// see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=137188
 		if (document == null && fReconciler != null) {
@@ -25,6 +28,6 @@
 		} else {
 			super.setDocument(document);
 		}
-	}	
-	
+	}
+
 }
\ No newline at end of file
Index: src/org/codehaus/groovy/eclipse/editor/GroovyEditor.java
===================================================================
--- src/org/codehaus/groovy/eclipse/editor/GroovyEditor.java	(revision 12158)
+++ src/org/codehaus/groovy/eclipse/editor/GroovyEditor.java	(working copy)
@@ -1,13 +1,24 @@
 package org.codehaus.groovy.eclipse.editor;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.ResourceBundle;
+import java.util.Set;
 
 import org.codehaus.groovy.eclipse.GroovyPlugin;
+import org.codehaus.groovy.eclipse.core.model.GroovyBuildListener;
+import org.codehaus.groovy.eclipse.core.model.GroovyModel;
+import org.codehaus.groovy.eclipse.core.model.GroovyProject;
 import org.codehaus.groovy.eclipse.editor.actions.IndentAction;
 import org.codehaus.groovy.eclipse.editor.contentoutline.GroovyContentOutline;
+import org.codehaus.groovy.eclipse.preferences.PreferenceConstants;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.jdt.internal.ui.JavaPlugin;
 import org.eclipse.jdt.internal.ui.text.JavaPairMatcher;
-import org.eclipse.jdt.ui.PreferenceConstants;
 import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IMenuManager;
@@ -12,14 +23,24 @@
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.preference.IPreferenceStore;
+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.ICharacterPairMatcher;
 import org.eclipse.jface.text.source.ISourceViewer;
 import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
 import org.eclipse.ui.texteditor.ChainedPreferenceStore;
 import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.IDocumentProvider;
 import org.eclipse.ui.texteditor.ITextEditor;
 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
 import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
@@ -26,127 +47,271 @@
 import org.eclipse.ui.texteditor.TextOperationAction;
 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
 
+public class GroovyEditor extends AbstractDecoratedTextEditor {
+	public static final String EDITOR_ID = "org.codehaus.groovy.eclipse.editor.GroovyEditor";
 
+	private ColorManager colorManager;
+	protected ICharacterPairMatcher pairMatcher = new JavaPairMatcher(
+			new char[] { '{', '}', '(', ')', '[', ']', '<', '>' });
 
-public class GroovyEditor extends AbstractDecoratedTextEditor{
-    private ColorManager colorManager;
-    public static final String EDITOR_ID = "org.codehaus.groovy.eclipse.editor.GroovyEditor";
-    protected ICharacterPairMatcher pairMatcher = new JavaPairMatcher(new char[] {'{', '}', '(', ')', '[', ']', '<', '>' } );
+	private ProjectionSupport projectionSupport;
+	private ProjectionAnnotationModel annotationModel;
+	private Collection projectionAnnotations = Collections.emptyList();
 
-    public GroovyEditor() {
-        super();
+	private final GroovyBuildListener foldingUpdater = new GroovyBuildListener() {
+		public void fileBuilt(IFile file) {
+			IFile editedFile = (IFile) getEditorInput().getAdapter(IFile.class);
+			if (file != null && file.equals(editedFile)) {
+				updateAnnotationModel();
+			}
+		}
+	};
 
-        setPreferenceStore(new ChainedPreferenceStore(
-                new IPreferenceStore[] {
-                        getPreferenceStore(),
-                        JavaPlugin.getDefault().getPreferenceStore(),
-                        GroovyPlugin.getDefault().getPreferenceStore()
-                }));
-        setEditorContextMenuId("#GroovyEditorContext"); //$NON-NLS-1$
+	public GroovyEditor() {
+		super();
+		setPreferenceStore(new ChainedPreferenceStore(new IPreferenceStore[] {
+				getPreferenceStore(),
+				JavaPlugin.getDefault().getPreferenceStore(),
+				GroovyPlugin.getDefault().getPreferenceStore() }));
+		setEditorContextMenuId("#GroovyEditorContext"); //$NON-NLS-1$
 		setRulerContextMenuId("#GroovyRulerContext"); //$NON-NLS-1$
-        colorManager = new ColorManager();
-        GroovyConfiguration groovyConfiguration = new GroovyConfiguration(colorManager);
-        groovyConfiguration.setEditor(this);
-        setSourceViewerConfiguration(groovyConfiguration);
-    }
-    
-    protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
-    	// Implementation taken from AbstractDecoratedTextEditor#createSourceViewer, except creating a with
+		colorManager = new ColorManager();
+		GroovyConfiguration groovyConfiguration = new GroovyConfiguration(
+				colorManager);
+		groovyConfiguration.setEditor(this);
+		setSourceViewerConfiguration(groovyConfiguration);
+	}
+
+	public void updateAnnotationModel() {
+		if (annotationModel == null) {
+			return;
+		}
+		final Map positionToProjectionAnnotation = new HashMap();
+		for (Iterator iterator = projectionAnnotations.iterator(); iterator
+				.hasNext();) {
+			final ProjectionAnnotation projectionAnnotation = (ProjectionAnnotation) iterator
+					.next();
+			final Position position = annotationModel
+					.getPosition(projectionAnnotation);
+			if (position != null) {
+				positionToProjectionAnnotation.put(position,
+						projectionAnnotation);
+			}
+		}
+
+		final IEditorInput input = getEditorInput();
+		final IFile editedFile = (IFile) input.getAdapter(IFile.class);
+		final IDocumentProvider documentProvider = getDocumentProvider();
+		final IDocument document = documentProvider.getDocument(input);
+
+		final Set positions = positionToProjectionAnnotation.keySet();
+		final FoldingPositionProvider foldingPositionProvider = new FoldingPositionProvider(
+				document, positions);
+		final List moduleNodes = GroovyModel.getModel().getModuleNodes(
+				editedFile);
+		foldingPositionProvider.updatePositions(moduleNodes);
+
+		final Set removedPositions = foldingPositionProvider
+				.getRemovedPositions();
+		final Annotation[] removedAnnotations = getAnnotations(
+				positionToProjectionAnnotation, removedPositions);
+		for (Iterator removedPositionIter = removedPositions.iterator(); removedPositionIter
+				.hasNext();) {
+			Position removedPosition = (Position) removedPositionIter.next();
+			positionToProjectionAnnotation.remove(removedPosition);
+		}
+		final Map addedAnnotations = new HashMap();
+		final Set addedPositions = foldingPositionProvider.getAddedPositions();
+		for (Iterator addedPositionIter = addedPositions.iterator(); addedPositionIter
+				.hasNext();) {
+			Position addedPosition = (Position) addedPositionIter.next();
+			ProjectionAnnotation projectionAnnotation = new ProjectionAnnotation();
+			addedAnnotations.put(projectionAnnotation, addedPosition);
+			positionToProjectionAnnotation.put(addedPosition,
+					projectionAnnotation);
+		}
+		annotationModel.modifyAnnotations(removedAnnotations, addedAnnotations,
+				null);
+		projectionAnnotations = positionToProjectionAnnotation.values();
+	}
+
+	private Annotation[] getAnnotations(final Map positionToAnnotation,
+			final Set positions) {
+		final Annotation[] annotations = new Annotation[positions.size()];
+		int i = 0;
+		for (Iterator positionIter = positions.iterator(); positionIter
+				.hasNext(); i++) {
+			final Position position = (Position) positionIter.next();
+			Annotation annotation = (Annotation) positionToAnnotation
+					.get(position);
+			annotations[i] = annotation;
+		}
+		return annotations;
+	}
+
+	protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+		super.handlePreferenceStoreChanged(event);
+		if (PreferenceConstants.GROOVY_EDITOR_FOLDING_ENABLED.equals(event
+				.getProperty())) {
+			updateFoldingEnabled();
+		}
+	}
+
+	private void updateFoldingEnabled() {
+		boolean foldingEnabled = getPreferenceStore().getBoolean(
+				PreferenceConstants.GROOVY_EDITOR_FOLDING_ENABLED);
+		ProjectionViewer sourceViewer = (ProjectionViewer) getSourceViewer();
+		if (foldingEnabled) {
+			sourceViewer.enableProjection();
+			annotationModel = sourceViewer.getProjectionAnnotationModel();
+			updateAnnotationModel();
+		} else {
+			sourceViewer.disableProjection();
+		}
+	}
+
+	public void createPartControl(Composite parent) {
+		super.createPartControl(parent);
+		ProjectionViewer viewer = (ProjectionViewer) getSourceViewer();
+
+		projectionSupport = new ProjectionSupport(viewer,
+				getAnnotationAccess(), getSharedColors());
+		projectionSupport
+				.addSummarizableAnnotationType(GroovyProject.GROOVY_ERROR_MARKER);
+		projectionSupport
+				.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error");
+		projectionSupport
+				.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning");
+
+		projectionSupport.install();
+		GroovyModel.getModel().addBuildListener(foldingUpdater);
+
+		updateFoldingEnabled();
+	}
+
+	protected ISourceViewer createSourceViewer(Composite parent,
+			IVerticalRuler ruler, int styles) {
+		// Implementation taken from
+		// AbstractDecoratedTextEditor#createSourceViewer, except creating a
+		// with
 		// GroovySourceViewer.
-		fAnnotationAccess= getAnnotationAccess();
-		fOverviewRuler= createOverviewRuler(getSharedColors());
+		fAnnotationAccess = getAnnotationAccess();
+		fOverviewRuler = createOverviewRuler(getSharedColors());
 
-		ISourceViewer viewer= new GroovySourceViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles);
+		ProjectionViewer viewer = new GroovySourceViewer(parent, ruler,
+				getOverviewRuler(), isOverviewRulerVisible(), styles);
 		getSourceViewerDecorationSupport(viewer);
 
 		return viewer;
-    }
-    
-    /**
-     * The GroovyEditor scope is:
-     * org.codehaus.groovy.eclipse.editor.GroovyEditorScope
-     * GroovyEditor specific key bindings use this as their 'contextId' so that 
-     * they are active only when a GroovyEditor has focus.
-     */
-    protected void initializeKeyBindingScopes() {
-        setKeyBindingScopes(new String[] { "org.codehaus.groovy.eclipse.editor.GroovyEditorScope" });
-    }
-    
-    /*
-     * @see IAdaptable#getAdapter(java.lang.Class)
-     * @since 2.0
-     */
-    public Object getAdapter(Class adapter) {
-        if (adapter.equals(IContentOutlinePage.class)) {
-            IFile file = (IFile) getEditorInput().getAdapter(IFile.class);
-            if (file!=null) return new GroovyContentOutline(file);
-        }
-        if (adapter.equals(ITextEditor.class)){
-           	return this;
-        }
-        return super.getAdapter(adapter);
-    }
-    
-    public void dispose() {
-        colorManager.dispose();
-        super.dispose();
-    }
-    
-    public int getCaretOffset() {
-        ISourceViewer viewer = getSourceViewer();
-        return viewer.getTextWidget().getCaretOffset();
-    }
-    
-    public void setCaretOffset(int offset) {
-        ISourceViewer viewer = getSourceViewer();
-        viewer.getTextWidget().setCaretOffset(offset);
-    }
-    
-    protected void editorContextMenuAboutToShow(IMenuManager menu) {
-        super.editorContextMenuAboutToShow(menu);
-        addAction(menu, "org.codehaus.groovy.eclipse.actions.RunGroovy");
-    }
-    
-    protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
-        support.setCharacterPairMatcher(pairMatcher);
-        support.setMatchingCharacterPainterPreferenceKeys(
-                org.eclipse.jdt.ui.PreferenceConstants.EDITOR_MATCHING_BRACKETS,
-                org.eclipse.jdt.ui.PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR);
-        super.configureSourceViewerDecorationSupport(support);
-    }
+	}
+
+	/**
+	 * The GroovyEditor scope is:
+	 * org.codehaus.groovy.eclipse.editor.GroovyEditorScope GroovyEditor
+	 * specific key bindings use this as their 'contextId' so that they are
+	 * active only when a GroovyEditor has focus.
+	 */
+	protected void initializeKeyBindingScopes() {
+		setKeyBindingScopes(new String[] { "org.codehaus.groovy.eclipse.editor.GroovyEditorScope" });
+	}
+
+	/*
+	 * @see IAdaptable#getAdapter(java.lang.Class)
+	 * @since 2.0
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(IContentOutlinePage.class)) {
+			IFile file = (IFile) getEditorInput().getAdapter(IFile.class);
+			if (file != null)
+				return new GroovyContentOutline(file);
+		}
+		if (adapter.equals(ITextEditor.class)) {
+			return this;
+		}
+		return super.getAdapter(adapter);
+	}
+
+	public void dispose() {
+		colorManager.dispose();
 
-    protected void createActions()
-    {
-        super.createActions();
-        Action 
-        action= new TextOperationAction(ResourceBundle.getBundle( GroovyEditor.class.getPackage().getName() + ".messages" ), "ContentAssistContextInformation.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION);	//$NON-NLS-1$
-        action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
-        setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
-        //markAsStateDependentAction("ContentAssistContextInformation", true); //$NON-NLS-1$
-        
-        action = new ContentAssistAction( ResourceBundle.getBundle( GroovyEditor.class.getPackage().getName() + ".messages" ), "ContentAssistProposal.", this );
-        action.setActionDefinitionId( ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS );
-        setAction( "ContentAssist", action );
-        markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
+		if (foldingUpdater != null) {
+			GroovyModel.getModel().removeBuildListener(foldingUpdater);
+		}
+		super.dispose();
+	}
 
+	public int getCaretOffset() {
+		ISourceViewer viewer = getSourceViewer();
+		return viewer.getTextWidget().getCaretOffset();
+	}
 
-        // Smart indenting when user presses the TAB key.
-        action= new IndentAction(ResourceBundle.getBundle( GroovyEditor.class.getPackage().getName() + ".messages" ), "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 TextOperationAction(ResourceBundle.getBundle( GroovyEditor.class.getPackage().getName() + ".messages" ), "ShowOutline.", this, ISourceViewer.QUICK_ASSIST);	//$NON-NLS-1$
-        	
-        	//new TextOperationAction(JavaEditorMessages.getBundleForConstructedKeys(),"ShowOutline.", this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
-		action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SHOW_OUTLINE);
+	public void setCaretOffset(int offset) {
+		ISourceViewer viewer = getSourceViewer();
+		viewer.getTextWidget().setCaretOffset(offset);
+	}
+
+	protected void editorContextMenuAboutToShow(IMenuManager menu) {
+		super.editorContextMenuAboutToShow(menu);
+		addAction(menu, "org.codehaus.groovy.eclipse.actions.RunGroovy");
+	}
+
+	protected void configureSourceViewerDecorationSupport(
+			SourceViewerDecorationSupport support) {
+		support.setCharacterPairMatcher(pairMatcher);
+		support
+				.setMatchingCharacterPainterPreferenceKeys(
+						org.eclipse.jdt.ui.PreferenceConstants.EDITOR_MATCHING_BRACKETS,
+						org.eclipse.jdt.ui.PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR);
+		super.configureSourceViewerDecorationSupport(support);
+	}
+
+	protected void createActions() {
+		super.createActions();
+		Action action = new TextOperationAction(
+				ResourceBundle.getBundle(GroovyEditor.class.getPackage()
+						.getName()
+						+ ".messages"), "ContentAssistContextInformation.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
+		action
+				.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
+		setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
+		// markAsStateDependentAction("ContentAssistContextInformation", true);
+		// //$NON-NLS-1$
+
+		action = new ContentAssistAction(ResourceBundle
+				.getBundle(GroovyEditor.class.getPackage().getName()
+						+ ".messages"), "ContentAssistProposal.", this);
+		action
+				.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+		setAction("ContentAssist", action);
+		markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
+
+		// Smart indenting when user presses the TAB key.
+		action = new IndentAction(ResourceBundle.getBundle(GroovyEditor.class
+				.getPackage().getName()
+				+ ".messages"), "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 TextOperationAction(
+				ResourceBundle.getBundle(GroovyEditor.class.getPackage()
+						.getName()
+						+ ".messages"), "ShowOutline.", this, ISourceViewer.QUICK_ASSIST); //$NON-NLS-1$
+
+		// new
+		// TextOperationAction(JavaEditorMessages.getBundleForConstructedKeys(),"ShowOutline.",
+		// this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
+		action
+				.setActionDefinitionId(IJavaEditorActionDefinitionIds.SHOW_OUTLINE);
 		setAction(IJavaEditorActionDefinitionIds.SHOW_OUTLINE, action);
 
-        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$
-        }
+		if (getPreferenceStore().getBoolean(
+				org.eclipse.jdt.ui.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$
+		}
 
-    }
+	}
 }
Index: src/org/codehaus/groovy/eclipse/preferences/PreferenceInitializer.java
===================================================================
--- src/org/codehaus/groovy/eclipse/preferences/PreferenceInitializer.java	(revision 12158)
+++ src/org/codehaus/groovy/eclipse/preferences/PreferenceInitializer.java	(working copy)
@@ -19,51 +19,74 @@
 	public void initializeDefaultPreferences() {
 		IPreferenceStore store = GroovyPlugin.getDefault().getPreferenceStore();
 
-		store.setDefault(PreferenceConstants.GROOVY_LOG_TRACE_MESSAGES_ENABLED, false);
-		
+		store.setDefault(PreferenceConstants.GROOVY_LOG_TRACE_MESSAGES_ENABLED,
+				false);
+
 		// GJDK Prefs
-		store.setDefault(PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GJDK_ENABLED, true);
-		PreferenceConverter.setDefault(store, 
-				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GJDK_COLOR, 
-				new Color(null, 102,204,255).getRGB());
-		
+		store.setDefault(
+				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GJDK_ENABLED, true);
+		PreferenceConverter.setDefault(store,
+				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GJDK_COLOR,
+				new Color(null, 102, 204, 255).getRGB());
+
 		// Multiline Comment Prefs
-		store.setDefault(PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_ENABLED, true);
-		PreferenceConverter.setDefault(store, 
-				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_COLOR,
-				new Color(null, 204, 0, 0).getRGB());
+		store
+				.setDefault(
+						PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_ENABLED,
+						true);
+		PreferenceConverter
+				.setDefault(
+						store,
+						PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_COLOR,
+						new Color(null, 204, 0, 0).getRGB());
 
 		// Java Keyword Prefs
-		store.setDefault(PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_ENABLED, true);
-		PreferenceConverter.setDefault(store, 
+		store
+				.setDefault(
+						PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_ENABLED,
+						true);
+		PreferenceConverter.setDefault(store,
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_COLOR,
 				new Color(null, 0, 102, 153).getRGB());
-		
+
 		// Groovy Keyword Prefs
-		store.setDefault(PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_ENABLED, true);
-		PreferenceConverter.setDefault(store, 
-				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_COLOR,
-				new Color(null, 0, 153, 102).getRGB());
-		
+		store
+				.setDefault(
+						PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_ENABLED,
+						true);
+		PreferenceConverter
+				.setDefault(
+						store,
+						PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_COLOR,
+						new Color(null, 0, 153, 102).getRGB());
+
 		// Java Types Prefs
-		store.setDefault(PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_ENABLED, true);
-		PreferenceConverter.setDefault(store, 
+		store.setDefault(
+				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_ENABLED,
+				true);
+		PreferenceConverter.setDefault(store,
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_COLOR,
 				new Color(null, 0, 153, 255).getRGB());
-		
+
 		// String Prefs
-		store.setDefault(PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_STRINGS_ENABLED, true);
-		PreferenceConverter.setDefault(store, 
+		store.setDefault(
+				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_STRINGS_ENABLED,
+				true);
+		PreferenceConverter.setDefault(store,
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_STRINGS_COLOR,
 				new Color(null, 255, 0, 204).getRGB());
-		
+
 		// Number Prefs
-		store.setDefault(PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_NUMBERS_ENABLED, true);
-		PreferenceConverter.setDefault(store, 
+		store.setDefault(
+				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_NUMBERS_ENABLED,
+				true);
+		PreferenceConverter.setDefault(store,
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_NUMBERS_COLOR,
 				new Color(null, 255, 0, 0).getRGB());
-		
-		
+
+		// Enable Folding
+		store.setDefault(PreferenceConstants.GROOVY_EDITOR_FOLDING_ENABLED,
+				true);
 	}
 
 }
Index: src/org/codehaus/groovy/eclipse/preferences/Messages.properties
===================================================================
--- src/org/codehaus/groovy/eclipse/preferences/Messages.properties	(revision 12158)
+++ src/org/codehaus/groovy/eclipse/preferences/Messages.properties	(working copy)
@@ -2,3 +2,24 @@
 OverlayPage.Use_Project_Settings=Use pr&oject settings
 OverlayPage.Configure_Workspace_Settings=&Configure Workspace Settings ...
 PropertyStore.Cannot_write_resource_property=Cannot write resource property 
+
+GroovyEditorPreferencesPage.Enable_GJDK_method_coloring=Enable GJDK method coloring
+GroovyEditorPreferencesPage.GJDK_method_color=GJDK method color
+GroovyEditorPreferencesPage.Enable_Groovy_keyword_coloring=Enable Groovy keyword coloring
+GroovyEditorPreferencesPage.Groovy_keyword_color=Groovy keyword color
+GroovyEditorPreferencesPage.Enable_multi_line_comment_coloring=Enable multi-line comment coloring
+GroovyEditorPreferencesPage.Multi_line_comment_color=Multi-line comment color
+GroovyEditorPreferencesPage.Enable_Java_types_coloring=Enable Java types coloring
+GroovyEditorPreferencesPage.Java_types_color=Java types color
+GroovyEditorPreferencesPage.Enable_Java_keyword_coloring=Enable Java keyword coloring
+GroovyEditorPreferencesPage.Java_keyword_color=Java Keyword color
+GroovyEditorPreferencesPage.Enable_String_coloring=Enable String coloring
+GroovyEditorPreferencesPage.String_color=String color
+GroovyEditorPreferencesPage.Enable_GroovyDoc_keyword_coloring=Enable GroovyDoc keyword coloring
+GroovyEditorPreferencesPage.GroovyDoc_keyword_color=GroovyDoc keyword color
+GroovyEditorPreferencesPage.Enable_GroovyDoc_tag_coloring=Enable GroovyDoc tag coloring
+GroovyEditorPreferencesPage.GroovyDoc_tag_color=GroovyDoc tag color
+GroovyEditorPreferencesPage.Enable_GroovyDoc_link_coloring=Enable GroovyDoc link coloring
+GroovyEditorPreferencesPage.GroovyDoc_link_color=GroovyDoc link color
+GroovyEditorPreferencesPage.Enable_folding=Enable f&olding
+GroovyEditorPreferencesPage.Copy_Java_Color_Preferences=&Copy Java Color Preferences
Index: src/org/codehaus/groovy/eclipse/preferences/PreferenceConstants.java
===================================================================
--- src/org/codehaus/groovy/eclipse/preferences/PreferenceConstants.java	(revision 12158)
+++ src/org/codehaus/groovy/eclipse/preferences/PreferenceConstants.java	(working copy)
@@ -5,42 +5,44 @@
  */
 public class PreferenceConstants {
 
-	public static final String P_PATH = "pathPreference";
+	public static final String P_PATH = "pathPreference"; //$NON-NLS-1$
 
-	public static final String GROOVY_EDITOR_HIGHLIGHT_GJDK_ENABLED = "groovy.editor.highlight.gjdk.enabled";
-	public static final String GROOVY_EDITOR_HIGHLIGHT_GJDK_COLOR = "groovy.editor.highlight.gjdk.color";
+	public static final String GROOVY_EDITOR_HIGHLIGHT_GJDK_ENABLED = "groovy.editor.highlight.gjdk.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_HIGHLIGHT_GJDK_COLOR = "groovy.editor.highlight.gjdk.color"; //$NON-NLS-1$
 
-	public static final String GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_ENABLED = "groovy.editor.highlight.multilinecomments.enabled";
-	public static final String GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_COLOR = "groovy.editor.highlight.multilinecomments.color";
+	public static final String GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_ENABLED = "groovy.editor.highlight.multilinecomments.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_COLOR = "groovy.editor.highlight.multilinecomments.color"; //$NON-NLS-1$
 
-	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_ENABLED = "groovy.editor.highlight.javakeywords.enabled";
-	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_COLOR = "groovy.editor.highlight.javakeywords.color";
+	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_ENABLED = "groovy.editor.highlight.javakeywords.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_COLOR = "groovy.editor.highlight.javakeywords.color"; //$NON-NLS-1$
 
-	public static final String GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_ENABLED = "groovy.editor.highlight.groovykeywords.enabled";
-	public static final String GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_COLOR = "groovy.editor.highlight.groovykeywords.color";
+	public static final String GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_ENABLED = "groovy.editor.highlight.groovykeywords.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_COLOR = "groovy.editor.highlight.groovykeywords.color"; //$NON-NLS-1$
 
-	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_ENABLED = "groovy.editor.highlight.javatypes.enabled";
-	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_COLOR = "groovy.editor.highlight.javatypes.color";
+	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_ENABLED = "groovy.editor.highlight.javatypes.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_COLOR = "groovy.editor.highlight.javatypes.color"; //$NON-NLS-1$
 
-	public static final String GROOVY_EDITOR_HIGHLIGHT_STRINGS_ENABLED = "groovy.editor.highlight.strings.enabled";
-	public static final String GROOVY_EDITOR_HIGHLIGHT_STRINGS_COLOR = "groovy.editor.highlight.strings.color";
+	public static final String GROOVY_EDITOR_HIGHLIGHT_STRINGS_ENABLED = "groovy.editor.highlight.strings.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_HIGHLIGHT_STRINGS_COLOR = "groovy.editor.highlight.strings.color"; //$NON-NLS-1$
 
-	public static final String GROOVY_EDITOR_HIGHLIGHT_NUMBERS_ENABLED = "groovy.editor.highlight.numbers.enabled";
-	public static final String GROOVY_EDITOR_HIGHLIGHT_NUMBERS_COLOR = "groovy.editor.highlight.numbers.color";
+	public static final String GROOVY_EDITOR_HIGHLIGHT_NUMBERS_ENABLED = "groovy.editor.highlight.numbers.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_HIGHLIGHT_NUMBERS_COLOR = "groovy.editor.highlight.numbers.color"; //$NON-NLS-1$
 
-//	public static final String GROOVY_GENERATE_CLASS_FILES = "groovy.generate.class.files";
-//    public static final String GROOVY_COMPILER_OUTPUT_PATH = "groovy.compiler.output.path";
-//    public static final String GROOVY_COMPILER_DEFAULT_OUTPUT_PATH = "groovy.compiler.output.defaultPath";
+	//	public static final String GROOVY_GENERATE_CLASS_FILES = "groovy.generate.class.files";
+	//    public static final String GROOVY_COMPILER_OUTPUT_PATH = "groovy.compiler.output.path";
+	//    public static final String GROOVY_COMPILER_DEFAULT_OUTPUT_PATH = "groovy.compiler.output.defaultPath";
 	// this preference will add the plugin trace statements to the error in order
 	// to make it easier to track down problems at runtime
-	public static final String GROOVY_LOG_TRACE_MESSAGES_ENABLED = "groovy.log.trace.messages.enabled";
-	
-	public static final String GROOVY_EDITOR_GROOVYDOC_KEYWORD_ENABLED = "groovy.editor.groovyDoc.keyword.enabled";
-	public static final String GROOVY_EDITOR_GROOVYDOC_KEYWORD_COLOR = "groovy.editor.groovyDoc.keyword.color";
-	
-	public static final String GROOVY_EDITOR_GROOVYDOC_TAG_ENABLED = "groovy.editor.groovyDoc.tag.enabled";
-	public static final String GROOVY_EDITOR_GROOVYDOC_TAG_COLOR = "groovy.editor.groovyDoc.tag.color";
-	
-	public static final String GROOVY_EDITOR_GROOVYDOC_LINK_ENABLED = "groovy.editor.groovyDoc.link.enabled";
-	public static final String GROOVY_EDITOR_GROOVYDOC_LINK_COLOR = "groovy.editor.groovyDoc.link.color";
+	public static final String GROOVY_LOG_TRACE_MESSAGES_ENABLED = "groovy.log.trace.messages.enabled"; //$NON-NLS-1$
+
+	public static final String GROOVY_EDITOR_GROOVYDOC_KEYWORD_ENABLED = "groovy.editor.groovyDoc.keyword.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_GROOVYDOC_KEYWORD_COLOR = "groovy.editor.groovyDoc.keyword.color"; //$NON-NLS-1$
+
+	public static final String GROOVY_EDITOR_GROOVYDOC_TAG_ENABLED = "groovy.editor.groovyDoc.tag.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_GROOVYDOC_TAG_COLOR = "groovy.editor.groovyDoc.tag.color"; //$NON-NLS-1$
+
+	public static final String GROOVY_EDITOR_GROOVYDOC_LINK_ENABLED = "groovy.editor.groovyDoc.link.enabled"; //$NON-NLS-1$
+	public static final String GROOVY_EDITOR_GROOVYDOC_LINK_COLOR = "groovy.editor.groovyDoc.link.color"; //$NON-NLS-1$
+
+	public static final String GROOVY_EDITOR_FOLDING_ENABLED = "groovy.editor.folding.enabled"; //$NON-NLS-1$
 }
Index: src/org/codehaus/groovy/eclipse/preferences/GroovyEditorPreferencesPage.java
===================================================================
--- src/org/codehaus/groovy/eclipse/preferences/GroovyEditorPreferencesPage.java	(revision 12158)
+++ src/org/codehaus/groovy/eclipse/preferences/GroovyEditorPreferencesPage.java	(working copy)
@@ -25,11 +25,8 @@
  * preference store that belongs to the main plug-in class. That way,
  * preferences can be accessed directly via the preference store.
  */
-
-public class GroovyEditorPreferencesPage 
-extends FieldEditorOverlayPage 
-implements IWorkbenchPreferencePage 
-{
+public class GroovyEditorPreferencesPage extends FieldEditorOverlayPage
+		implements IWorkbenchPreferencePage {
 
 	public GroovyEditorPreferencesPage() {
 		super(GRID);
@@ -46,10 +43,12 @@
 		// GJDK Color Prefs
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GJDK_ENABLED,
-				"&Enable GJDK method coloring", getFieldEditorParent()));
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_GJDK_method_coloring"), getFieldEditorParent())); //$NON-NLS-1$
 		addField(new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GJDK_COLOR,
-				"&GJDK method color", getFieldEditorParent()));
+				Messages
+						.getString("GroovyEditorPreferencesPage.GJDK_method_color"), getFieldEditorParent())); //$NON-NLS-1$
 
 		// Groovy Keyword Color Prefs
 		addField(new BooleanFieldEditor(
@@ -54,31 +53,37 @@
 		// Groovy Keyword Color Prefs
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_ENABLED,
-				"&Groovy keyword coloring", getFieldEditorParent()));
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_Groovy_keyword_coloring"), getFieldEditorParent())); //$NON-NLS-1$
 		addField(new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_GROOVYKEYWORDS_COLOR,
-				"&Groovy keyword color", getFieldEditorParent()));
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Groovy_keyword_color"), getFieldEditorParent())); //$NON-NLS-1$
+
 		// Multiline Comment Color Prefs
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_ENABLED,
-				"&Enable multi-line comment coloring", getFieldEditorParent()));
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_multi_line_comment_coloring"), getFieldEditorParent())); //$NON-NLS-1$
 
 		final ColorFieldEditor commentColor = new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_MULTILINECOMMENTS_COLOR,
-				"&Multi-line comment color", getFieldEditorParent());
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Multi_line_comment_color"), getFieldEditorParent()); //$NON-NLS-1$
+
 		addField(commentColor);
-		
+
 		// Java Types Comment Color Prefs
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_ENABLED,
-				"&Enable Java types coloring", getFieldEditorParent()));
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_Java_types_coloring"), getFieldEditorParent())); //$NON-NLS-1$
+
 		final ColorFieldEditor javaTypesColor = new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVATYPES_COLOR,
-				"&Java types color", getFieldEditorParent());
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Java_types_color"), getFieldEditorParent()); //$NON-NLS-1$
+
 		addField(javaTypesColor);
 
 		// Java Keyword Color Prefs
@@ -84,80 +89,105 @@
 		// Java Keyword Color Prefs
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_ENABLED,
-				"&Enable Java keyword coloring", getFieldEditorParent()));
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_Java_keyword_coloring"), getFieldEditorParent())); //$NON-NLS-1$
+
 		final ColorFieldEditor javaKeywordColor = new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_JAVAKEYWORDS_COLOR,
-				"&Java Keyword color", getFieldEditorParent())  ;
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Java_keyword_color"), getFieldEditorParent()); //$NON-NLS-1$
+
 		addField(javaKeywordColor);
 
-		//String Coloring
+		// String Coloring
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_STRINGS_ENABLED,
-				"&Enable String coloring", getFieldEditorParent()));
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_String_coloring"), getFieldEditorParent())); //$NON-NLS-1$
+
 		final ColorFieldEditor stringColor = new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_HIGHLIGHT_STRINGS_COLOR,
-				"&String color", getFieldEditorParent()) ;
+				Messages.getString("GroovyEditorPreferencesPage.String_color"), getFieldEditorParent()); //$NON-NLS-1$
 
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_GROOVYDOC_KEYWORD_ENABLED,
-				"&Enable GroovyDoc keyword coloring", getFieldEditorParent()));
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_GroovyDoc_keyword_coloring"), getFieldEditorParent())); //$NON-NLS-1$
+
 		final ColorFieldEditor groovyDocKeywordColor = new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_GROOVYDOC_KEYWORD_COLOR,
-				"&GroovyDoc keyword color", getFieldEditorParent()) ;
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.GroovyDoc_keyword_color"), getFieldEditorParent()); //$NON-NLS-1$
+
 		addField(groovyDocKeywordColor);
-		
+
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_GROOVYDOC_TAG_ENABLED,
-				"&Enable GroovyDoc tag coloring", getFieldEditorParent()));
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_GroovyDoc_tag_coloring"), getFieldEditorParent())); //$NON-NLS-1$
+
 		final ColorFieldEditor groovyDocTagColor = new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_GROOVYDOC_TAG_COLOR,
-				"&GroovyDoc tag color", getFieldEditorParent()) ;
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.GroovyDoc_tag_color"), getFieldEditorParent()); //$NON-NLS-1$
+
 		addField(groovyDocTagColor);
-		
+
 		addField(new BooleanFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_GROOVYDOC_LINK_ENABLED,
-				"&Enable GroovyDoc link coloring", getFieldEditorParent()));
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_GroovyDoc_link_coloring"), getFieldEditorParent())); //$NON-NLS-1$
+
 		final ColorFieldEditor groovyDocLinkColor = new ColorFieldEditor(
 				PreferenceConstants.GROOVY_EDITOR_GROOVYDOC_LINK_COLOR,
-				"&GroovyDoc link color", getFieldEditorParent()) ;
-		
+				Messages
+						.getString("GroovyEditorPreferencesPage.GroovyDoc_link_color"), getFieldEditorParent()); //$NON-NLS-1$
+
 		addField(groovyDocLinkColor);
-		
-		Button javaColorButton = new Button(super.getFieldEditorParent(), SWT.BUTTON1);
 
-		javaColorButton.setText("Copy Java Color Preferences");
-		javaColorButton.addSelectionListener( new SelectionListener() {
+		addField(new BooleanFieldEditor(
+				PreferenceConstants.GROOVY_EDITOR_FOLDING_ENABLED,
+				Messages
+						.getString("GroovyEditorPreferencesPage.Enable_folding"), getFieldEditorParent())); //$NON-NLS-1$
+
+		Button javaColorButton = new Button(super.getFieldEditorParent(),
+				SWT.BUTTON1);
+
+		javaColorButton
+				.setText(Messages
+						.getString("GroovyEditorPreferencesPage.Copy_Java_Color_Preferences")); //$NON-NLS-1$
+		javaColorButton.addSelectionListener(new SelectionListener() {
 			public void widgetSelected(SelectionEvent arg0) {
 
-				IPreferenceStore store = JavaPlugin.getDefault().getPreferenceStore() ; 
+				IPreferenceStore store = JavaPlugin.getDefault()
+						.getPreferenceStore();
 
-				RGB rgb = PreferenceConverter.getColor(store,IJavaColorConstants.JAVA_STRING);
+				RGB rgb = PreferenceConverter.getColor(store,
+						IJavaColorConstants.JAVA_STRING);
 				stringColor.getColorSelector().setColorValue(rgb);
-				
-				rgb = PreferenceConverter.getColor(store,IJavaColorConstants.JAVA_KEYWORD);
-				javaKeywordColor.getColorSelector().setColorValue(rgb) ;
-				javaTypesColor.getColorSelector().setColorValue(rgb) ;
-				
-				rgb = PreferenceConverter.getColor(store,IJavaColorConstants.JAVA_MULTI_LINE_COMMENT);
+
+				rgb = PreferenceConverter.getColor(store,
+						IJavaColorConstants.JAVA_KEYWORD);
+				javaKeywordColor.getColorSelector().setColorValue(rgb);
+				javaTypesColor.getColorSelector().setColorValue(rgb);
+
+				rgb = PreferenceConverter.getColor(store,
+						IJavaColorConstants.JAVA_MULTI_LINE_COMMENT);
 				commentColor.getColorSelector().setColorValue(rgb);
-				
-				rgb = PreferenceConverter.getColor(store, IJavaColorConstants.JAVADOC_KEYWORD);
+
+				rgb = PreferenceConverter.getColor(store,
+						IJavaColorConstants.JAVADOC_KEYWORD);
 				groovyDocKeywordColor.getColorSelector().setColorValue(rgb);
-				
-				rgb = PreferenceConverter.getColor(store, IJavaColorConstants.JAVADOC_TAG);
+
+				rgb = PreferenceConverter.getColor(store,
+						IJavaColorConstants.JAVADOC_TAG);
 				groovyDocTagColor.getColorSelector().setColorValue(rgb);
-				
-				rgb = PreferenceConverter.getColor(store, IJavaColorConstants.JAVADOC_LINK);
+
+				rgb = PreferenceConverter.getColor(store,
+						IJavaColorConstants.JAVADOC_LINK);
 				groovyDocLinkColor.getColorSelector().setColorValue(rgb);
 			}
+
 			public void widgetDefaultSelected(SelectionEvent arg0) {
 			}
 		});
@@ -172,8 +202,7 @@
 	public void init(IWorkbench workbench) {
 	}
 
-	protected String getPageId()
-	{
+	protected String getPageId() {
 		return this.getClass().getPackage().getName();
 	}
 
#P GroovyEclipseTests
Index: src/org/codehaus/groovy/eclipse/test/ui/FoldingPositionProviderTest.java
===================================================================
--- src/org/codehaus/groovy/eclipse/test/ui/FoldingPositionProviderTest.java	(revision 0)
+++ src/org/codehaus/groovy/eclipse/test/ui/FoldingPositionProviderTest.java	(revision 0)
@@ -0,0 +1,160 @@
+package org.codehaus.groovy.eclipse.test.ui;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.eclipse.core.model.ChangeSet;
+import org.codehaus.groovy.eclipse.core.model.GroovyRuntime;
+import org.codehaus.groovy.eclipse.editor.FoldingPositionProvider;
+import org.codehaus.groovy.eclipse.editor.GroovyDocumentSetupParticipant;
+import org.codehaus.groovy.eclipse.test.Activator;
+import org.codehaus.groovy.eclipse.test.EclipseTestCase;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Test for {@link FoldingPositionProvider}.
+ * 
+ * @author km
+ */
+public class FoldingPositionProviderTest extends EclipseTestCase {
+	/**
+	 * Name of test file.
+	 */
+	private static final String FOLDING_TEST_CLASS_SCRIPT_NAME = "FoldingTestClass.groovy";
+	/**
+	 * Number of folding in test file.
+	 */
+	private static final int INITIAL_FOLDING_POSITIONS = 8;
+
+	@SuppressWarnings("unchecked")
+	private List moduleNodes;
+	private FoldingPositionProvider foldingPositionProvider;
+	private IDocument document;
+
+	@SuppressWarnings("unchecked")
+	public void testUpdatePositions() {
+		foldingPositionProvider.updatePositions(moduleNodes);
+		assertEquals("Expected that initially no positions have been removed!",
+				0, foldingPositionProvider.getRemovedPositions().size());
+		assertEquals(INITIAL_FOLDING_POSITIONS, foldingPositionProvider
+				.getAddedPositions().size());
+		assertEquals(INITIAL_FOLDING_POSITIONS, foldingPositionProvider
+				.getPositions().size());
+
+		// update folding without a change
+		initFoldingPositionProvider(foldingPositionProvider.getPositions());
+		foldingPositionProvider.updatePositions(moduleNodes);
+		assertEquals("Expected that no positions have been removed!", 0,
+				foldingPositionProvider.getRemovedPositions().size());
+		assertEquals("Expected that no positions have been added!", 0,
+				foldingPositionProvider.getAddedPositions().size());
+		assertEquals("Expected same number of positions as before!",
+				INITIAL_FOLDING_POSITIONS, foldingPositionProvider
+						.getPositions().size());
+
+		// remove one class node
+		ModuleNode moduleNode = (ModuleNode) moduleNodes.get(0);
+		List allClasses = moduleNode.getClasses();
+		ClassNode removedClassNode = (ClassNode) allClasses.remove(allClasses
+				.size() - 1);
+		initFoldingPositionProvider(foldingPositionProvider.getPositions());
+		foldingPositionProvider.updatePositions(moduleNodes);
+		assertEquals("Expected that one positions has been removed!", 1,
+				foldingPositionProvider.getRemovedPositions().size());
+		assertEquals("Expected that no positions have been added!", 0,
+				foldingPositionProvider.getAddedPositions().size());
+		assertEquals("Expected that one positions has been removed!",
+				INITIAL_FOLDING_POSITIONS - 1, foldingPositionProvider
+						.getPositions().size());
+
+		// re-add removed class node
+		allClasses.add(removedClassNode);
+		initFoldingPositionProvider(foldingPositionProvider.getPositions());
+		foldingPositionProvider.updatePositions(moduleNodes);
+		assertEquals("Expected that no positions have been removed!", 0,
+				foldingPositionProvider.getRemovedPositions().size());
+		assertEquals("Expected that one position has been added!", 1,
+				foldingPositionProvider.getAddedPositions().size());
+		assertEquals("Expected same number of positions as before!",
+				INITIAL_FOLDING_POSITIONS, foldingPositionProvider
+						.getPositions().size());
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		GroovyRuntime.addGroovyRuntime(testProject.getProject());
+		final URL url = Activator.bundle().getEntry(
+				"/testData/groovyfiles/" + FOLDING_TEST_CLASS_SCRIPT_NAME);
+		InputStream input = null;
+
+		try {
+			input = url.openStream();
+			IFile file = testProject.createGroovyTypeAndPackage("pack1",
+					FOLDING_TEST_CLASS_SCRIPT_NAME, input);
+			final ChangeSet changeSet = model.getGroovyProject(
+					testProject.getProject()).filesForFullBuild();
+			model.getGroovyProject(testProject.getJavaProject())
+					.buildGroovyContent(new NullProgressMonitor(),
+							IncrementalProjectBuilder.FULL_BUILD, changeSet,
+							true);
+			moduleNodes = model.getModuleNodes(file);
+			document = createDocument(file);
+			initFoldingPositionProvider(Collections.EMPTY_SET);
+		} finally {
+			IOUtils.closeQuietly(input);
+		}
+	}
+
+	/**
+	 * Initializes the CUT with specified old positions
+	 * @param oldPositions list of {@link org.eclipse.jface.text.Position}
+	 */
+	@SuppressWarnings("unchecked")
+	private void initFoldingPositionProvider(Set oldPositions) {
+		foldingPositionProvider = new FoldingPositionProvider(document,
+				oldPositions);
+	}
+
+	/**
+	 * Creates a document from the specified file.
+	 * @param file file to create document from
+	 * @return
+	 * @throws IOException
+	 */
+	private IDocument createDocument(IFile file) throws IOException {
+		String contents = getContents(file);
+		IDocument document = new Document(contents);
+		new GroovyDocumentSetupParticipant().setup(document);
+		return document;
+	}
+
+	private String getContents(IFile fileHandle) throws IOException {
+		URL url = fileHandle.getLocationURI().toURL();
+		InputStream inputStream = url.openStream();
+		BufferedReader reader = new BufferedReader(new InputStreamReader(
+				inputStream));
+		try {
+			StringBuilder stringBuffer = new StringBuilder();
+			String line = null;
+			while ((line = reader.readLine()) != null) {
+				stringBuffer.append(line + "\n");
+			}
+			return stringBuffer.toString();
+		} finally {
+			reader.close();
+		}
+	}
+}
Index: testData/groovyfiles/FoldingTestClass.groovy
===================================================================
--- testData/groovyfiles/FoldingTestClass.groovy	(revision 0)
+++ testData/groovyfiles/FoldingTestClass.groovy	(revision 0)
@@ -0,0 +1,28 @@
+import java.util.Map
+import java.awt.List
+import java.awt.Label
+
+/**
+ * 
+ */
+class TestClass1 {
+	/**
+	 * 
+	 */
+	def testMethod1() {
+	}	
+}
+
+import java.util.Hashtable
+import java.util.Hashtable
+
+class TestClass2 {
+	
+}
+
+import java.math.BigDecimal
+
+/**/
+
+class TestClass3 {
+	
\ No newline at end of file

