소스 검색

Moved plugins to separate module.

Alexander Nyßen 14 년 전
부모
커밋
1e330f450f
17개의 변경된 파일1922개의 추가작업 그리고 0개의 파일을 삭제
  1. 7 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/.classpath
  2. 28 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/.project
  3. 8 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/.settings/org.eclipse.jdt.core.prefs
  4. 13 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/META-INF/MANIFEST.MF
  5. 4 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/build.properties
  6. 38 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/directedit/IXtextAwareEditPart.java
  7. 683 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/directedit/XtextDirectEditManager.java
  8. 120 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/directedit/XtextLabelEditPart.java
  9. 82 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/experimental/StyledLabel.java
  10. 116 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/viewers/XtextCellEditorEx.java
  11. 7 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/.classpath
  12. 28 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/.project
  13. 8 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/.settings/org.eclipse.jdt.core.prefs
  14. 14 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/META-INF/MANIFEST.MF
  15. 4 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/build.properties
  16. 471 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/src/de/itemis/xtext/utils/jface/viewers/StyledTextCellEditor.java
  17. 291 0
      de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/src/de/itemis/xtext/utils/jface/viewers/XtextCellEditor.java

+ 7 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/.classpath

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

+ 28 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/.project

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>de.itemis.xtext.utils.gmf</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

+ 8 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,8 @@
+#Mon Mar 28 13:08:10 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5

+ 13 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/META-INF/MANIFEST.MF

@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Xtext GMF Utils
+Bundle-SymbolicName: de.itemis.xtext.utils.gmf
+Bundle-Version: 1.0.0.qualifier
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.xtext.ui;bundle-version="[1.0.1,2.0.0)",
+ de.itemis.xtext.utils.jface;bundle-version="[1.0.0,2.0.0)",
+ org.eclipse.gmf.runtime.diagram.ui;bundle-version="[1.4.0,2.0.0)"
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Export-Package: de.itemis.xtext.utils.gmf.directedit,
+ de.itemis.xtext.utils.gmf.viewers
+Bundle-Vendor: itemis AG

+ 4 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/build.properties

@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .

+ 38 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/directedit/IXtextAwareEditPart.java

@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2011 itemis AG 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:
+ * 	Andreas Muelder - initial API and implementation
+ * 
+ */
+package de.itemis.xtext.utils.gmf.directedit;
+
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+
+/**
+ * 
+ * Implemented by EditParts, which contain text that should be edited via Xtext.
+ * The interface provides a subset of the methods delivered by
+ * {@link org.eclipse.gmf.runtime.diagram.ui.editparts.ITextAwareEditPart}.
+ * 
+ * @author muelder
+ * 
+ */
+public interface IXtextAwareEditPart extends IGraphicalEditPart {
+
+	/**
+	 * Returns the text to edit
+	 */
+	String getEditText();
+
+	/**
+	 * Called when edit text was modified and edit part should update itself to
+	 * reflect the changes.
+	 */
+	public void setLabelText(String text);
+
+}

+ 683 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/directedit/XtextDirectEditManager.java

@@ -0,0 +1,683 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2010 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 
+ *    Dmitry Stadnik (Borland) - contribution for bugzilla 135694
+ ****************************************************************************/
+
+package de.itemis.xtext.utils.gmf.directedit;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.draw2d.AncestorListener;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.TextUtilities;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.gef.tools.CellEditorLocator;
+import org.eclipse.gef.tools.DirectEditManager;
+import org.eclipse.gmf.runtime.common.core.util.Log;
+import org.eclipse.gmf.runtime.common.core.util.Trace;
+import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIDebugOptions;
+import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIPlugin;
+import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIStatusCodes;
+import org.eclipse.gmf.runtime.diagram.ui.label.ILabelDelegate;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.WrappingLabel;
+import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
+import org.eclipse.gmf.runtime.gef.ui.internal.parts.TextCellEditorEx;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.DeviceResourceException;
+import org.eclipse.jface.resource.FontDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+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.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.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.part.CellEditorActionHandler;
+
+import com.google.inject.Injector;
+
+import de.itemis.xtext.utils.gmf.viewers.XtextCellEditorEx;
+
+/**
+ * @author melaasar
+ */
+@SuppressWarnings("restriction")
+public class XtextDirectEditManager extends DirectEditManager {
+
+	/**
+	 * content assist background color
+	 */
+	private Color proposalPopupBackgroundColor = null;
+
+	/**
+	 * content assist foreground color
+	 */
+	private Color proposalPopupForegroundColor = null;
+
+	private boolean committed = false;
+
+	/**
+	 * flag used to avoid unhooking listeners twice if the UI thread is blocked
+	 */
+	private boolean listenersAttached = true;
+
+	/** String buffer to hold initial characters * */
+	private StringBuffer initialString = new StringBuffer();
+
+	/**
+	 * Cache the font descriptor when a font is created so that it can be
+	 * disposed later.
+	 */
+	private List<FontDescriptor> cachedFontDescriptors = new ArrayList<FontDescriptor>();
+
+	private IActionBars actionBars;
+
+	private CellEditorActionHandler actionHandler;
+
+	private IAction copy, cut, paste, undo, redo, find, selectAll, delete;
+
+	private Font zoomLevelFont = null;
+
+	/**
+	 * The superclass only relocates the cell editor when the location of the
+	 * editpart's figure moves, but we need to also relocate the cell editor
+	 * when the text figure's location changes.
+	 */
+	private AncestorListener textFigureListener;
+
+	/**
+	 * Cache locally so we can check if the user specified an editorType.
+	 */
+	private Class<?> editorType;
+
+	private final Injector injector;
+	private final int style;
+
+	/**
+	 * constructor
+	 * 
+	 * @param source
+	 *            <code>GraphicalEditPart</code> to support direct edit of. The
+	 *            figure of the <code>source</code> edit part must be of type
+	 *            <code>WrapLabel</code>.
+	 */
+	public XtextDirectEditManager(IXtextAwareEditPart source, Injector injector, int style) {
+		this(source, null, getTextCellEditorLocator(source), injector, style);
+	}
+
+	/**
+	 * @param source
+	 * @param editorType
+	 * @param locator
+	 */
+	public XtextDirectEditManager(GraphicalEditPart source,
+			Class<?> editorType, CellEditorLocator locator, Injector injector,
+			int style) {
+		super(source, editorType, locator);
+		this.editorType = editorType;
+		this.injector = injector;
+		this.style = style;
+	}
+
+	/**
+	 * @param source
+	 *            the <code>ITextAwareEditPart</code> to determine the cell
+	 *            editor for
+	 * @return the <code>CellEditorLocator</code> that is appropriate for the
+	 *         source <code>EditPart</code>
+	 */
+	public static CellEditorLocator getTextCellEditorLocator(
+			final IXtextAwareEditPart source) {
+
+		final ILabelDelegate label = (ILabelDelegate) source
+				.getAdapter(ILabelDelegate.class);
+		if (label != null) {
+			return new CellEditorLocator() {
+
+				public void relocate(CellEditor celleditor) {
+					StyledText text = (StyledText) celleditor.getControl();
+
+					Rectangle rect = label.getTextBounds().getCopy();
+					if (label.getText().length() <= 0) {
+						// if there is no text, let's assume a default size
+						// of one character because it looks silly when the cell
+						// editor is tiny.
+						rect.setSize(TextUtilities.INSTANCE.getTextExtents(
+								"a", text.getFont())); //$NON-NLS-1$
+
+						if (label.isTextWrapOn()) {
+							// adjust the location of the cell editor based on
+							// text
+							// justification (i.e. where the cursor will be
+							if (label.getTextJustification() == PositionConstants.RIGHT) {
+								rect.translate(-rect.width, 0);
+							} else if (label.getTextJustification() == PositionConstants.CENTER) {
+								rect.translate(-rect.width / 2, 0);
+							}
+						}
+					}
+
+					if (!text.getFont().isDisposed()) {
+						// Font may be disposed if the locator is called while
+						// this manager is being brought down in which case the
+						// calls below that use the font will result in an
+						// exception.
+						if (label.isTextWrapOn()) {
+							// When zoomed in, the height of this rectangle is
+							// not
+							// sufficient because the text is shifted downwards
+							// a
+							// little bit. Add some to the height to compensate
+							// for
+							// this. I'm not sure why this is happening, but I
+							// can
+							// see the text shifting down even in a label on a
+							// GEF
+							// logic diagram when zoomed into 400%.
+							int charHeight = FigureUtilities.getFontMetrics(
+									text.getFont()).getHeight();
+							rect.resize(0, charHeight / 2);
+						} else {
+
+							rect.setSize(new Dimension(text.computeSize(
+									SWT.DEFAULT, SWT.DEFAULT)));
+
+							// If SWT.WRAP is not passed in as a style of the
+							// TextCellEditor, then for some reason the first
+							// character disappears upon entering the second
+							// character. This should be investigated and an
+							// SWT bug logged.
+							int avr = FigureUtilities.getFontMetrics(
+									text.getFont()).getAverageCharWidth();
+							rect.setSize(new Dimension(text.computeSize(
+									SWT.DEFAULT, SWT.DEFAULT)).expand(avr * 2,
+									0));
+						}
+					}
+
+					org.eclipse.swt.graphics.Rectangle newRect = text
+							.computeTrim(rect.x, rect.y, rect.width,
+									rect.height);
+					if (!newRect.equals(text.getBounds())) {
+						text.setBounds(newRect.x, newRect.y, newRect.width,
+								newRect.height);
+					}
+				}
+			};
+		}
+
+		// return a default figure locator
+		return new CellEditorLocator() {
+			public void relocate(CellEditor celleditor) {
+				StyledText text = (StyledText) celleditor.getControl();
+				Rectangle rect = source.getFigure().getBounds().getCopy();
+				source.getFigure().translateToAbsolute(rect);
+				if (!rect.equals(new Rectangle(text.getBounds()))) {
+					text.setBounds(rect.x, rect.y, rect.width, rect.height);
+				}
+			}
+		};
+	}
+
+	/**
+	 * This method is overridden so that the editor class can have a style as
+	 * the style needs to be passed into the editor class when it is created. It
+	 * will default to the super behavior if an <code>editorType</code> was
+	 * passed into the constructor.
+	 * 
+	 * @since 2.1
+	 */
+	protected CellEditor createCellEditorOn(Composite composite) {
+
+		// if the client has overridden this class and provided their own editor
+		// type, then we should use that
+		if (editorType != null) {
+			return super.createCellEditorOn(composite);
+		}
+
+		XtextCellEditorEx editor = new XtextCellEditorEx(style);
+		injector.injectMembers(editor);
+		editor.create(composite);
+		return editor;
+	}
+
+	/**
+	 * Given a label figure object, this will calculate the correct Font needed
+	 * to display into screen coordinates, taking into account the current
+	 * mapmode. This will typically be used by direct edit cell editors that
+	 * need to display independent of the zoom or any coordinate mapping that is
+	 * taking place on the drawing surface.
+	 * 
+	 * @param label
+	 *            the label to use for the font calculation
+	 * @return the <code>Font</code> that is scaled to the screen coordinates.
+	 *         Note: the returned <code>Font</code> should not be disposed since
+	 *         it is cached by a common resource manager.
+	 */
+	protected Font getScaledFont(IFigure label) {
+		Font scaledFont = label.getFont();
+		FontData data = scaledFont.getFontData()[0];
+		Dimension fontSize = new Dimension(0, MapModeUtil.getMapMode(label)
+				.DPtoLP(data.getHeight()));
+		label.translateToAbsolute(fontSize);
+
+		if (Math.abs(data.getHeight() - fontSize.height) < 2)
+			fontSize.height = data.getHeight();
+
+		try {
+			FontDescriptor fontDescriptor = FontDescriptor.createFrom(data);
+			cachedFontDescriptors.add(fontDescriptor);
+			return getResourceManager().createFont(fontDescriptor);
+		} catch (DeviceResourceException e) {
+			Trace.catching(DiagramUIPlugin.getInstance(),
+					DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
+					"getScaledFont", e); //$NON-NLS-1$
+			Log.error(DiagramUIPlugin.getInstance(),
+					DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING,
+					"getScaledFont", e); //$NON-NLS-1$
+		}
+		return JFaceResources.getDefaultFont();
+	}
+
+	protected void initCellEditor() {
+		committed = false;
+
+		// Get the Text Compartments Edit Part
+
+		setEditText(getEditPart().getEditText());
+
+		IFigure label = getEditPart().getFigure();
+		Assert.isNotNull(label);
+		StyledText text = (StyledText) getCellEditor().getControl();
+		// scale the font accordingly to the zoom level
+		text.setFont(getScaledFont(label));
+
+		// Hook the cell editor's copy/paste actions to the actionBars so that
+		// they can
+		// be invoked via keyboard shortcuts.
+		actionBars = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+				.getActivePage().getActiveEditor().getEditorSite()
+				.getActionBars();
+		saveCurrentActions(actionBars);
+		actionHandler = new CellEditorActionHandler(actionBars);
+		actionHandler.addCellEditor(getCellEditor());
+		actionBars.updateActionBars();
+	}
+
+	/**
+	 * @see org.eclipse.gef.tools.DirectEditManager#commit()
+	 */
+	protected void commit() {
+		Shell activeShell = Display.getCurrent().getActiveShell();
+		if (activeShell != null
+				&& getCellEditor().getControl().getShell()
+						.equals(activeShell.getParent())) {
+			Control[] children = activeShell.getChildren();
+			if (children.length == 1 && children[0] instanceof Table) {
+				/*
+				 * CONTENT ASSIST: focus is lost to the content assist pop up -
+				 * stay in focus
+				 */
+				getCellEditor().getControl().setVisible(true);
+				((XtextCellEditorEx) getCellEditor()).setDeactivationLock(true);
+				return;
+			}
+		}
+
+		// content assist hacks
+		if (committed) {
+			bringDown();
+			return;
+		}
+		committed = true;
+		super.commit();
+	}
+
+	/**
+	 * @see org.eclipse.gef.tools.DirectEditManager#bringDown()
+	 */
+	protected void bringDown() {
+		if (proposalPopupForegroundColor != null) {
+			proposalPopupForegroundColor.dispose();
+			proposalPopupForegroundColor = null;
+		}
+		if (proposalPopupBackgroundColor != null) {
+			proposalPopupBackgroundColor.dispose();
+			proposalPopupBackgroundColor = null;
+		}
+
+		// myee - RATLC00523014: crashes when queued in asyncExec()
+		eraseFeedback();
+
+		initialString = new StringBuffer();
+
+		Display.getCurrent().asyncExec(new Runnable() {
+
+			public void run() {
+				// Content Assist hack - allow proper cleanup on childen
+				// controls
+				XtextDirectEditManager.super.bringDown();
+			}
+		});
+
+		for (Iterator<FontDescriptor> iter = cachedFontDescriptors.iterator(); iter
+				.hasNext();) {
+			getResourceManager().destroyFont((FontDescriptor) iter.next());
+		}
+		cachedFontDescriptors.clear();
+
+		if (actionHandler != null) {
+			actionHandler.dispose();
+			actionHandler = null;
+		}
+		if (actionBars != null) {
+			restoreSavedActions(actionBars);
+			actionBars.updateActionBars();
+			actionBars = null;
+		}
+	}
+
+	/**
+	 * This method is used to set the cell editors text
+	 * 
+	 * @param toEdit
+	 *            String to be set in the cell editor
+	 */
+	public void setEditText(String toEdit) {
+
+		// Get the cell editor
+		CellEditor cellEditor = getCellEditor();
+
+		// IF the cell editor doesn't exist yet...
+		if (cellEditor == null) {
+			// Do nothing
+			return;
+		}
+
+		// Get the Text Compartment Edit Part
+		IXtextAwareEditPart textEP = (IXtextAwareEditPart) getEditPart();
+
+		// Get the Text control
+		StyledText textControl = (StyledText) cellEditor.getControl();
+
+		// Set the Figures text
+		textEP.setLabelText(toEdit);
+
+		// See RATLC00522324
+		if (cellEditor instanceof TextCellEditorEx) {
+			((TextCellEditorEx) cellEditor)
+					.setValueAndProcessEditOccured(toEdit);
+		} else {
+			cellEditor.setValue(toEdit);
+		}
+
+		// Set the controls text and position the caret at the end of the text
+		textControl.setSelection(toEdit.length());
+	}
+
+	/**
+	 * Performs show and sets the edit string to be the initial character or
+	 * string
+	 * 
+	 * @param initialChar
+	 */
+	public void show(char initialChar) {
+		initialString = initialString.append(initialChar);
+		show();
+		if (SWT.getPlatform() != "carbon") { //$NON-NLS-1$ 
+			// Set the cell editor text to the initial character
+			setEditText(initialString.toString());
+		}
+	}
+
+	/**
+	 * This method obtains the fonts that are being used by the figure at its
+	 * zoom level.
+	 * 
+	 * @param gep
+	 *            the associated <code>GraphicalEditPart</code> of the figure
+	 * @param actualFont
+	 *            font being used by the figure
+	 * @param display
+	 * @return <code>actualFont</code> if zoom level is 1.0 (or when there's an
+	 *         error), new Font otherwise.
+	 */
+	private Font getZoomLevelFont(Font actualFont, Display display) {
+		Object zoom = getEditPart().getViewer().getProperty(
+				ZoomManager.class.toString());
+
+		if (zoom != null) {
+			double zoomLevel = ((ZoomManager) zoom).getZoom();
+
+			if (zoomLevel == 1.0f)
+				return actualFont;
+
+			FontData[] fd = new FontData[actualFont.getFontData().length];
+			FontData tempFD = null;
+
+			for (int i = 0; i < fd.length; i++) {
+				tempFD = actualFont.getFontData()[i];
+
+				fd[i] = new FontData(tempFD.getName(),
+						(int) (zoomLevel * tempFD.getHeight()),
+						tempFD.getStyle());
+			}
+
+			try {
+				FontDescriptor fontDescriptor = FontDescriptor.createFrom(fd);
+				cachedFontDescriptors.add(fontDescriptor);
+				return getResourceManager().createFont(fontDescriptor);
+			} catch (DeviceResourceException e) {
+				Trace.catching(DiagramUIPlugin.getInstance(),
+						DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
+						"getZoomLevelFonts", e); //$NON-NLS-1$
+				Log.error(DiagramUIPlugin.getInstance(),
+						DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING,
+						"getZoomLevelFonts", e); //$NON-NLS-1$
+
+				return actualFont;
+			}
+		} else
+			return actualFont;
+	}
+
+	public void show() {
+		super.show();
+
+		IFigure fig = getEditPart().getFigure();
+
+		Control control = getCellEditor().getControl();
+		this.zoomLevelFont = getZoomLevelFont(fig.getFont(),
+				control.getDisplay());
+
+		control.setFont(this.zoomLevelFont);
+
+		// since the font's have been resized, we need to resize the Text
+		// control...
+		getLocator().relocate(getCellEditor());
+
+	}
+
+	/**
+	 * 
+	 * Performs show and sends an extra mouse click to the point location so
+	 * that cursor appears at the mouse click point
+	 * 
+	 * The Text control does not allow for the cursor to appear at point
+	 * location but at a character location
+	 * 
+	 * @param location
+	 */
+	public void show(Point location) {
+		show();
+		sendClickToCellEditor(location);
+	}
+
+	private void sendClickToCellEditor(final Point location) {
+		// make sure the diagram doesn't receive the click event..
+		getCellEditor().getControl().setCapture(true);
+
+		if (getCellEditor() != null
+				&& getCellEditor().getControl().getBounds().contains(location))
+			sendMouseClick(location);
+	}
+
+	/**
+	 * 
+	 * Sends a SWT MouseUp and MouseDown event to the point location to the
+	 * current Display
+	 * 
+	 * @param location
+	 */
+	private void sendMouseClick(final Point location) {
+
+		final Display currDisplay = Display.getCurrent();
+		currDisplay.asyncExec(new Runnable() {
+			public void run() {
+				Event event;
+				event = new Event();
+				event.type = SWT.MouseDown;
+				event.button = 1;
+				event.x = location.x;
+				event.y = location.y;
+				currDisplay.post(event);
+				event.type = SWT.MouseUp;
+				currDisplay.post(event);
+			}
+		});
+	}
+
+	protected void hookListeners() {
+		super.hookListeners();
+
+		// TODO: This gets around the problem of the cell editor not growing big
+		// enough when in autosize mode because it doesn't listen to textflow
+		// size changes. The superclass should be modified to not assume we want
+		// to listen to the editpart's figure.
+		ILabelDelegate label = (ILabelDelegate) getEditPart().getAdapter(
+				ILabelDelegate.class);
+		if (label != null && getEditPart().getFigure() instanceof WrappingLabel) {
+
+			textFigureListener = new AncestorListener.Stub() {
+
+				public void ancestorMoved(IFigure ancestor) {
+					getLocator().relocate(getCellEditor());
+				}
+			};
+			((IFigure) ((WrappingLabel) getEditPart().getFigure())
+					.getTextFigure().getChildren().get(0))
+					.addAncestorListener(textFigureListener);
+		}
+	}
+
+	/*
+	 * Overrides super unhookListeners to set listeners attached flag This
+	 * method prevents unhooking listeners twice if the UI thread is blocked.
+	 * For example, a validation dialog may block the thread
+	 */
+	protected void unhookListeners() {
+		if (listenersAttached) {
+			listenersAttached = false;
+			super.unhookListeners();
+
+			ILabelDelegate label = (ILabelDelegate) getEditPart().getAdapter(
+					ILabelDelegate.class);
+			if (label != null && textFigureListener != null) {
+				((IFigure) ((WrappingLabel) getEditPart().getFigure())
+						.getTextFigure().getChildren().get(0))
+						.removeAncestorListener(textFigureListener);
+				textFigureListener = null;
+			}
+		}
+	}
+
+	/*
+	 * Sets the listeners attached flag if the cell editor exists
+	 */
+	protected void setCellEditor(CellEditor editor) {
+		super.setCellEditor(editor);
+		if (editor != null) {
+			listenersAttached = true;
+		}
+	}
+
+	public void showFeedback() {
+		try {
+			getEditPart().getRoot();
+			super.showFeedback();
+		} catch (Exception e) {
+			// TODO: handle exception
+		}
+	}
+	
+	@Override
+	protected IXtextAwareEditPart getEditPart() {
+		return (IXtextAwareEditPart)super.getEditPart();
+	}
+
+	/**
+	 * Gets the resource manager to remember the resources allocated for this
+	 * graphical viewer. All resources will be disposed when the graphical
+	 * viewer is closed if they have not already been disposed.
+	 * 
+	 * @return
+	 */
+	protected ResourceManager getResourceManager() {
+		return ((DiagramGraphicalViewer) getEditPart().getViewer())
+				.getResourceManager();
+	}
+
+	private void saveCurrentActions(IActionBars _actionBars) {
+		copy = _actionBars.getGlobalActionHandler(ActionFactory.COPY.getId());
+		paste = _actionBars.getGlobalActionHandler(ActionFactory.PASTE.getId());
+		delete = _actionBars.getGlobalActionHandler(ActionFactory.DELETE
+				.getId());
+		selectAll = _actionBars.getGlobalActionHandler(ActionFactory.SELECT_ALL
+				.getId());
+		cut = _actionBars.getGlobalActionHandler(ActionFactory.CUT.getId());
+		find = _actionBars.getGlobalActionHandler(ActionFactory.FIND.getId());
+		undo = _actionBars.getGlobalActionHandler(ActionFactory.UNDO.getId());
+		redo = _actionBars.getGlobalActionHandler(ActionFactory.REDO.getId());
+	}
+
+	private void restoreSavedActions(IActionBars _actionBars) {
+		_actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copy);
+		_actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), paste);
+		_actionBars
+				.setGlobalActionHandler(ActionFactory.DELETE.getId(), delete);
+		_actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
+				selectAll);
+		_actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(), cut);
+		_actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(), find);
+		_actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undo);
+		_actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), redo);
+	}
+
+}

+ 120 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/directedit/XtextLabelEditPart.java

@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2011 itemis AG 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:
+ * 	itemis AG - initial API and implementation
+ * 
+ */
+package de.itemis.xtext.utils.gmf.directedit;
+
+import static org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants.REQ_DIRECTEDIT_EXTENDEDDATA_INITIAL_CHAR;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.tools.DirectEditManager;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.tools.TextDirectEditManager;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.LabelEx;
+import org.eclipse.gmf.runtime.notation.ShapeStyle;
+import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.swt.graphics.Color;
+
+/**
+ * Abstract base implementation for all {@link LabelEditPart}s that use Xtext
+ * for direct editing.
+ * 
+ * 
+ * @author muelder
+ * 
+ */
+public abstract class XtextLabelEditPart extends LabelEditPart implements
+		IXtextAwareEditPart {
+
+	private DirectEditManager manager;
+
+	protected abstract DirectEditManager createXTextDirectEditManager();
+
+	public XtextLabelEditPart(View view) {
+		super(view);
+	}
+
+	@Override
+	protected IFigure createFigure() {
+		LabelEx label = new LabelEx();
+		label.setLabelAlignment(PositionConstants.LEFT);
+		label.setTextAlignment(PositionConstants.TOP);
+		return label;
+	}
+
+	@Override
+	public LabelEx getFigure() {
+		return (LabelEx) super.getFigure();
+	}
+
+	public void setLabelText(String text) {
+		getFigure().setText(text);
+	}
+
+	@Override
+	protected void refreshVisuals() {
+		super.refreshVisuals();
+		refreshFont();
+		refreshFontColor();
+		updateLabelText();
+	}
+
+	private void updateLabelText() {
+		getFigure().setText(getEditText());
+	}
+
+	@Override
+	protected void setFontColor(Color color) {
+		getFigure().setForegroundColor(color);
+	}
+
+	@Override
+	protected void handleNotificationEvent(Notification notification) {
+		if (notification.getNotifier() instanceof ShapeStyle) {
+			refreshVisuals();
+		}
+		super.handleNotificationEvent(notification);
+	}
+
+	@Override
+	protected void performDirectEditRequest(Request request) {
+		if (manager == null) {
+			manager = createXTextDirectEditManager();
+		}
+		final Request theRequest = request;
+		try {
+			getEditingDomain().runExclusive(new Runnable() {
+
+				public void run() {
+					if (isActive()) {
+						if (theRequest.getExtendedData().get(
+								REQ_DIRECTEDIT_EXTENDEDDATA_INITIAL_CHAR) instanceof Character
+								&& manager instanceof TextDirectEditManager) {
+							Character initialChar = (Character) theRequest
+									.getExtendedData()
+									.get(REQ_DIRECTEDIT_EXTENDEDDATA_INITIAL_CHAR);
+
+							((TextDirectEditManager) manager).show(initialChar);
+
+						} else {
+							manager.show();
+						}
+					}
+				}
+			});
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+	}
+
+}

+ 82 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/experimental/StyledLabel.java

@@ -0,0 +1,82 @@
+package de.itemis.xtext.utils.gmf.experimental;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.LabelEx;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * 
+ * @author muelder
+ * 
+ */
+public class StyledLabel extends LabelEx {
+
+	private StyleRange[] ranges = new StyleRange[0];
+
+	private Image image;
+
+	public StyledLabel() {
+	}
+
+	public StyleRange[] getRanges() {
+		return ranges;
+	}
+
+	public void setRanges(StyleRange[] ranges) {
+		this.ranges = ranges;
+	}
+
+	protected void updateImage() {
+		Rectangle bounds = getBounds();
+		if (bounds.width <= 0 || bounds.height <= 0)
+			return;
+		TextLayout layout = new TextLayout(Display.getDefault());
+		//layout.setFont(getFont());
+		layout.setText(getText());
+		for (StyleRange styleRange : ranges) {
+			//styleRange.background = ColorConstants.white;
+			layout.setStyle(styleRange, styleRange.start, styleRange.start
+					+ styleRange.length);
+		}
+		if (image != null && !image.isDisposed()) {
+			image.dispose();
+		}
+		image = new Image(Display.getDefault(), bounds.width, bounds.height);
+		
+		GC gc = new GC(image);
+		gc.setBackground(ColorConstants.red);
+		layout.draw(gc, 0, 0);
+		image.getImageData().transparentPixel = image.getImageData().palette
+				.getPixel(ColorConstants.white.getRGB());
+
+		
+		layout.dispose();
+		gc.dispose();
+	}
+
+	protected void paintFigure(Graphics graphics) {
+		Rectangle bounds = getBounds();
+		graphics.translate(bounds.x, bounds.y);
+		updateImage();
+
+		if (image == null || ranges == null || ranges.length == 0 || isOpaque()) {
+			return;
+		}
+
+		if (getIcon() != null)
+			graphics.drawImage(getIcon(), getIconLocation());
+//		if (!isEnabled()) {
+//			graphics.translate(1, 1);
+//			graphics.drawImage(image, getTextLocation());
+//			graphics.translate(-1, -1);
+//		}
+		graphics.drawImage(image, getTextLocation());
+		graphics.translate(-bounds.x, -bounds.y);
+	}
+}

+ 116 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.gmf/src/de/itemis/xtext/utils/gmf/viewers/XtextCellEditorEx.java

@@ -0,0 +1,116 @@
+/******************************************************************************
+ * Copyright (c) 2002, 2004 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 de.itemis.xtext.utils.gmf.viewers;
+
+import de.itemis.xtext.utils.jface.viewers.XtextCellEditor;
+
+
+
+/**
+ * This is a copy of TextCellEditorEx, only the super class has been changed to
+ * {@link XtextCellEditor}
+ * 
+ * @author muelder
+ * 
+ */
+public class XtextCellEditorEx extends XtextCellEditor {
+
+	private Object originalValue;
+	private boolean deactivationLock = false;
+
+	public XtextCellEditorEx(int style) {
+		super(style);
+	}
+
+	/**
+	 * This will be used when an edit has occurred by a ModifyEvent has been
+	 * been send. Will call #setValue(Object) but will also call
+	 * editOccured(null) to make sure that the dirty flag is set probably and
+	 * that any listeners are informed about the changed.
+	 * 
+	 * @param value
+	 *            Value to set the cell editor to.
+	 * 
+	 *            Note: This happens address defect RATLC00522324. For our
+	 *            topgraphical edit parts we delagate the direct edit request to
+	 *            a primary edit part and set focus on that. The issue is that
+	 *            if the user has typed in an initial character when setting
+	 *            focus to the edit part, which typically is a
+	 *            TextCompartmentEditPart then setting that intial value does
+	 *            not fire the necessary change events that need to occur in
+	 *            order for that value to be recongnized. If you don't use this
+	 *            method then the result is that if you just type in the initial
+	 *            character and that is it then the text compartment loses focus
+	 *            then the value will not be saved. This is because setting the
+	 *            value of the cell doesn't think its value has changed since
+	 *            the first character is not recongized as a change.
+	 */
+	public void setValueAndProcessEditOccured(Object value) {
+		setValue(value);
+		// do the processing to ensure if we exit the cell then
+		// value will be applied.
+		editOccured(null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.CellEditor#doSetValue(java.lang.Object)
+	 */
+	protected void doSetValue(Object value) {
+		if (originalValue == null)
+			originalValue = value;
+		super.doSetValue(value);
+	}
+
+	/**
+	 * @return boolean value specifying whether or not the value has been
+	 *         changed
+	 */
+	public boolean hasValueChanged() {
+		if (getValue() == null)
+			return originalValue != null;
+		return !getValue().equals(originalValue);
+	}
+
+	/*
+	 * Runs super deactivate unless it has been locked and otherwise unlocks
+	 * deactivation
+	 * 
+	 * @see org.eclipse.jface.viewers.CellEditor#deactivate()
+	 */
+	public void deactivate() {
+		if (!isDeactivationLocked())
+			super.deactivate();
+		setDeactivationLock(false);
+	}
+
+	/**
+	 * Returns true if deactivation has been locked
+	 * 
+	 * @return
+	 */
+	public boolean isDeactivationLocked() {
+		return deactivationLock;
+	}
+
+	/**
+	 * Sets deactivation lock so that the cell editor does not perform
+	 * deactivate
+	 * 
+	 * @param deactivationLock
+	 */
+	public void setDeactivationLock(boolean deactivationLock) {
+		this.deactivationLock = deactivationLock;
+	}
+
+}

+ 7 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/.classpath

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

+ 28 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/.project

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>de.itemis.xtext.utils.jface</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

+ 8 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,8 @@
+#Mon Apr 11 10:19:08 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5

+ 14 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/META-INF/MANIFEST.MF

@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: de.itemis.xtext.utils.jface
+Bundle-SymbolicName: de.itemis.xtext.utils.jface
+Bundle-Version: 1.0.0.qualifier
+Bundle-Vendor: itemis AG
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Require-Bundle: org.eclipse.jface;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.jface.text;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.emf.common;bundle-version="[2.6.0,3.0.0)",
+ org.eclipse.xtext.ui;bundle-version="[1.0.1,2.0.0)",
+ org.eclipse.ui.ide;bundle-version="[3.6.0,4.0.0)"
+Export-Package: de.itemis.xtext.utils.jface.viewers

+ 4 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/build.properties

@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .

+ 471 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/src/de/itemis/xtext/utils/jface/viewers/StyledTextCellEditor.java

@@ -0,0 +1,471 @@
+
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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
+ *     Tom Eicher <eclipse@tom.eicher.name> - fix minimum width
+ *******************************************************************************/
+package de.itemis.xtext.utils.jface.viewers;
+
+import java.text.MessageFormat;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * This is a complete copy of {@link TextCellEditor}. Only the control is
+ * changed from {@link Text} to {@link StyledText}, with some small
+ * modifications.
+ * 
+ * @author muelder
+ * 
+ */
+public class StyledTextCellEditor extends CellEditor {
+
+	/**
+	 * The text control; initially <code>null</code>.
+	 */
+	protected StyledText text;
+
+	private ModifyListener modifyListener;
+
+	/**
+	 * State information for updating action enablement
+	 */
+	private boolean isSelection = false;
+
+	private boolean isDeleteable = false;
+
+	private boolean isSelectable = false;
+
+	/**
+	 * Creates a new text string cell editor with no control The cell editor
+	 * value is the string itself, which is initially the empty string.
+	 * Initially, the cell editor has no cell validator.
+	 * 
+	 * @since 2.1
+	 */
+	public StyledTextCellEditor() {
+	}
+
+	/**
+	 * Checks to see if the "deletable" state (can delete/ nothing to delete)
+	 * has changed and if so fire an enablement changed notification.
+	 */
+	private void checkDeleteable() {
+		boolean oldIsDeleteable = isDeleteable;
+		isDeleteable = isDeleteEnabled();
+		if (oldIsDeleteable != isDeleteable) {
+			fireEnablementChanged(DELETE);
+		}
+	}
+
+	/**
+	 * Checks to see if the "selectable" state (can select) has changed and if
+	 * so fire an enablement changed notification.
+	 */
+	private void checkSelectable() {
+		boolean oldIsSelectable = isSelectable;
+		isSelectable = isSelectAllEnabled();
+		if (oldIsSelectable != isSelectable) {
+			fireEnablementChanged(SELECT_ALL);
+		}
+	}
+
+	/**
+	 * Checks to see if the selection state (selection / no selection) has
+	 * changed and if so fire an enablement changed notification.
+	 */
+	private void checkSelection() {
+		boolean oldIsSelection = isSelection;
+		isSelection = text.getSelectionCount() > 0;
+		if (oldIsSelection != isSelection) {
+			fireEnablementChanged(COPY);
+			fireEnablementChanged(CUT);
+		}
+	}
+
+	/*
+	 * (non-Javadoc) Method declared on CellEditor.
+	 */
+	protected Control createControl(Composite parent) {
+		text = createStyledText(parent);
+		text.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				handleDefaultSelection(e);
+			}
+		});
+		text.addKeyListener(new KeyAdapter() {
+			// hook key pressed - see PR 14201
+			public void keyPressed(KeyEvent e) {
+				keyReleaseOccured(e);
+
+				// as a result of processing the above call, clients may have
+				// disposed this cell editor
+				if ((getControl() == null) || getControl().isDisposed()) {
+					return;
+				}
+				checkSelection(); // see explanation below
+				checkDeleteable();
+				checkSelectable();
+			}
+		});
+		text.addTraverseListener(new TraverseListener() {
+			public void keyTraversed(TraverseEvent e) {
+				if (e.detail == SWT.TRAVERSE_ESCAPE
+						|| e.detail == SWT.TRAVERSE_RETURN) {
+					e.doit = false;
+				}
+			}
+		});
+		// We really want a selection listener but it is not supported so we
+		// use a key listener and a mouse listener to know when selection
+		// changes
+		// may have occurred
+		text.addMouseListener(new MouseAdapter() {
+			public void mouseUp(MouseEvent e) {
+				checkSelection();
+				checkDeleteable();
+				checkSelectable();
+			}
+		});
+		text.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				StyledTextCellEditor.this.focusLost();
+			}
+		});
+		text.setFont(parent.getFont());
+		text.setBackground(parent.getBackground());
+		text.setText("");//$NON-NLS-1$
+		text.addModifyListener(getModifyListener());
+		return text;
+	}
+
+	/**
+	 * Hook changing creation of Control
+	 * 
+	 * @param parent
+	 * @return
+	 */
+	protected StyledText createStyledText(Composite parent) {
+		return new StyledText(parent, getStyle());
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> framework method returns the text string.
+	 * 
+	 * @return the text string
+	 */
+	protected Object doGetValue() {
+		return text.getText();
+	}
+
+	/*
+	 * (non-Javadoc) Method declared on CellEditor.
+	 */
+	protected void doSetFocus() {
+		if (text != null) {
+			text.selectAll();
+			text.setFocus();
+			checkSelection();
+			checkDeleteable();
+			checkSelectable();
+		}
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> framework method accepts a text string (type
+	 * <code>String</code>).
+	 * 
+	 * @param value
+	 *            a text string (type <code>String</code>)
+	 */
+	protected void doSetValue(Object value) {
+		Assert.isTrue(text != null && (value instanceof String));
+		text.removeModifyListener(getModifyListener());
+		text.setText((String) value);
+		text.addModifyListener(getModifyListener());
+	}
+
+	/**
+	 * Processes a modify event that occurred in this text cell editor. This
+	 * framework method performs validation and sets the error message
+	 * accordingly, and then reports a change via
+	 * <code>fireEditorValueChanged</code>. Subclasses should call this method
+	 * at appropriate times. Subclasses may extend or reimplement.
+	 * 
+	 * @param e
+	 *            the SWT modify event
+	 */
+	protected void editOccured(ModifyEvent e) {
+		String value = text.getText();
+		if (value == null) {
+			value = "";//$NON-NLS-1$
+		}
+		Object typedValue = value;
+		boolean oldValidState = isValueValid();
+		boolean newValidState = isCorrect(typedValue);
+		if (!newValidState) {
+			// try to insert the current value into the error message.
+			setErrorMessage(MessageFormat.format(getErrorMessage(),
+					new Object[] { value }));
+		}
+		valueChanged(oldValidState, newValidState);
+	}
+
+	/**
+	 * Since a text editor field is scrollable we don't set a minimumSize.
+	 */
+	public LayoutData getLayoutData() {
+		LayoutData data = new LayoutData();
+		data.minimumWidth = 0;
+		return data;
+	}
+
+	/**
+	 * Return the modify listener.
+	 */
+	private ModifyListener getModifyListener() {
+		if (modifyListener == null) {
+			modifyListener = new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					editOccured(e);
+				}
+			};
+		}
+		return modifyListener;
+	}
+
+	/**
+	 * Handles a default selection event from the text control by applying the
+	 * editor value and deactivating this cell editor.
+	 * 
+	 * @param event
+	 *            the selection event
+	 * 
+	 * @since 3.0
+	 */
+	protected void handleDefaultSelection(SelectionEvent event) {
+		// same with enter-key handling code in keyReleaseOccured(e);
+		fireApplyEditorValue();
+		deactivate();
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method returns <code>true</code> if the current
+	 * selection is not empty.
+	 */
+	public boolean isCopyEnabled() {
+		if (text == null || text.isDisposed()) {
+			return false;
+		}
+		return text.getSelectionCount() > 0;
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method returns <code>true</code> if the current
+	 * selection is not empty.
+	 */
+	public boolean isCutEnabled() {
+		if (text == null || text.isDisposed()) {
+			return false;
+		}
+		return text.getSelectionCount() > 0;
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method returns <code>true</code> if there is a
+	 * selection or if the caret is not positioned at the end of the text.
+	 */
+	public boolean isDeleteEnabled() {
+		if (text == null || text.isDisposed()) {
+			return false;
+		}
+		return text.getSelectionCount() > 0
+				|| text.getCaretOffset() < text.getCharCount();
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method always returns <code>true</code>.
+	 */
+	public boolean isPasteEnabled() {
+		if (text == null || text.isDisposed()) {
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Check if save all is enabled
+	 * 
+	 * @return true if it is
+	 */
+	public boolean isSaveAllEnabled() {
+		if (text == null || text.isDisposed()) {
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Returns <code>true</code> if this cell editor is able to perform the
+	 * select all action.
+	 * <p>
+	 * This default implementation always returns <code>false</code>.
+	 * </p>
+	 * <p>
+	 * Subclasses may override
+	 * </p>
+	 * 
+	 * @return <code>true</code> if select all is possible, <code>false</code>
+	 *         otherwise
+	 */
+	public boolean isSelectAllEnabled() {
+		if (text == null || text.isDisposed()) {
+			return false;
+		}
+		return text.getCharCount() > 0;
+	}
+
+	/**
+	 * Processes a key release event that occurred in this cell editor.
+	 * <p>
+	 * The <code>TextCellEditor</code> implementation of this framework method
+	 * ignores when the RETURN key is pressed since this is handled in
+	 * <code>handleDefaultSelection</code>. An exception is made for Ctrl+Enter
+	 * for multi-line texts, since a default selection event is not sent in this
+	 * case.
+	 * </p>
+	 * 
+	 * @param keyEvent
+	 *            the key event
+	 */
+	protected void keyReleaseOccured(KeyEvent keyEvent) {
+		if (keyEvent.character == '\r') { // Return key
+			// Enter is handled in handleDefaultSelection.
+			// Do not apply the editor value in response to an Enter key event
+			// since this can be received from the IME when the intent is -not-
+			// to apply the value.
+			// See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus
+			// event from Text Control
+			//
+			// An exception is made for Ctrl+Enter for multi-line texts, since
+			// a default selection event is not sent in this case.
+			if (text != null && !text.isDisposed()
+					&& (text.getStyle() & SWT.MULTI) != 0) {
+				if ((keyEvent.stateMask & SWT.CTRL) != 0) {
+					super.keyReleaseOccured(keyEvent);
+				}
+			}
+			return;
+		}
+		super.keyReleaseOccured(keyEvent);
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method copies the current selection to the
+	 * clipboard.
+	 */
+	public void performCopy() {
+		text.copy();
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method cuts the current selection to the
+	 * clipboard.
+	 */
+	public void performCut() {
+		text.cut();
+		checkSelection();
+		checkDeleteable();
+		checkSelectable();
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method deletes the current selection or, if there
+	 * is no selection, the character next character from the current position.
+	 */
+	public void performDelete() {
+		if (text.getSelectionCount() > 0) {
+			// remove the contents of the current selection
+			text.insert(""); //$NON-NLS-1$
+		} else {
+			// remove the next character
+			int pos = text.getCaretOffset();
+			if (pos < text.getCharCount()) {
+				text.setSelection(pos, pos + 1);
+				text.insert(""); //$NON-NLS-1$
+			}
+		}
+		checkSelection();
+		checkDeleteable();
+		checkSelectable();
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method pastes the the clipboard contents over the
+	 * current selection.
+	 */
+	public void performPaste() {
+		text.paste();
+		checkSelection();
+		checkDeleteable();
+		checkSelectable();
+	}
+
+	/**
+	 * The <code>TextCellEditor</code> implementation of this
+	 * <code>CellEditor</code> method selects all of the current text.
+	 */
+	public void performSelectAll() {
+		text.selectAll();
+		checkSelection();
+		checkDeleteable();
+	}
+
+	/**
+	 * This implementation of
+	 * {@link CellEditor#dependsOnExternalFocusListener()} returns false if the
+	 * current instance's class is TextCellEditor, and true otherwise.
+	 * Subclasses that hook their own focus listener should override this method
+	 * and return false. See also bug 58777.
+	 * 
+	 * @since 3.4
+	 */
+	protected boolean dependsOnExternalFocusListener() {
+		return getClass() != StyledTextCellEditor.class;
+	}
+}

+ 291 - 0
de.itemis.xtext.utils/plugins/de.itemis.xtext.utils.jface/src/de/itemis/xtext/utils/jface/viewers/XtextCellEditor.java

@@ -0,0 +1,291 @@
+/**
+ * Copyright (c) 2011 itemis AG 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:
+ * 	itemis AG - initial API and implementation
+ * 
+ */
+package de.itemis.xtext.utils.jface.viewers;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.text.source.AnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.editors.text.EditorsPlugin;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
+import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+import org.eclipse.xtext.parser.IParseResult;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.resource.XtextResourceSet;
+import org.eclipse.xtext.ui.editor.XtextEditor;
+import org.eclipse.xtext.ui.editor.XtextSourceViewer;
+import org.eclipse.xtext.ui.editor.XtextSourceViewer.Factory;
+import org.eclipse.xtext.ui.editor.XtextSourceViewerConfiguration;
+import org.eclipse.xtext.ui.editor.bracketmatching.BracketMatchingPreferencesInitializer;
+import org.eclipse.xtext.ui.editor.bracketmatching.CharacterPairMatcher;
+import org.eclipse.xtext.ui.editor.model.XtextDocument;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionProvider;
+import org.eclipse.xtext.ui.editor.validation.AnnotationIssueProcessor;
+import org.eclipse.xtext.ui.editor.validation.ValidationJob;
+import org.eclipse.xtext.util.concurrent.IUnitOfWork;
+import org.eclipse.xtext.validation.CheckMode;
+import org.eclipse.xtext.validation.IResourceValidator;
+import org.eclipse.xtext.validation.Issue;
+
+import com.google.inject.Inject;
+
+
+/**
+ * This class integrates xText Features into a {@link CellEditor} and can be
+ * used i.E. in jface {@link StructuredViewer}s or in GMF EditParts via
+ * DirectEditManager.
+ * 
+ * The current implementation supports, code completion, syntax highlighting and
+ * validation
+ * 
+ * Some code is initially copied from xText.
+ * 
+ * @author andreas.muelder@itemis.de
+ * @author alexander.nyssen@itemis.de
+ */
+
+@SuppressWarnings("restriction")
+public class XtextCellEditor extends StyledTextCellEditor {
+
+	/**
+	 * Key listener executed content assist operation on CTRL+Space
+	 */
+	private final KeyListener keyListener = new KeyListener() {
+
+
+		public void keyPressed(KeyEvent e) {
+			XtextCellEditor.this.valueChanged(true, true);
+			// CONTENTASSIST_PROPOSALS
+			if ((e.keyCode == 32) && ((e.stateMask & SWT.CTRL) != 0)) {
+				BusyIndicator.showWhile(Display.getDefault(), new Runnable() {
+					public void run() {
+						sourceviewer
+								.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
+					}
+				});
+			}
+		}
+		public void keyReleased(KeyEvent e) {
+		}
+
+	};
+
+	
+
+	/**
+	 * The sourceViewer, that provides additional functions to the styled text
+	 * widget
+	 */
+	private XtextSourceViewer sourceviewer;
+
+	private ValidationJob validationJob;
+	/**
+	 * the xText document the sourceViewer uses
+	 */
+	@Inject
+	private XtextDocument document;
+	@Inject
+	private IssueResolutionProvider resolutionProvider;
+	@Inject
+	private IPreferenceStoreAccess preferenceStoreAccess;
+	@Inject
+	private CharacterPairMatcher characterPairMatcher;
+	@Inject
+	private XtextSourceViewerConfiguration configuration;
+	@Inject
+	private Factory sourceViewerFactory;
+	@Inject
+	private XtextResource resource;
+	@Inject
+	private IResourceValidator validator;
+
+
+
+	/**
+	 * C'tor to create a new Instance.
+	 * 
+	 */
+	public XtextCellEditor(int style) {
+		setStyle(style);
+	}
+	
+	/**
+	 * Creates an {@link SourceViewer} and returns the {@link StyledText} widget
+	 * of the viewer as the cell editors control. Some code is copied from
+	 * {@link XtextEditor}.
+	 */
+	@Override
+	protected Control createControl(Composite parent) {
+		sourceviewer = sourceViewerFactory.createSourceViewer(parent, null,
+				null, false, getStyle());
+		sourceviewer.configure(configuration);
+		
+		//'dummy' document for the sourceviewer
+		XtextResourceSet resourceSet = new XtextResourceSet();
+		resourceSet.getResources().add(resource);
+		setResourceUri(resource);
+		document.setInput(resource);
+		
+		sourceviewer.setDocument(document, new AnnotationModel());
+
+		SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(
+				sourceviewer, null, new DefaultMarkerAnnotationAccess(),
+				EditorsPlugin.getDefault().getSharedTextColors());
+		configureSourceViewerDecorationSupport(support);
+
+		validationJob = createValidationJob();
+		document.setValidationJob(validationJob);
+
+		text = sourceviewer.getTextWidget();
+		text.addKeyListener(keyListener);
+
+		text.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				XtextCellEditor.this.focusLost();
+			}
+		});
+		text.setFont(parent.getFont());
+		text.setBackground(parent.getBackground());
+		text.setText("");
+		return text;
+	}
+
+
+	@Override
+	protected StyledText createStyledText(Composite parent) {
+		sourceviewer = sourceViewerFactory.createSourceViewer(parent, null,
+				null, false, getStyle());
+		sourceviewer.configure(configuration);
+		sourceviewer.setDocument(document, new AnnotationModel());
+
+		SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(
+				sourceviewer, null, new DefaultMarkerAnnotationAccess(),
+				EditorsPlugin.getDefault().getSharedTextColors());
+		configureSourceViewerDecorationSupport(support);
+
+		validationJob = createValidationJob();
+		document.setValidationJob(validationJob);
+
+		return sourceviewer.getTextWidget();
+	}
+
+	private ValidationJob createValidationJob() {
+		return new ValidationJob(validator, document,
+				new AnnotationIssueProcessor(document, sourceviewer
+						.getAnnotationModel(), resolutionProvider),
+				CheckMode.ALL);
+	}
+
+	/**
+	 * Creates decoration support for the sourceViewer. code is entirely copied
+	 * from {@link XtextEditor} and its super class
+	 * {@link AbstractDecoratedTextEditor}.
+	 * 
+	 */
+	private void configureSourceViewerDecorationSupport(
+			SourceViewerDecorationSupport support) {
+		MarkerAnnotationPreferences annotationPreferences = new MarkerAnnotationPreferences();
+		@SuppressWarnings("unchecked")
+		List<AnnotationPreference> prefs = annotationPreferences
+				.getAnnotationPreferences();
+		for (AnnotationPreference annotationPreference : prefs) {
+			support.setAnnotationPreference(annotationPreference);
+		}
+
+		support.setCharacterPairMatcher(characterPairMatcher);
+		support.setMatchingCharacterPainterPreferenceKeys(
+				BracketMatchingPreferencesInitializer.IS_ACTIVE_KEY,
+				BracketMatchingPreferencesInitializer.COLOR_KEY);
+
+		support.install(preferenceStoreAccess.getPreferenceStore());
+
+	}
+
+
+	/**
+	 * Sets the resource uri. From the resource uris project name the global
+	 * scope is determined.
+	 * 
+	 * @param resource
+	 */
+	protected void setResourceUri(final XtextResource resource) {
+		// TODO: This should be moved outside the CellEditor
+		//TODO: Remove dependency to IFileEditorInput
+		Display.getDefault().syncExec(new Runnable() {
+
+			public void run() {
+				IWorkbenchWindow activeWorkbenchWindow = PlatformUI
+						.getWorkbench().getActiveWorkbenchWindow();
+				IWorkbenchPage activePage = activeWorkbenchWindow
+						.getActivePage();
+				if (activePage != null) {
+					IEditorInput editorInput = activePage.getActiveEditor()
+							.getEditorInput();
+					if (editorInput instanceof IFileEditorInput) {
+						IFileEditorInput input = (IFileEditorInput) editorInput;
+						String activeProject = input.getFile().getProject()
+								.getName();
+						resource.setURI(URI.createURI("platform:/resource/"
+								+ activeProject + "/embedded"));
+					}
+				}
+			}
+		});
+	}
+
+
+	public IParseResult getParseResult() {
+		return document
+				.readOnly(new IUnitOfWork<IParseResult, XtextResource>() {
+
+					public IParseResult exec(XtextResource state)
+							throws Exception {
+						return state.getParseResult();
+					}
+				});
+	}
+
+	public List<Issue> getIssues() {
+		return validationJob.createIssues(new NullProgressMonitor());
+	}
+
+	@Override
+	public void dispose() {
+		text.removeKeyListener(keyListener);
+		document.disposeInput();
+		super.dispose();
+	}
+}