sample to write (xtext) editors with javafx!
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/.classpath b/demos/org.eclipse.fx.xtext.sample.editor/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/.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/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/.gitignore b/demos/org.eclipse.fx.xtext.sample.editor/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/.project b/demos/org.eclipse.fx.xtext.sample.editor/.project
new file mode 100644
index 0000000..7b81c60
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.fx.xtext.sample.editor</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<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>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+	</natures>
+</projectDescription>
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/.settings/org.eclipse.jdt.core.prefs b/demos/org.eclipse.fx.xtext.sample.editor/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/META-INF/MANIFEST.MF b/demos/org.eclipse.fx.xtext.sample.editor/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a010cd7
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/META-INF/MANIFEST.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Editor
+Bundle-SymbolicName: org.eclipse.fx.xtext.sample.editor
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.eclipse.fx.ui.controls;bundle-version="2.0.0",
+ org.eclipse.text,
+ org.eclipse.fx.text.ui;bundle-version="1.0.0",
+ org.eclipse.fx.xtext.statemachine.fx;bundle-version="1.0.0"
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/build.properties b/demos/org.eclipse.fx.xtext.sample.editor/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/Sample.txt b/demos/org.eclipse.fx.xtext.sample.editor/src/Sample.txt
new file mode 100644
index 0000000..7fb70f8
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/Sample.txt
@@ -0,0 +1,7 @@
+package sample;
+
+public class MySample {
+	public void main(String[] args) {
+		Sytem.err.println("Hello World!");
+	}
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/Sample_big.txt b/demos/org.eclipse.fx.xtext.sample.editor/src/Sample_big.txt
new file mode 100644
index 0000000..c74612b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/Sample_big.txt
@@ -0,0 +1,9871 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    chris.gross@us.ibm.com - initial API and implementation
+ *******************************************************************************/ 
+package org.eclipse.nebula.widgets.grid;
+
+
+
+// This is a big file
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector
+import org.eclipse.nebula.widgets.grid.internal.DefaultColumnGroupHeaderRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultDropPointRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultEmptyCellRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultEmptyColumnHeaderRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultEmptyRowHeaderRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultFocusRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultInsertMarkRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultRowHeaderRenderer;
+import org.eclipse.nebula.widgets.grid.internal.DefaultTopLeftRenderer;
+import org.eclipse.nebula.widgets.grid.internal.GridToolTip;
+import org.eclipse.nebula.widgets.grid.internal.IScrollBarProxy;
+import org.eclipse.nebula.widgets.grid.internal.NullScrollBarProxy;
+import org.eclipse.nebula.widgets.grid.internal.ScrollBarProxyAdapter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.events.TreeEvent;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+
+/**
+ * <p>
+ * NOTE:  THIS WIDGET AND ITS API ARE STILL UNDER DEVELOPMENT.  THIS IS A PRE-RELEASE ALPHA 
+ * VERSION.  USERS SHOULD EXPECT API CHANGES IN FUTURE VERSIONS.
+ * </p> 
+ * Instances of this class implement a selectable user interface object that
+ * displays a list of images and strings and issue notification when selected.
+ * <p>
+ * The item children that may be added to instances of this class must be of
+ * type {@code GridItem}.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SWT.SINGLE, SWT.MULTI, SWT.NO_FOCUS, SWT.CHECK, SWT.VIRTUAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection</dd>
+ * </dl>
+ * 
+ * @author chris.gross@us.ibm.com
+ */
+public class Grid extends Canvas
+{
+    //TODO: figure out better way to allow renderers to trigger events
+    //TODO: scroll as necessary when performing drag select (current strategy ok)
+    //TODO: need to refactor the way the range select remembers older selection
+    //TODO: remember why i decided i needed to refactor the way the range select remembers older selection
+    //TODO: need to alter how column drag selection works to allow selection of spanned cells   
+    //TODO: JAVADOC!
+    //TODO: column freezing
+    
+    //TODO: Performance - need to cache top index
+    
+    /**
+     * Accessibility default action for column headers and column group headers.
+     */
+    private static final String ACC_COLUMN_DEFAULT_ACTION = "Click";
+
+    /**
+     * Accessibility default action for items.
+     */
+    private static final String ACC_ITEM_DEFAULT_ACTION = "Double Click";
+
+    /**
+     * Accessibility expand action for tree items.
+     */
+    private static final String ACC_ITEM_ACTION_EXPAND = "Expand";
+
+    /**
+     * Accessibility collapse action for tree items.
+     */
+    private static final String ACC_ITEM_ACTION_COLLAPSE = "Collapse";
+
+    /**
+     * Accessibility name for the column group header toggle button.
+     */
+    private static final String ACC_TOGGLE_BUTTON_NAME = "Toggle Button";
+    
+    /**
+     * Alpha blending value used when drawing the dragged column header.
+     */
+    private static final int COLUMN_DRAG_ALPHA = 128;
+
+    /**
+     * Number of pixels below the header to draw the drop point.
+     */
+    private static final int DROP_POINT_LOWER_OFFSET = 3;
+
+    /**
+     * Horizontal scrolling increment, in pixels.
+     */
+    private static final int HORZ_SCROLL_INCREMENT = 5;
+
+    /**
+     * The area to the left and right of the column boundary/resizer that is
+     * still considered the resizer area. This prevents a user from having to be
+     * *exactly* over the resizer.
+     */
+    private static final int COLUMN_RESIZER_THRESHOLD = 4;
+
+    /**
+     * @see #COLUMN_RESIZER_THRESHOLD
+     */
+    private static final int ROW_RESIZER_THRESHOLD = 3;
+
+
+    /**
+     * The minimum width of a column header.
+     */
+    private static final int MIN_COLUMN_HEADER_WIDTH = 20;
+    /**
+     * The minimum height of a row header.
+     */
+    private static final int MIN_ROW_HEADER_HEIGHT = 10;
+
+    /**
+     * The number used when sizing the row header (i.e. size it for '1000')
+     * initially.
+     */
+//    private static final int INITIAL_ROW_HEADER_SIZING_VALUE = 1000;
+
+    /**
+     * The factor to multiply the current row header sizing value by when
+     * determining the next sizing value. Used for performance reasons.
+     */
+//    private static final int ROW_HEADER_SIZING_MULTIPLIER = 10;
+
+    /**
+     * Tracks whether the scroll values are correct. If not they will be
+     * recomputed in onPaint. This allows us to get a free ride on top of the
+     * OS's paint event merging to assure that we don't perform this expensive
+     * operation when unnecessary.
+     */
+    private boolean scrollValuesObsolete = false;
+
+    /**
+     * All items in the table, not just root items.
+     */
+    private List items = new ArrayList();
+    
+    /**
+     * All root items. 
+     */
+    private List rootItems = new ArrayList();
+
+    /**
+     * List of selected items.
+     */
+    private List selectedItems = new ArrayList();
+
+    /**
+     * Reference to the item in focus.
+     */
+    private GridItem focusItem;
+    
+    private boolean cellSelectionEnabled = false;
+    
+    private List selectedCells = new ArrayList();
+    private List selectedCellsBeforeRangeSelect = new ArrayList();
+    
+    private boolean cellDragSelectionOccuring = false;
+    private boolean cellRowDragSelectionOccuring = false;
+    private boolean cellColumnDragSelectionOccuring = false;
+    private boolean cellDragCTRL = false;
+    private boolean followupCellSelectionEventOwed = false;
+    
+    private boolean cellSelectedOnLastMouseDown;
+    private boolean cellRowSelectedOnLastMouseDown;
+    private boolean cellColumnSelectedOnLastMouseDown;
+    
+    private GridColumn shiftSelectionAnchorColumn;
+    
+    private GridColumn focusColumn;
+    
+    private List selectedColumns = new ArrayList();
+    
+    /**
+     * This is the column that the user last navigated to, but may not be the focusColumn because
+     * that column may be spanned in the current row.  This is only used in situations where the user
+     * has used the keyboard to navigate up or down in the table and the focusColumn has switched to
+     * a new column because the intended column (was maintained in this var) was spanned.  The table
+     * will attempt to set focus back to the intended column during subsequent up/down navigations.
+     */
+    private GridColumn intendedFocusColumn;
+    
+
+    /**
+     * List of table columns in creation/index order.
+     */
+    private List columns = new ArrayList();
+
+    /**
+     * List of the table columns in the order they are displayed.
+     */
+    private List displayOrderedColumns = new ArrayList();
+
+    private GridColumnGroup[] columnGroups = new GridColumnGroup[0];
+
+    /**
+     * Renderer to paint the top left area when both column and row headers are
+     * shown.
+     */
+    private IRenderer topLeftRenderer = new DefaultTopLeftRenderer();
+
+    /**
+     * Renderer used to paint row headers.
+     */
+    private IRenderer rowHeaderRenderer = new DefaultRowHeaderRenderer();
+
+    /**
+     * Renderer used to paint empty column headers, used when the columns don't
+     * fill the horz space.
+     */
+    private IRenderer emptyColumnHeaderRenderer = new DefaultEmptyColumnHeaderRenderer();
+
+    /**
+     * Renderer used to paint empty cells to fill horz and vert space.
+     */
+    private GridCellRenderer emptyCellRenderer = new DefaultEmptyCellRenderer();
+
+    /**
+     * Renderer used to paint empty row headers when the rows don't fill the
+     * vertical space.
+     */
+    private IRenderer emptyRowHeaderRenderer = new DefaultEmptyRowHeaderRenderer();
+
+    /**
+     * Renderers the UI affordance identifying where the dragged column will be
+     * dropped.
+     */
+    private IRenderer dropPointRenderer = new DefaultDropPointRenderer();
+
+    /**
+     * Renderer used to paint on top of an already painted row to denote focus.
+     */
+    private IRenderer focusRenderer = new DefaultFocusRenderer();
+
+    /**
+     * Are row headers visible?
+     */
+    private boolean rowHeaderVisible = false;
+
+    /**
+     * Are column headers visible?
+     */
+    private boolean columnHeadersVisible = false;
+
+    /**
+     * Type of selection behavior. Valid values are SWT.SINGLE and SWT.MULTI.
+     */
+    private int selectionType = SWT.SINGLE;
+
+    /**
+     * True if selection highlighting is enabled.
+     */
+    private boolean selectionEnabled = true;
+    
+    /**
+     * Default height of items.  This value is used
+     * for <code>GridItem</code>s with a height
+     * of -1.
+     */
+    private int itemHeight = 1;
+    
+    private boolean userModifiedItemHeight = false;
+
+    /**
+     * Width of each row header.
+     */
+    private int rowHeaderWidth = 0;
+
+    /**
+     * The row header width is variable. The row header width gets larger as
+     * more rows are added to the table to ensure that the row header has enough
+     * room to display the longest string of numbers that display in the row
+     * header. This determination of how wide to make the row header is rather
+     * slow and therefore is only done at every 1000 items (or so). This
+     * variable remembers how many items were last computed and therefore when
+     * the number of items is greater than this value, we need to recalculate
+     * the row header width. See newItem().
+     */
+//    private int lastRowHeaderWidthCalculationAt = 0;
+
+    /**
+     * Height of each column header.
+     */
+    private int headerHeight = 0;
+
+    /**
+     * True if mouse is hover on a column boundary and can resize the column.
+     */
+    private boolean hoveringOnColumnResizer = false;
+
+    /**
+     * Reference to the column being resized.
+     */
+    private GridColumn columnBeingResized;
+
+    /**
+     * Are this <code>Grid</code>'s rows resizeable?
+     */
+    private boolean rowsResizeable = false;
+
+    /**
+     * Is the user currently resizing a column?
+     */
+    private boolean resizingColumn = false;
+
+    /**
+     * The mouse X position when the user starts the resize.
+     */
+    private int resizingStartX = 0;
+
+    /**
+     * The width of the column when the user starts the resize. This, together
+     * with the resizingStartX determines the current width during resize.
+     */
+    private int resizingColumnStartWidth = 0;
+
+    private boolean hoveringOnRowResizer = false;
+    private GridItem rowBeingResized;
+    private boolean resizingRow = false;
+    private int resizingStartY;
+    private int resizingRowStartHeight;
+
+    /**
+     * Reference to the column whose header is currently in a pushed state.
+     */
+    private GridColumn columnBeingPushed;
+
+    /**
+     * Is the user currently pushing a column header?
+     */
+    private boolean pushingColumn = false;
+
+    /**
+     * Is the user currently pushing a column header and hovering over that same
+     * header?
+     */
+    private boolean pushingAndHovering = false;
+
+    /**
+     * X position of the mouse when the user first pushes a column header.
+     */
+    private int startHeaderPushX = 0;
+
+    /**
+     * X position of the mouse when the user has initiated a drag. This is
+     * different than startHeaderPushX because the mouse is allowed some
+     * 'wiggle-room' until the header is put into drag mode.
+     */
+    private int startHeaderDragX = 0;
+
+    /**
+     * The current X position of the mouse during a header drag.
+     */
+    private int currentHeaderDragX = 0;
+
+    /**
+     * Are we currently dragging a column header?
+     */
+    private boolean draggingColumn = false;
+
+    private GridColumn dragDropBeforeColumn = null;
+
+    private GridColumn dragDropAfterColumn = null;
+
+    /**
+     * True if the current dragDropPoint is a valid drop point for the dragged
+     * column. This is false if the column groups are involved and a column is
+     * being dropped into or out of its column group.
+     */
+    private boolean dragDropPointValid = true;
+
+    /**
+     * Reference to the currently item that the mouse is currently hovering
+     * over.
+     */
+    private GridItem hoveringItem;
+
+    /**
+     * Reference to the column that the mouse is currently hovering over.
+     * Includes the header and all cells (all rows) in this column.
+     */
+    private GridColumn hoveringColumn;
+
+    private GridColumn hoveringColumnHeader;
+
+    private GridColumnGroup hoverColumnGroupHeader;
+
+    /**
+     * String-based detail of what is being hovered over in a cell. This allows
+     * a renderer to differentiate between hovering over different parts of the
+     * cell. For example, hovering over a checkbox in the cell or hovering over
+     * a tree node in the cell. The table does nothing with this string except
+     * to set it back in the renderer when its painted. The renderer sets this
+     * during its notify method (InternalWidget.HOVER) and the table pulls it
+     * back and maintains it so it can be set back when the cell is painted. The
+     * renderer determines what the hover detail means and how it affects
+     * painting.
+     */
+    private String hoveringDetail = "";
+    
+    /**
+     * True if the mouse is hovering of a cell's text.
+     */
+    private boolean hoveringOverText = false;
+
+    /**
+     * Are the grid lines visible?
+     */
+    private boolean linesVisible = true;
+
+    /**
+     * Are tree lines visible?
+     */
+    private boolean treeLinesVisible = true;
+
+    /**
+     * Grid line color.
+     */
+    private Color lineColor;
+
+    /**
+     * Vertical scrollbar proxy.
+     * <p>
+     * Note:
+     * <ul>
+     * <li>{@link Grid#getTopIndex()} is the only method allowed to call vScroll.getSelection()
+     * (except #updateScrollbars() of course)</li>
+     * <li>{@link Grid#setTopIndex(int)} is the only method allowed to call vScroll.setSelection(int)</li>
+     * </ul>
+     */
+    private IScrollBarProxy vScroll;
+
+    /**
+     * Horizontal scrollbar proxy.
+     */
+    private IScrollBarProxy hScroll;
+
+    /**
+     * The number of GridItems whose visible = true. Maintained for
+     * performance reasons (rather than iterating over all items).
+     */
+    private int currentVisibleItems = 0;
+
+    /**
+     * Item selected when a multiple selection using shift+click first occurs.
+     * This item anchors all further shift+click selections.
+     */
+    private GridItem shiftSelectionAnchorItem;
+
+    private boolean columnScrolling = false;
+
+    private int groupHeaderHeight;
+
+    private Color cellHeaderSelectionBackground;
+    
+    /**
+     * Dispose listener.  This listener is removed during the dispose event to allow re-firing of
+     * the event.
+     */
+    private Listener disposeListener;
+    
+    /**
+     * The inplace tooltip.
+     */
+    private GridToolTip inplaceToolTip;
+    
+    private GC sizingGC;
+
+    private Color backgroundColor;
+    
+    /**
+     * True if the widget is being disposed.  When true, events are not fired.
+     */
+    private boolean disposing = false;
+    
+    /**
+     * True if there is at least one tree node.  This is used by accessibility and various 
+     * places for optimization.
+     */
+    private boolean isTree = false;
+    
+    /**
+     * True if there is at least one <code>GridItem</code> with an individual height.
+     * This value is only set to true in {@link GridItem#setHeight(int,boolean)}
+     * and it is never reset to false.
+     */
+    boolean hasDifferingHeights = false;
+    
+    /**
+     * True if three is at least one cell spanning columns.  This is used in various places for
+     * optimizatoin.
+     */
+    private boolean hasSpanning = false;
+
+    /**
+     * Index of first visible item.  The value must never be read directly.  It is cached and 
+     * updated when appropriate.  #getTopIndex should be called for every client (even internal 
+     * callers).  A value of -1 indicates that the value is old and will be recomputed.
+     * 
+     * @see #bottomIndex
+     */
+    int topIndex = -1;
+    /**
+     * Index of last visible item.  The value must never be read directly.  It is cached and 
+     * updated when appropriate.  #getBottomIndex() should be called for every client (even internal 
+     * callers).  A value of -1 indicates that the value is old and will be recomputed.
+     * <p>
+     * Note that the item with this index is often only partly visible; maybe only
+     * a single line of pixels is visible. In extreme cases, bottomIndex may be the
+     * same as topIndex.
+     * 
+     * @see #topIndex
+     */
+    int bottomIndex = -1;
+    /**
+     * True if the last visible item is completely visible.  The value must never be read directly.  It is cached and
+     * updated when appropriate.  #isShown() should be called for every client (even internal 
+     * callers).
+     * 
+     * @see #bottomIndex
+     */
+    private boolean bottomIndexShownCompletely = false;
+    
+    /**
+     * Tooltip text - overriden because we have cell specific tooltips
+     */
+    private String toolTipText = null;
+    
+    /**
+     * Flag that is set to true as soon as one image is set on any one item.  
+     * This is used to mimic Table behavior that resizes the rows on the first image added.
+     * See imageSetOnItem.
+     */
+    private boolean firstImageSet = false;
+
+    /** 
+     * Mouse capture flag.  Used for inplace tooltips.  This flag must be used to ensure that 
+     * we don't setCapture(false) in situations where we didn't do setCapture(true).  The OS (SWT?)
+     * will automatically capture the mouse for us during a drag operation. 
+     */
+    private boolean inplaceTooltipCapture;
+
+    /**
+     * This is the tooltip text currently used.  This could be the tooltip text for the currently
+     * hovered cell, or the general grid tooltip.  See handleCellHover.
+     */
+    private String displayedToolTipText;
+    
+    /**
+     * The height of the area at the top and bottom of the
+     * visible grid area in which scrolling is initiated
+     * while dragging over this Grid.
+     */
+    private static final int DRAG_SCROLL_AREA_HEIGHT = 12;
+
+    /**
+     * Threshold for the selection border used for drag n drop
+     * in mode (!{@link #dragOnFullSelection}}.
+     */
+    private static final int SELECTION_DRAG_BORDER_THRESHOLD = 2;
+
+    private boolean hoveringOnSelectionDragArea = false;
+
+    private GridItem insertMarkItem = null;
+    private GridColumn insertMarkColumn = null;
+    private boolean insertMarkBefore = false;
+    private IRenderer insertMarkRenderer = new DefaultInsertMarkRenderer();
+    
+    /**
+     * A range of rows in a <code>Grid</code>.
+     * <p>
+     * A row in this sense exists only for visible items
+     * (i.e. items with {@link GridItem#isVisible()} == true).
+     * Therefore, the items at 'startIndex' and 'endIndex'
+     * are always visible.
+     * 
+     * @see Grid#getRowRange(int, int, boolean, boolean)
+     */
+    private static class RowRange {
+        /** index of first item in range */
+        public int startIndex;
+        /** index of last item in range */
+        public int endIndex;
+        /** number of rows (i.e. <em>visible</em> items) in this range */
+        public int rows;
+        /** height in pixels of this range (including horizontal separator between rows) */
+        public int height;
+    }
+    
+    /**
+     * Filters out unnecessary styles, adds mandatory styles and generally
+     * manages the style to pass to the super class.
+     * 
+     * @param style user specified style.
+     * @return style to pass to the super class.
+     */
+    private static int checkStyle(int style)
+    {
+        int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.H_SCROLL | SWT.V_SCROLL
+                   | SWT.SINGLE | SWT.MULTI | SWT.NO_FOCUS | SWT.CHECK | SWT.VIRTUAL;
+        int newStyle = style & mask;
+        newStyle |= SWT.DOUBLE_BUFFERED;
+        return newStyle;
+    }
+
+    /**
+     * Constructs a new instance of this class given its parent and a style
+     * value describing its behavior and appearance.
+     * <p>
+     * 
+     * @param parent a composite control which will be the parent of the new
+     * instance (cannot be null)
+     * @param style the style of control to construct
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the parent</li>
+     * </ul>
+     * @see SWT#SINGLE
+     * @see SWT#MULTI
+     */
+    public Grid(Composite parent, int style)
+    {
+        super(parent, checkStyle(style));
+
+        // initialize drag & drop support
+        setData("DEFAULT_DRAG_SOURCE_EFFECT", new GridDragSourceEffect(this));
+        setData("DEFAULT_DROP_TARGET_EFFECT", new GridDropTargetEffect(this));
+
+        sizingGC = new GC(this);
+        
+        topLeftRenderer.setDisplay(getDisplay());
+        rowHeaderRenderer.setDisplay(getDisplay());
+        emptyColumnHeaderRenderer.setDisplay(getDisplay());
+        emptyCellRenderer.setDisplay(getDisplay());
+        dropPointRenderer.setDisplay(getDisplay());
+        focusRenderer.setDisplay(getDisplay());
+        emptyRowHeaderRenderer.setDisplay(getDisplay());
+        insertMarkRenderer.setDisplay(getDisplay());
+
+        setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+        setLineColor(getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
+
+        if ((style & SWT.MULTI) != 0)
+        {
+            selectionType = SWT.MULTI;
+        }
+        
+        if (getVerticalBar() != null)
+        {
+            getVerticalBar().setVisible(false);
+            vScroll = new ScrollBarProxyAdapter(getVerticalBar());
+        }
+        else
+        {
+            vScroll = new NullScrollBarProxy();
+        }
+
+        if (getHorizontalBar() != null)
+        {
+            getHorizontalBar().setVisible(false);            
+            hScroll = new ScrollBarProxyAdapter(getHorizontalBar());
+        }
+        else
+        {
+            hScroll = new NullScrollBarProxy();
+        }
+
+        scrollValuesObsolete = true;
+
+        initListeners();
+        initAccessible();
+
+        
+        itemHeight = sizingGC.getFontMetrics().getHeight() + 2;
+        
+        
+        RGB sel = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION).getRGB();
+        RGB white = getDisplay().getSystemColor(SWT.COLOR_WHITE).getRGB();
+        
+        RGB cellSel = blend(sel,white,50);
+        
+        cellHeaderSelectionBackground = new Color(getDisplay(),cellSel);
+        
+        setDragDetect(false);
+    }    
+    
+    
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public Color getBackground()
+    {
+        checkWidget();
+        if (backgroundColor == null)
+            return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+        return backgroundColor;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void setBackground(Color color)
+    {
+        checkWidget();
+        backgroundColor = color;
+        redraw();
+    }
+
+    /**
+     * Returns the background color of column and row headers when a cell in 
+     * the row or header is selected.
+     * 
+     * @return cell header selection background color 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public Color getCellHeaderSelectionBackground()
+    {
+        checkWidget();
+        return cellHeaderSelectionBackground;
+    }
+
+    /**
+     * Sets the background color of column and row headers displayed when a cell in 
+     * the row or header is selected.
+     * 
+     * @param cellSelectionBackground color to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setCellHeaderSelectionBackground(Color cellSelectionBackground)
+    {
+        checkWidget();
+        this.cellHeaderSelectionBackground = cellSelectionBackground;
+    }
+
+    /**
+     * Adds the listener to the collection of listeners who will be notified
+     * when the receiver's selection changes, by sending it one of the messages
+     * defined in the {@code SelectionListener} interface.
+     * <p>
+     * Cell selection events may have <code>Event.detail = SWT.DRAG</code> when the 
+     * user is drag selecting multiple cells.  A follow up selection event will be generated 
+     * when the drag is complete.    
+     * 
+     * @param listener the listener which should be notified
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void addSelectionListener(SelectionListener listener)
+    {
+        checkWidget();
+        if (listener == null)
+        {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        addListener(SWT.Selection, new TypedListener(listener));
+        addListener(SWT.DefaultSelection, new TypedListener(listener));
+    }
+
+    /**
+     * Adds the listener to the collection of listeners who will be notified
+     * when the receiver's items changes, by sending it one of the messages
+     * defined in the {@code TreeListener} interface.
+     * 
+     * @param listener the listener which should be notified
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see TreeListener
+     * @see #removeTreeListener
+     * @see org.eclipse.swt.events.TreeEvent
+     */
+    public void addTreeListener(TreeListener listener)
+    {
+        checkWidget();
+        if (listener == null)
+        {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+
+        addListener(SWT.Expand, new TypedListener(listener));
+        addListener(SWT.Collapse, new TypedListener(listener));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Point computeSize(int wHint, int hHint, boolean changed)
+    {
+        checkWidget();
+
+        Point prefSize = null;
+        if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT)
+        {
+            prefSize = getTableSize();
+            prefSize.x += 2 * getBorderWidth();
+            prefSize.y += 2 * getBorderWidth();
+        }
+
+        int x = 0;
+        int y = 0;
+
+        if (wHint == SWT.DEFAULT)
+        {
+            x += prefSize.x;
+            if (getVerticalBar() != null)
+            {
+                x += getVerticalBar().getSize().x;
+            }
+        }
+        else
+        {
+            x = wHint;
+        }
+
+        if (hHint == SWT.DEFAULT)
+        {
+            y += prefSize.y;
+            if (getHorizontalBar() != null)
+            {
+                y += getHorizontalBar().getSize().y;
+            }
+        }
+        else
+        {
+            y = hHint;
+        }
+
+        return new Point(x, y);
+    }
+
+    /**
+     * Deselects the item at the given zero-relative index in the receiver. If
+     * the item at the index was already deselected, it remains deselected.
+     * Indices that are out of range are ignored.
+     * <p>
+     * If cell selection is enabled, all cells in the specified item are deselected.
+     * 
+     * @param index the index of the item to deselect
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void deselect(int index)
+    {
+        checkWidget();
+
+        if (index < 0 || index > items.size() - 1)
+        {
+            return;
+        }
+
+        GridItem item = (GridItem)items.get(index);
+        
+        if (!cellSelectionEnabled)
+        {
+            if (selectedItems.contains(item))
+            {
+                selectedItems.remove(item);
+            }
+        }
+        else
+        {
+            deselectCells(getCells(item));
+        }
+        redraw();
+    }
+
+    /**
+     * Deselects the items at the given zero-relative indices in the receiver.
+     * If the item at the given zero-relative index in the receiver is selected,
+     * it is deselected. If the item at the index was not selected, it remains
+     * deselected. The range of the indices is inclusive. Indices that are out
+     * of range are ignored.
+     * <p>
+     * If cell selection is enabled, all cells in the given range are deselected.
+     * 
+     * @param start the start index of the items to deselect
+     * @param end the end index of the items to deselect
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void deselect(int start, int end)
+    {
+        checkWidget();
+
+        for (int i = start; i <= end; i++)
+        {
+            if (i < 0)
+            {
+                continue;
+            }
+            if (i > items.size() - 1)
+            {
+                break;
+            }
+
+            GridItem item = (GridItem)items.get(i);
+            
+            if (!cellSelectionEnabled)
+            {
+                if (selectedItems.contains(item))
+                {
+                    selectedItems.remove(item);
+                }
+            }
+            else
+            {
+                deselectCells(getCells(item));
+            }
+        }
+        redraw();
+    }
+
+    /**
+     * Deselects the items at the given zero-relative indices in the receiver.
+     * If the item at the given zero-relative index in the receiver is selected,
+     * it is deselected. If the item at the index was not selected, it remains
+     * deselected. Indices that are out of range and duplicate indices are
+     * ignored.
+     * <p>
+     * If cell selection is enabled, all cells in the given items are deselected.
+     * 
+     * @param indices the array of indices for the items to deselect
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the set of indices is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void deselect(int[] indices)
+    {
+        checkWidget();
+        if (indices == null)
+        {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+
+        for (int i = 0; i < indices.length; i++)
+        {
+            int j = indices[i];
+
+            if (j >= 0 && j < items.size())
+            {
+                GridItem item = (GridItem)items.get(j);
+                
+                if (!cellSelectionEnabled)
+                {
+                    if (selectedItems.contains(item))
+                    {
+                        selectedItems.remove(item);
+                    }
+                }
+                else
+                {
+                    deselectCells(getCells(item));
+                }
+            }
+        }
+        redraw();
+    }
+
+    /**
+     * Deselects all selected items in the receiver.  If cell selection is enabled,
+     * all cells are deselected.
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void deselectAll()
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled)
+        {
+            selectedItems.clear();
+            redraw();
+        }
+        else
+        {
+            deselectAllCells();
+        }
+    }
+
+    /**
+     * Returns the column at the given, zero-relative index in the receiver.
+     * Throws an exception if the index is out of range. If no
+     * {@code GridColumn}s were created by the programmer, this method will
+     * throw {@code ERROR_INVALID_RANGE} despite the fact that a single column
+     * of data may be visible in the table. This occurs when the programmer uses
+     * the table like a list, adding items but never creating a column.
+     * 
+     * @param index the index of the column to return
+     * @return the column at the given index
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+     * of elements in the list minus 1 (inclusive)</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridColumn getColumn(int index)
+    {
+        checkWidget();
+
+        if (index < 0 || index > getColumnCount() - 1)
+        {
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        }
+
+        return (GridColumn)columns.get(index);
+    }
+
+    /**
+     * Returns the column at the given point in the receiver or null if no such
+     * column exists. The point is in the coordinate system of the receiver.
+     * 
+     * @param point the point used to locate the column
+     * @return the column at the given point
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridColumn getColumn(Point point)
+    {
+        checkWidget();
+        if (point == null)
+        {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+
+        GridColumn overThis = null;
+
+        int x2 = 0;
+
+        if (rowHeaderVisible)
+        {
+            if (point.x <= rowHeaderWidth)
+            {
+                return null;
+            }
+
+            x2 += rowHeaderWidth;
+        }
+
+        x2 -= getHScrollSelectionInPixels();
+        
+        for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
+        {
+            GridColumn column = (GridColumn) columnIterator.next();
+
+            if (!column.isVisible())
+            {
+                continue;
+            }
+
+            if (point.x >= x2 && point.x < x2 + column.getWidth())
+            {
+                overThis = column;
+                break;
+            }
+
+            x2 += column.getWidth();
+        }
+
+        if (overThis == null)
+        {
+            return null;
+        }
+
+        if (hasSpanning)
+        {
+            // special logic for column spanning
+            GridItem item = getItem(point);
+            if (item != null)
+            {
+                int displayColIndex = displayOrderedColumns.indexOf(overThis);
+    
+                // track back all previous columns and check their spanning
+                for (int i = 0; i < displayColIndex; i++)
+                {
+                    if (!((GridColumn)displayOrderedColumns.get(i)).isVisible())
+                    {
+                        continue;
+                    }
+    
+                    int colIndex = indexOf((GridColumn)displayOrderedColumns.get(i));
+                    int span = item.getColumnSpan(colIndex);
+    
+                    if (i + span >= displayColIndex)
+                    {
+                        overThis = (GridColumn)displayOrderedColumns.get(i);
+                        break;
+                    }
+                }
+            }
+        }
+
+        return overThis;
+    }
+
+    /**
+     * Returns the number of columns contained in the receiver. If no
+     * {@code GridColumn}s were created by the programmer, this value is
+     * zero, despite the fact that visually, one column of items may be visible.
+     * This occurs when the programmer uses the table like a list, adding items
+     * but never creating a column.
+     * 
+     * @return the number of columns
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getColumnCount()
+    {
+        checkWidget();
+        return columns.size();
+    }
+
+    /**
+     * Returns an array of zero-relative integers that map the creation order of
+     * the receiver's items to the order in which they are currently being
+     * displayed.
+     * <p>
+     * Specifically, the indices of the returned array represent the current
+     * visual order of the items, and the contents of the array represent the
+     * creation order of the items.
+     * </p>
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its list of items, so modifying the array will not affect the receiver.
+     * </p>
+     * 
+     * @return the current visual order of the receiver's items
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int[] getColumnOrder()
+    {
+        checkWidget();
+
+        int[] order = new int[columns.size()];
+        int i = 0;
+        for (Iterator colIterator = displayOrderedColumns.iterator(); colIterator.hasNext(); )
+        {
+            GridColumn col = (GridColumn) colIterator.next();
+            order[i] = columns.indexOf(col);
+            i++;
+        }
+        return order;
+    }
+    
+    /**
+     * Returns the number of column groups contained in the receiver. 
+     * 
+     * @return the number of column groups
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getColumnGroupCount()
+    {
+        checkWidget();
+        return columnGroups.length;
+    }
+    
+    /**
+     * Returns an array of {@code GridColumnGroup}s which are the column groups in the
+     * receiver. 
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its list of items, so modifying the array will not affect the receiver.
+     * </p>
+     * 
+     * @return the column groups in the receiver
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridColumnGroup[] getColumnGroups()
+    {
+        checkWidget();
+        GridColumnGroup[] newArray = new GridColumnGroup[columnGroups.length];
+        System.arraycopy (columnGroups, 0, newArray, 0, columnGroups.length);
+        return newArray;
+    }
+    
+    /**
+     * Returns the column group at the given, zero-relative index in the receiver.
+     * Throws an exception if the index is out of range. 
+     * 
+     * @param index the index of the column group to return
+     * @return the column group at the given index
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+     * of elements in the list minus 1 (inclusive)</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridColumnGroup getColumnGroup(int index)
+    {
+        checkWidget();
+        
+        if (index < 0 || index >= columnGroups.length) 
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        
+        return columnGroups[index];
+    }
+
+    /**
+     * Sets the order that the items in the receiver should be displayed in to
+     * the given argument which is described in terms of the zero-relative
+     * ordering of when the items were added.
+     * 
+     * @param order the new order to display the items
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS -if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
+     * <li>ERROR_INVALID_ARGUMENT - if the order is not the same length as the
+     * number of items, or if an item is listed twice, or if the order splits a
+     * column group</li>
+     * </ul>
+     */
+    public void setColumnOrder(int[] order)
+    {
+        checkWidget();
+
+        if (order == null)
+        {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+
+        if (order.length != displayOrderedColumns.size())
+        {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+
+        boolean[] seen = new boolean[displayOrderedColumns.size()];
+
+        for (int i = 0; i < order.length; i++)
+        {
+            if (order[i] < 0 || order[i] >= displayOrderedColumns.size())
+            {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+            if (seen[order[i]])
+            {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+            seen[order[i]] = true;
+        }
+
+        if (columnGroups.length != 0)
+        {
+            GridColumnGroup currentGroup = null;
+            int colsInGroup = 0;
+
+            for (int i = 0; i < order.length; i++)
+            {
+                GridColumn col = getColumn(order[i]);
+
+                if (currentGroup != null)
+                {
+                    if (col.getColumnGroup() != currentGroup)
+                    {
+                        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+                    }
+                    else
+                    {
+                        colsInGroup--;
+                        if (colsInGroup == 0)
+                        {
+                            currentGroup = null;
+                        }
+                    }
+                }
+                else if (col.getColumnGroup() != null)
+                {
+                    currentGroup = col.getColumnGroup();
+                    colsInGroup = currentGroup.getColumns().length - 1;
+                }
+
+            }
+        }
+
+        GridColumn[] cols = getColumns();
+
+        displayOrderedColumns.clear();
+
+        for (int i = 0; i < order.length; i++)
+        {
+            displayOrderedColumns.add(cols[order[i]]);
+        }
+    }
+
+    /**
+     * Returns an array of {@code GridColumn}s which are the columns in the
+     * receiver. If no {@code GridColumn}s were created by the programmer,
+     * the array is empty, despite the fact that visually, one column of items
+     * may be visible. This occurs when the programmer uses the table like a
+     * list, adding items but never creating a column.
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its list of items, so modifying the array will not affect the receiver.
+     * </p>
+     * 
+     * @return the items in the receiver
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridColumn[] getColumns()
+    {
+        checkWidget();
+        return (GridColumn[])columns.toArray(new GridColumn[columns.size()]);
+    }
+
+    /**
+     * Returns the empty cell renderer.
+     * 
+     * @return Returns the emptyCellRenderer.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridCellRenderer getEmptyCellRenderer()
+    {
+        checkWidget();
+        return emptyCellRenderer;
+    }
+
+    /**
+     * Returns the empty column header renderer.
+     * 
+     * @return Returns the emptyColumnHeaderRenderer.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public IRenderer getEmptyColumnHeaderRenderer()
+    {
+        checkWidget();
+        return emptyColumnHeaderRenderer;
+    }
+
+    /**
+     * Returns the empty row header renderer.
+     * 
+     * @return Returns the emptyRowHeaderRenderer.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public IRenderer getEmptyRowHeaderRenderer()
+    {
+        checkWidget();
+        return emptyRowHeaderRenderer;
+    }
+
+    /**
+     * Returns the externally managed horizontal scrollbar.
+     * 
+     * @return the external horizontal scrollbar.
+     * @see #setHorizontalScrollBarProxy(IScrollBarProxy)
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    protected IScrollBarProxy getHorizontalScrollBarProxy()
+    {
+        checkWidget();
+        return hScroll;
+    }
+
+    /**
+     * Returns the externally managed vertical scrollbar.
+     * 
+     * @return the external vertical scrollbar.
+     * @see #setlVerticalScrollBarProxy(IScrollBarProxy)
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    protected IScrollBarProxy getVerticalScrollBarProxy()
+    {
+        checkWidget();
+        return vScroll;
+    }
+
+    /**
+     * Gets the focus renderer.
+     * 
+     * @return Returns the focusRenderer.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public IRenderer getFocusRenderer()
+    {
+        checkWidget();
+        return focusRenderer;
+    }
+
+    /**
+     * Returns the height of the column headers. If this table has column
+     * groups, the returned value includes the height of group headers.
+     * 
+     * @return height of the column header row
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getHeaderHeight()
+    {
+        checkWidget();
+        return headerHeight;
+    }
+
+    /**
+     * Returns the height of the column group headers.
+     * 
+     * @return height of column group headers
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getGroupHeaderHeight()
+    {
+        checkWidget();
+        return groupHeaderHeight;
+    }
+
+    /**
+     * Returns {@code true} if the receiver's header is visible, and
+     * {@code false} otherwise.
+     * 
+     * @return the receiver's header's visibility state
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean getHeaderVisible()
+    {
+        checkWidget();
+        return columnHeadersVisible;
+    }
+
+    /**
+     * Returns the item at the given, zero-relative index in the receiver.
+     * Throws an exception if the index is out of range.
+     * 
+     * @param index the index of the item to return
+     * @return the item at the given index
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the 
+     * list minus 1 (inclusive) </li>     * 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem getItem(int index)
+    {
+        checkWidget();
+        
+        if (index < 0 || index >= items.size())
+        {
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        }
+        
+        return (GridItem)items.get(index);
+    }
+
+    /**
+     * Returns the item at the given point in the receiver or null if no such
+     * item exists. The point is in the coordinate system of the receiver.
+     * 
+     * @param point the point used to locate the item
+     * @return the item at the given point
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem getItem(Point point)
+    {
+        checkWidget();
+        
+        if (point == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+        if (point.x < 0 || point.x > getClientArea().width) return null;
+        
+        Point p = new Point(point.x, point.y);
+
+        int y2=0;
+
+        if (columnHeadersVisible)
+        {
+            if (p.y <= headerHeight)
+            {
+                return null;
+            }
+            y2 += headerHeight;
+        }
+
+        int row=getTopIndex();
+        while(row<items.size() && y2<=getClientArea().height)
+        {
+            GridItem currItem = (GridItem)items.get(row);
+            if (currItem.isVisible())
+            {
+                int currItemHeight = currItem.getHeight();
+
+                if (p.y >= y2 && p.y < y2+currItemHeight+1)
+                {
+                    return currItem;
+                }
+
+                y2 += currItemHeight +1;
+            }
+            row++;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the number of items contained in the receiver.
+     * 
+     * @return the number of items
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getItemCount()
+    {
+        checkWidget();
+        return getItems().length;
+    }
+
+    /**
+     * Returns the default height of the items
+     * in this <code>Grid</code>. See {@link #setItemHeight(int)}
+     * for details.
+     * 
+     * <p>IMPORTANT: The Grid's items need not all have the
+     * height returned by this method, because an
+     * item's height may have been changed by calling
+     * {@link GridItem#setHeight(int)}.
+     * 
+     * @return default height of items
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see #setItemHeight(int)
+     */
+    public int getItemHeight()
+    {
+        checkWidget();
+        return itemHeight;
+    }
+    
+    /**
+     * Sets the default height for this <code>Grid</code>'s items.  When
+     * this method is called, all existing items are resized
+     * to the specified height and items created afterwards will be
+     * initially sized to this height.
+     * <p>
+     * As long as no default height was set by the client through this method,
+     * the preferred height of the first item in this <code>Grid</code> is
+     * used as a default for all items (and is returned by {@link #getItemHeight()}).
+     * 
+     * @param height  default height in pixels
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_ARGUMENT - if the height is < 1</li> 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * 
+     * @see GridItem#getHeight()
+     * @see GridItem#setHeight(int)
+     */
+    public void setItemHeight(int height)
+    {
+        checkWidget();
+        if (height < 1)
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        itemHeight = height;
+        userModifiedItemHeight = true;
+        for(int cnt=0;cnt<items.size();cnt++)
+            ((GridItem)items.get(cnt)).setHeight(height);
+        hasDifferingHeights=false;
+        setScrollValuesObsolete();
+        redraw();
+    }
+
+    /**
+     * Returns true if the rows are resizable.
+     * 
+     * @return the row resizeable state
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see #setRowsResizeable(boolean)
+     */
+    public boolean getRowsResizeable() {
+        checkWidget();
+        return rowsResizeable;
+    }
+    /**
+     * Sets the rows resizeable state of this <code>Grid</code>.
+     * The default is 'false'.
+     * <p>
+     * If a row in a <code>Grid</code> is resizeable,
+     * then the user can interactively change its height
+     * by dragging the border of the row header.
+     * <p>
+     * Note that for rows to be resizable the row headers must be visible.
+     * 
+     * @param rowsResizeable true if this <code>Grid</code>'s rows should be resizable
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see #setRowHeaderVisible(boolean)
+     */
+    public void setRowsResizeable(boolean rowsResizeable) {
+        checkWidget();
+        this.rowsResizeable=rowsResizeable;
+    }
+
+    /**
+     * Returns a (possibly empty) array of {@code GridItem}s which are the
+     * items in the receiver.
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its list of items, so modifying the array will not affect the receiver.
+     * </p>
+     * 
+     * @return the items in the receiver
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem[] getItems()
+    {
+        checkWidget();
+        return (GridItem[])items.toArray(new GridItem[items.size()]);
+    }
+
+    /**
+     * Returns the line color.
+     * 
+     * @return Returns the lineColor.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public Color getLineColor()
+    {
+        checkWidget();
+        return lineColor;
+    }
+
+    /**
+     * Returns true if the lines are visible.
+     * 
+     * @return Returns the linesVisible.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean getLinesVisible()
+    {
+        checkWidget();
+        return linesVisible;
+    }
+    
+    /**
+     * Returns true if the tree lines are visible.
+     * 
+     * @return Returns the treeLinesVisible.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean getTreeLinesVisible() {
+        checkWidget();
+        return treeLinesVisible;
+    }
+
+    /**
+     * Returns the next visible item in the table.
+     * 
+     * @param item item
+     * @return next visible item or null
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem getNextVisibleItem(GridItem item)
+    {
+        checkWidget();
+
+        int index = items.indexOf(item);
+        if (items.size() == index + 1)
+        {
+            return null;
+        }
+        
+        GridItem nextItem = (GridItem)items.get(index + 1);
+
+        while (!nextItem.isVisible())
+        {
+            index++;
+            if (items.size() == index + 1)
+            {
+                return null;
+            }
+
+            nextItem = (GridItem)items.get(index + 1);
+        }
+
+        return nextItem;
+    }
+
+    /**
+     * Returns the previous visible item in the table. Passing null for the item
+     * will return the last visible item in the table.
+     * 
+     * @param item item or null
+     * @return previous visible item or if item==null last visible item
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem getPreviousVisibleItem(GridItem item)
+    {
+        checkWidget();
+
+        int index = 0;
+        if (item == null)
+        {
+            index = items.size();
+        }
+        else
+        {
+            index = items.indexOf(item);
+            if (index == 0)
+            {
+                return null;
+            }
+        }
+
+        GridItem prevItem = (GridItem)items.get(index - 1);
+
+        while (!prevItem.isVisible())
+        {
+            index--;
+            if (index == 0)
+            {
+                return null;
+            }
+
+            prevItem = (GridItem)items.get(index - 1);
+        }
+
+        return prevItem;
+    }
+    
+    /**
+     * Returns the previous visible column in the table.
+     * 
+     * @param column column
+     * @return previous visible column or null
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridColumn getPreviousVisibleColumn(GridColumn column)
+    {        
+        checkWidget();
+        
+        int index = displayOrderedColumns.indexOf(column);
+        
+        if (index == 0)
+            return null;
+        
+        index --;
+        
+        GridColumn previous = (GridColumn)displayOrderedColumns.get(index);
+        
+        while (!previous.isVisible())
+        {
+            if (index == 0)
+                return null;
+            
+            index --;
+            previous = (GridColumn)displayOrderedColumns.get(index);
+        }
+        
+        return previous;
+    }
+    
+    /**
+     * Returns the next visible column in the table.
+     * 
+     * @param column column
+     * @return next visible column or null
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridColumn getNextVisibleColumn(GridColumn column)
+    {        
+        checkWidget();
+        
+        int index = displayOrderedColumns.indexOf(column);
+        
+        if (index == displayOrderedColumns.size() - 1)
+            return null;
+        
+        index ++;
+        
+        GridColumn next = (GridColumn)displayOrderedColumns.get(index);
+        
+        while (!next.isVisible())
+        {
+            if (index == displayOrderedColumns.size() - 1)
+                return null;
+            
+            index ++;
+            next = (GridColumn)displayOrderedColumns.get(index);
+        }
+        
+        return next;
+    }
+
+    /**
+     * Returns the number of root items contained in the receiver.
+     * 
+     * @return the number of items
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getRootItemCount()
+    {
+        checkWidget();
+        return rootItems.size();
+    }
+
+    /**
+     * Returns a (possibly empty) array of {@code GridItem}s which are
+     * the root items in the receiver.
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its list of items, so modifying the array will not affect the receiver.
+     * </p>
+     * 
+     * @return the root items in the receiver
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem[] getRootItems()
+    {
+        checkWidget();
+
+        return (GridItem[])rootItems.toArray(new GridItem[rootItems.size()]);
+    }
+    
+    /**
+     * TODO: asl;fj
+     * @param index
+     * @return asdf
+     */
+    public GridItem getRootItem(int index)
+    {
+        checkWidget();
+        
+        if (index < 0 || index >= rootItems.size())
+        {
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        }
+        
+        return (GridItem)rootItems.get(index);
+    }
+
+    /**
+     * Gets the row header renderer.
+     * 
+     * @return Returns the rowHeaderRenderer.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public IRenderer getRowHeaderRenderer()
+    {
+        checkWidget();
+        return rowHeaderRenderer;
+    }
+
+    /**
+     * Returns a array of {@code GridItem}s that are currently selected in the
+     * receiver. The order of the items is unspecified. An empty array indicates
+     * that no items are selected.
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its selection, so modifying the array will not affect the receiver.
+     * <p>
+     * If cell selection is enabled, any items which contain at least one selected
+     * cell are returned.
+     * 
+     * @return an array representing the selection
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem[] getSelection()
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled)
+        {
+            return (GridItem[])selectedItems.toArray(new GridItem[selectedItems.size()]);    
+        }
+        else
+        {
+            Vector items = new Vector();
+            for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
+            {
+                Point cell = (Point)iter.next();
+                GridItem item = getItem(cell.y);
+                if (!items.contains(item))
+                    items.add(item);                
+            }
+            return (GridItem[])items.toArray(new GridItem[]{});
+        }
+    }
+
+    /**
+     * Returns the number of selected items contained in the receiver.  If cell selection
+     * is enabled, the number of items with at least one selected cell are returned.
+     * 
+     * @return the number of selected items
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getSelectionCount()
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled)
+        {
+            return selectedItems.size();
+        }
+        else
+        {
+            Vector items = new Vector();
+            for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
+            {
+                Point cell = (Point)iter.next();
+                GridItem item = getItem(cell.y);
+                if (!items.contains(item))
+                    items.add(item);                
+            }
+            return items.size();
+        }
+    }
+    
+    /**
+     * Returns the number of selected cells contained in the receiver.
+     * 
+     * @return the number of selected cells
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getCellSelectionCount()
+    {
+        checkWidget();
+        return selectedCells.size();
+    }
+
+    /**
+     * Returns the zero-relative index of the item which is currently selected
+     * in the receiver, or -1 if no item is selected.  If cell selection is enabled,
+     * returns the index of first item that contains at least one selected cell.
+     * 
+     * @return the index of the selected item
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getSelectionIndex()
+    {
+        checkWidget();
+
+        if (!cellSelectionEnabled)
+        {
+            if (selectedItems.size() == 0)
+            {
+                return -1;
+            }
+    
+            return items.indexOf(selectedItems.get(0));
+        }
+        else
+        {
+            if (selectedCells.size() == 0)
+                return -1;
+            
+            return ((Point)selectedCells.get(0)).y;
+        }
+    }
+
+    /**
+     * Returns the zero-relative indices of the items which are currently
+     * selected in the receiver. The order of the indices is unspecified. The
+     * array is empty if no items are selected.
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its selection, so modifying the array will not affect the receiver.
+     * <p>
+     * If cell selection is enabled, returns the indices of any items which 
+     * contain at least one selected cell.
+     * 
+     * @return the array of indices of the selected items
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int[] getSelectionIndices()
+    {
+        checkWidget();
+
+        if (!cellSelectionEnabled)
+        {
+            int[] indices = new int[selectedItems.size()];
+            int i = 0;
+            for (Iterator itemIterator = selectedItems.iterator(); itemIterator.hasNext(); )
+            {
+                GridItem item = (GridItem) itemIterator.next();
+                indices[i] = items.indexOf(item);
+                i++;
+            }
+            return indices;
+        }
+        else
+        {
+            Vector selectedRows = new Vector();
+            for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
+            {
+                Point cell = (Point)iter.next();
+                GridItem item = getItem(cell.y);
+                if (!selectedRows.contains(item))
+                    selectedRows.add(item);                
+            }
+            int[] indices = new int[selectedRows.size()];
+            int i = 0;
+            for (Iterator itemIterator = selectedRows.iterator(); itemIterator.hasNext(); )
+            {
+                GridItem item = (GridItem) itemIterator.next();
+                indices[i] = items.indexOf(item);
+                i++;
+            }
+            return indices;
+        }
+    }
+
+    /**
+     * Returns the zero-relative index of the item which is currently at the top
+     * of the receiver. This index can change when items are scrolled or new
+     * items are added or removed.
+     * 
+     * @return the index of the top item
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getTopIndex()
+    {
+        checkWidget();
+
+        if (topIndex != -1)
+            return topIndex;
+
+        if (!vScroll.getVisible())
+        {
+            topIndex = 0;
+        }
+        else
+        {
+            // figure out first visible row and last visible row
+            int firstVisibleIndex = vScroll.getSelection();
+
+            if (isTree)
+            {
+                Iterator itemsIter = items.iterator();
+                int row = firstVisibleIndex + 1;
+
+                while (row > 0 && itemsIter.hasNext())
+                {
+                    GridItem item = (GridItem)itemsIter.next();
+
+                    if (item.isVisible())
+                    {
+                        row--;
+                        if (row == 0)
+                        {
+                            firstVisibleIndex = items.indexOf(item);
+                        }
+                    }
+                }
+            }
+
+            topIndex = firstVisibleIndex;
+
+            /*
+             *  MOPR  here lies more potential for increasing performance
+             *  for the case (isTree || hasDifferingHeights)
+             *  the topIndex could be derived from the previous value
+             *  depending on a delta of the vScroll.getSelection()
+             *  instead of being calculated completely anew
+             */
+        }
+
+        return topIndex;
+    }
+    /**
+     * Returns the zero-relative index of the item which is currently at the bottom
+     * of the receiver. This index can change when items are scrolled, expanded
+     * or collapsed or new items are added or removed.
+     * <p>
+     * Note that the item with this index is often only partly visible; maybe only
+     * a single line of pixels is visible. Use {@link #isShown(GridItem)} to find
+     * out.
+     * <p>
+     * In extreme cases, getBottomIndex() may return the same value as
+     * {@link #getTopIndex()}.
+     * 
+     * @return the index of the bottom item
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    int getBottomIndex() {
+        checkWidget();
+
+        if (bottomIndex != -1)
+            return bottomIndex;
+
+        if (items.size() == 0)
+        {
+            bottomIndex = 0;
+        }
+        else if (getVisibleGridHeight()<1)
+        {
+            bottomIndex = getTopIndex();
+        }
+        else
+        {
+            RowRange range = getRowRange(getTopIndex(),getVisibleGridHeight(),false,false);
+
+            bottomIndex = range.endIndex;
+            bottomIndexShownCompletely = range.height <= getVisibleGridHeight();
+        }
+
+        return bottomIndex;
+    }
+    /**
+     * Returns a {@link RowRange} ranging from
+     * the grid item at startIndex to that at endIndex.
+     * <p>
+     * This is primarily used to measure the height
+     * in pixel of such a range and to count the number
+     * of visible grid items within the range.
+     * 
+     * @param startIndex index of the first item in the range or -1 to the first visible item in this grid
+     * @param endIndex index of the last item in the range or -1 to use the last visible item in this grid
+     * @return
+     */
+    private RowRange getRowRange(int startIndex, int endIndex) {
+
+        // parameter preparation
+        if (startIndex == -1)
+        {
+            // search frist visible item
+            do startIndex++; while (startIndex < items.size() && !((GridItem)items.get(startIndex)).isVisible());
+            if (startIndex == items.size()) return null;
+        }
+        if (endIndex == -1)
+        {
+            // search last visible item
+            endIndex = items.size();
+            do endIndex--; while (endIndex >= 0 && !((GridItem)items.get(endIndex)).isVisible());
+            if (endIndex == -1) return null;
+        }
+
+        // fail fast
+        if (startIndex<0 || endIndex<0 || startIndex>=items.size() || endIndex>=items.size()
+                || endIndex < startIndex
+                || ((GridItem)items.get(startIndex)).isVisible()==false
+                || ((GridItem)items.get(endIndex)).isVisible()==false)
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        RowRange range = new RowRange();
+        range.startIndex = startIndex;
+        range.endIndex = endIndex;
+
+        if(isTree || hasDifferingHeights)
+        {
+            for (int idx=startIndex ; idx<=endIndex ; idx++ )
+            {
+                GridItem currItem = (GridItem)items.get(idx);
+
+                if(currItem.isVisible())
+                {
+                    if (range.rows>0)
+                        range.height++;        // height of horizontal row separator
+                    range.height += currItem.getHeight();
+                    range.rows++;
+                }
+            }
+        }
+        else
+        {
+            range.rows = range.endIndex - range.startIndex + 1;
+            range.height = ( getItemHeight() + 1 ) * range.rows - 1;
+        }
+
+        return range;
+    }
+    /**
+     * This method can be used to build a range of grid rows
+     * that is allowed to span a certain height in pixels.
+     * <p>
+     * It returns a {@link RowRange} that contains information
+     * about the range, especially the index of the last
+     * element in the range (or if inverse == true, then the
+     * index of the first element).
+     * <p>
+     * Note:  Even if 'forceEndCompletelyInside' is set to
+     * true, the last item will not lie completely within
+     * the availableHeight, if (height of item at startIndex < availableHeight).
+     * 
+     * @param startIndex  index of the first (if inverse==false) or
+     *                    last (if inverse==true) item in the range
+     * @param availableHeight height in pixels
+     * @param forceEndCompletelyInside if true, the last item in the range will lie completely 
+     *        within the availableHeight, otherwise it may lie partly outside this range
+     * @param inverse  if true, then the first item in the range will be searched, not the last
+     * @return range of grid rows
+     * @see RowRange
+     */
+    private RowRange getRowRange(int startIndex, int availableHeight,
+                                 boolean forceEndCompletelyInside, boolean inverse) {
+        // parameter preparation
+        if (startIndex == -1)
+        {
+            if(!inverse)
+            {
+                // search frist visible item
+                do startIndex++; while (startIndex < items.size() && !((GridItem)items.get(startIndex)).isVisible());
+                if (startIndex == items.size()) return null;
+            }
+            else
+            {
+                // search last visible item
+                startIndex = items.size();
+                do startIndex--; while (startIndex >= 0 && !((GridItem)items.get(startIndex)).isVisible());
+                if (startIndex == -1) return null;
+            }
+        }
+
+        // fail fast
+        if (startIndex < 0 || startIndex >= items.size()
+                || ((GridItem)items.get(startIndex)).isVisible() == false)
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+        RowRange range = new RowRange();
+
+        if (availableHeight <= 0)
+        {
+            // special case: empty range
+            range.startIndex = startIndex;
+            range.endIndex = startIndex;
+            range.rows = 0;
+            range.height = 0;
+            return range;
+        }
+
+        if (isTree || hasDifferingHeights)
+        {
+            int otherIndex = startIndex;        // tentative end index
+            int consumedItems = 0;
+            int consumedHeight = 0;
+
+            // consume height for startEnd  (note: no separator pixel added here)
+            consumedItems++;
+            consumedHeight += ((GridItem)items.get(otherIndex)).getHeight();
+
+            // note: we use "+2" in next line, because we only try to add another row if there
+            // is room for the separator line + at least one pixel row for the additional item
+            while (consumedHeight+2 <= availableHeight)
+            {
+                // STEP 1:
+                // try to find a visible item we can add
+
+                int nextIndex = otherIndex;
+                GridItem nextItem;
+
+                do
+                {
+                    if (!inverse)
+                        nextIndex++;
+                    else
+                        nextIndex--;
+
+                    if (nextIndex >= 0 && nextIndex < items.size())
+                        nextItem = (GridItem)items.get(nextIndex);
+                    else
+                        nextItem = null;
+                }
+                while (nextItem != null && !nextItem.isVisible());
+
+
+                if (nextItem == null)
+                {
+                    // no visible item found
+                    break;
+                }
+
+                if (forceEndCompletelyInside)
+                {
+                    // must lie completely within the allowed height
+                    if(!(consumedHeight + 1 + nextItem.getHeight() <= availableHeight))
+                        break;
+                }
+
+                // we found one !!
+
+                // STEP 2:
+                // Consume height for this item
+
+                consumedItems++;
+                consumedHeight += 1;    // height of separator line
+                consumedHeight += nextItem.getHeight();
+            
+                // STEP 3:
+                // make this item it the current guess for the other end
+                otherIndex = nextIndex;
+            }
+
+            range.startIndex = !inverse ? startIndex : otherIndex;
+            range.endIndex   = !inverse ? otherIndex : startIndex;
+            range.rows       = consumedItems;
+            range.height     = consumedHeight;
+        }
+        else
+        {
+            int availableRows = ( availableHeight + 1 ) / ( getItemHeight() + 1 );
+
+            if ((( getItemHeight() + 1 ) * range.rows - 1) + 1 < availableHeight)
+            {
+                // not all available space used yet
+                // - so add another row if it need not be completely within availableHeight
+                if (!forceEndCompletelyInside)
+                    availableRows++;
+            }
+
+            int otherIndex = startIndex + ((availableRows - 1) * (!inverse ? 1 : -1));
+            if (otherIndex<0) otherIndex = 0;
+            if (otherIndex>=items.size()) otherIndex = items.size() - 1 ;
+
+            range.startIndex = !inverse ? startIndex : otherIndex;
+            range.endIndex   = !inverse ? otherIndex : startIndex;
+            range.rows       = range.endIndex - range.startIndex + 1;
+            range.height     = ( getItemHeight() + 1 ) * range.rows - 1;
+        }
+
+        return range;
+    }
+    /**
+     * Returns the height of the plain grid in pixels.
+     * <p>
+     * This includes all rows for visible items (i.e. items that return true
+     * on {@link GridItem#isVisible()} ; not only those currently visible on
+     * screen) and the 1 pixel separator between rows.
+     * <p>
+     * This does <em>not</em> include the height of the column headers.
+     * 
+     * @return height of plain grid
+     */
+    int getGridHeight() {
+        RowRange range = getRowRange(-1,-1);
+        return range != null ? range.height : 0;
+        /*
+         *  MOPR  currently this method is only used in #getTableSize() ;
+         *  if it will be used for more important things in the future
+         *  (e.g. the max value for vScroll.setValues() when doing pixel-by-pixel
+         *  vertical scrolling) then this value should at least be cached or
+         *  even updated incrementally when grid items are added/removed or
+         *  expaned/collapsed (similar as #currentVisibleItems).
+         *  (this is only necessary in the case (isTree || hasDifferingHeights))
+         */
+    }
+
+    /**
+     * Returns the height of the on-screen area that is available
+     * for showing the grid's rows, i.e. the client area of the
+     * scrollable minus the height of the column headers (if shown).
+     * 
+     * @return height of visible grid in pixels
+     */
+    int getVisibleGridHeight() {
+        return getClientArea().height - (columnHeadersVisible ? headerHeight : 0);
+    }
+
+    /**
+     * Gets the top left renderer.
+     * 
+     * @return Returns the topLeftRenderer.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public IRenderer getTopLeftRenderer()
+    {
+        checkWidget();
+        return topLeftRenderer;
+    }
+
+    /**
+     * Searches the receiver's list starting at the first column (index 0) until
+     * a column is found that is equal to the argument, and returns the index of
+     * that column. If no column is found, returns -1.
+     * 
+     * @param column the search column
+     * @return the index of the column
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the column is null</li>
+     * </ul>      
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int indexOf(GridColumn column)
+    {
+        checkWidget();
+        
+        if (column == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        if (column.getParent() != this) return -1;
+        
+        return columns.indexOf(column);
+    }
+
+    /**
+     * Searches the receiver's list starting at the first item (index 0) until
+     * an item is found that is equal to the argument, and returns the index of
+     * that item. If no item is found, returns -1.
+     * 
+     * @param item the search item
+     * @return the index of the item
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+     * </ul>  
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int indexOf(GridItem item)
+    {
+        checkWidget();
+        
+        if (item == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        if (item.getParent() != this) return -1;
+        
+        return items.indexOf(item);
+    }
+
+    /**
+     * Returns {@code true} if the receiver's row header is visible, and
+     * {@code false} otherwise.
+     * <p>
+     * 
+     * @return the receiver's row header's visibility state
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean isRowHeaderVisible()
+    {
+        checkWidget();
+        return rowHeaderVisible;
+    }
+
+    /**
+     * Returns {@code true} if the item is selected, and {@code false}
+     * otherwise. Indices out of range are ignored.  If cell selection is 
+     * enabled, returns true if the item at the given index contains at 
+     * least one selected cell.
+     * 
+     * @param index the index of the item
+     * @return the visibility state of the item at the index
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean isSelected(int index)
+    {
+        checkWidget();
+        
+        if (index < 0 || index >= items.size()) return false;
+        
+        if (!cellSelectionEnabled)
+        {
+            return isSelected((GridItem)items.get(index));
+        }
+        else
+        {
+            for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
+            {
+                Point cell = (Point)iter.next();
+                if (cell.y == index) return true;                
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Returns true if the given item is selected.  If cell selection is enabled,
+     * returns true if the given item contains at least one selected cell.
+     * 
+     * @param item item
+     * @return true if the item is selected.
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the item is null</li> 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean isSelected(GridItem item)
+    {
+        checkWidget();
+        if (!cellSelectionEnabled)
+        {
+            return selectedItems.contains(item);
+        }
+        else
+        {
+            int index = indexOf(item);
+            if (index == -1) return false;
+            for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
+            {
+                Point cell = (Point)iter.next();
+                if (cell.y == index) return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Returns true if the given cell is selected.
+     * 
+     * @param cell cell
+     * @return true if the cell is selected.
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the cell is null</li> 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean isCellSelected(Point cell)
+    {
+        checkWidget();
+        
+        if (cell == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        return selectedCells.contains(cell);
+    }
+    
+    
+    
+    /**
+     * Removes the item from the receiver at the given zero-relative index.
+     * 
+     * @param index the index for the item
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+     * of elements in the list minus 1 (inclusive)</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void remove(int index)
+    {
+        checkWidget();
+        if (index < 0 || index > items.size() - 1)
+        {
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        }
+        GridItem item = (GridItem)items.get(index);
+        item.dispose();
+        redraw();
+    }
+
+    /**
+     * Removes the items from the receiver which are between the given
+     * zero-relative start and end indices (inclusive).
+     * 
+     * @param start the start of the range
+     * @param end the end of the range
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0
+     * and the number of elements in the list minus 1 (inclusive)</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void remove(int start, int end)
+    {
+        checkWidget();
+
+        for (int i = end; i >= start; i--)
+        {
+            if (i < 0 || i > items.size() - 1)
+            {
+                SWT.error(SWT.ERROR_INVALID_RANGE);
+            }
+            GridItem item = (GridItem)items.get(i);
+            item.dispose();
+        }
+        redraw();
+    }
+
+    /**
+     * Removes the items from the receiver's list at the given zero-relative
+     * indices.
+     * 
+     * @param indices the array of indices of the items
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+     * of elements in the list minus 1 (inclusive)</li>
+     * <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void remove(int[] indices)
+    {
+        checkWidget();
+
+        if (indices == null)
+        {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+
+        GridItem[] removeThese = new GridItem[indices.length];
+        for (int i = 0; i < indices.length; i++)
+        {
+            int j = indices[i];
+            if (j < items.size() && j >= 0)
+            {
+                removeThese[i] = (GridItem)items.get(j);
+            }
+            else
+            {
+                SWT.error(SWT.ERROR_INVALID_RANGE);
+            }
+
+        }
+        for (int i = 0; i < removeThese.length; i++)
+        {
+            GridItem item = removeThese[i];
+            item.dispose();
+        }
+        redraw();
+    }
+
+    /**
+     * Removes all of the items from the receiver.
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void removeAll()
+    {
+        checkWidget();
+        
+        while (items.size() > 0)
+        {
+            ((GridItem)items.get(0)).dispose();
+        }
+        redraw();
+    }
+
+    /**
+     * Removes the listener from the collection of listeners who will be
+     * notified when the receiver's selection changes.
+     * 
+     * @param listener the listener which should no longer be notified
+     * @see SelectionListener
+     * @see #addSelectionListener(SelectionListener)
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void removeSelectionListener(SelectionListener listener)
+    {
+        checkWidget();
+        removeListener(SWT.Selection, listener);
+        removeListener(SWT.DefaultSelection, listener);
+    }
+
+    /**
+     * Removes the listener from the collection of listeners who will be
+     * notified when the receiver's items changes.
+     * 
+     * @param listener the listener which should no longer be notified
+     * @see TreeListener
+     * @see #addTreeListener(TreeListener)
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void removeTreeListener(TreeListener listener)
+    {
+        checkWidget();
+        removeListener(SWT.Expand, listener);
+        removeListener(SWT.Collapse, listener);
+    }
+
+    /**
+     * Selects the item at the given zero-relative index in the receiver. If the
+     * item at the index was already selected, it remains selected. Indices that
+     * are out of range are ignored. 
+     * <p>
+     * If cell selection is enabled, selects all cells at the given index.
+     * 
+     * @param index the index of the item to select
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void select(int index)
+    {
+        checkWidget();
+
+        if (!selectionEnabled) return;
+        
+        if (index < 0 || index >= items.size()) return;
+        
+        GridItem item = (GridItem)items.get(index);
+        
+        if (!cellSelectionEnabled)
+        {
+            if (selectionType == SWT.MULTI && selectedItems.contains(item)) return;
+
+            if (selectionType == SWT.SINGLE) selectedItems.clear();
+        
+            selectedItems.add(item);
+        }
+        else
+        {
+            selectCells(getCells(item));
+        }
+
+        redraw();
+    }
+
+    /**
+     * Selects the items in the range specified by the given zero-relative
+     * indices in the receiver. The range of indices is inclusive. The current
+     * selection is not cleared before the new items are selected.
+     * <p>
+     * If an item in the given range is not selected, it is selected. If an item
+     * in the given range was already selected, it remains selected. Indices
+     * that are out of range are ignored and no items will be selected if start
+     * is greater than end. If the receiver is single-select and there is more
+     * than one item in the given range, then all indices are ignored.
+     * <p>
+     * If cell selection is enabled, all cells within the given range are selected.
+     * 
+     * @param start the start of the range
+     * @param end the end of the range
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see Grid#setSelection(int,int)
+     */
+    public void select(int start, int end)
+    {
+        checkWidget();
+        
+        if (!selectionEnabled) return;
+        
+        if (selectionType == SWT.SINGLE && start != end) return;
+        
+        if (!cellSelectionEnabled)
+        {
+            if (selectionType == SWT.SINGLE) selectedItems.clear();            
+        }
+        
+        for (int i = start; i <= end; i++)
+        {
+            if (i < 0)
+            {
+                continue;
+            }
+            if (i > items.size() - 1)
+            {
+                break;
+            }
+
+            GridItem item = (GridItem)items.get(i);
+            
+            if (!cellSelectionEnabled)
+            {
+                if (!selectedItems.contains(item))
+                    selectedItems.add(item);
+            }
+            else
+            {
+                selectCells(getCells(item));
+            }
+        }
+        
+        redraw();
+    }
+
+    /**
+     * Selects the items at the given zero-relative indices in the receiver. The
+     * current selection is not cleared before the new items are selected.
+     * <p>
+     * If the item at a given index is not selected, it is selected. If the item
+     * at a given index was already selected, it remains selected. Indices that
+     * are out of range and duplicate indices are ignored. If the receiver is
+     * single-select and multiple indices are specified, then all indices are
+     * ignored.
+     * <p>
+     * If cell selection is enabled, all cells within the given indices are 
+     * selected.
+     * 
+     * @param indices the array of indices for the items to select
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see Grid#setSelection(int[])
+     */
+    public void select(int[] indices)
+    {
+        checkWidget();
+
+        if (indices == null)
+        {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        
+        if (!selectionEnabled) return;
+        
+        if (selectionType == SWT.SINGLE && indices.length > 1) return;
+        
+        if (!cellSelectionEnabled)
+            if (selectionType == SWT.SINGLE) selectedItems.clear();
+
+        for (int i = 0; i < indices.length; i++)
+        {
+            int j = indices[i];
+
+            if (j >= 0 && j < items.size())
+            {
+                GridItem item = (GridItem)items.get(j);
+                
+                if (!cellSelectionEnabled)
+                {
+                    if (!selectedItems.contains(item))
+                        selectedItems.add(item);
+                }
+                else
+                {
+                    selectCells(getCells(item));
+                }
+            }
+        }
+        redraw();
+    }
+
+    /**
+     * Selects all of the items in the receiver.
+     * <p>
+     * If the receiver is single-select, do nothing.  If cell selection is enabled,
+     * all cells are selected.
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void selectAll()
+    {
+        checkWidget();
+        
+        if (!selectionEnabled) return;
+        
+        if (selectionType == SWT.SINGLE) return;
+        
+        if (cellSelectionEnabled)
+        {
+            selectAllCells();
+            return;
+        }
+        
+        selectedItems.clear();
+        selectedItems.addAll(items);
+        redraw();
+    }
+
+    /**
+     * Sets the empty cell renderer.
+     * 
+     * @param emptyCellRenderer The emptyCellRenderer to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setEmptyCellRenderer(GridCellRenderer emptyCellRenderer)
+    {
+        checkWidget();
+        emptyCellRenderer.setDisplay(getDisplay());
+        this.emptyCellRenderer = emptyCellRenderer;
+    }
+
+    /**
+     * Sets the empty column header renderer.
+     * 
+     * @param emptyColumnHeaderRenderer The emptyColumnHeaderRenderer to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setEmptyColumnHeaderRenderer(IRenderer emptyColumnHeaderRenderer)
+    {
+        checkWidget();
+        emptyColumnHeaderRenderer.setDisplay(getDisplay());
+        this.emptyColumnHeaderRenderer = emptyColumnHeaderRenderer;
+    }
+
+    /**
+     * Sets the empty row header renderer.
+     * 
+     * @param emptyRowHeaderRenderer The emptyRowHeaderRenderer to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setEmptyRowHeaderRenderer(IRenderer emptyRowHeaderRenderer)
+    {
+        checkWidget();
+        emptyRowHeaderRenderer.setDisplay(getDisplay());
+        this.emptyRowHeaderRenderer = emptyRowHeaderRenderer;
+    }
+
+    /**
+     * Sets the external horizontal scrollbar. Allows the scrolling to be
+     * managed externally from the table. This functionality is only intended
+     * when SWT.H_SCROLL is not given.
+     * <p>
+     * Using this feature, a ScrollBar could be instantiated outside the table,
+     * wrapped in IScrollBar and thus be 'connected' to the table.
+     * 
+     * @param scroll The horizontal scrollbar to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    protected void setHorizontalScrollBarProxy(IScrollBarProxy scroll)
+    {
+        checkWidget();
+        if (getHorizontalBar() != null)
+        {
+            return;
+        }
+        hScroll = scroll;
+        
+        hScroll.addSelectionListener(new SelectionListener() {
+            public void widgetSelected(SelectionEvent e) {
+                onScrollSelection();
+            }
+
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+    }
+
+    /**
+     * Sets the external vertical scrollbar. Allows the scrolling to be managed
+     * externally from the table. This functionality is only intended when
+     * SWT.V_SCROLL is not given.
+     * <p>
+     * Using this feature, a ScrollBar could be instantiated outside the table,
+     * wrapped in IScrollBar and thus be 'connected' to the table.
+     * 
+     * @param scroll
+     *            The vertical scrollbar to set.
+     * @throws org.eclipse.swt.SWTException
+     *             <ul>
+     *             <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+     *             disposed</li>
+     *             <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+     *             thread that created the receiver</li>
+     *             </ul>
+     */
+    protected void setlVerticalScrollBarProxy(IScrollBarProxy scroll)
+    {
+        checkWidget();
+        if (getVerticalBar() != null)
+        {
+            return;
+        }
+        vScroll = scroll;
+        
+        vScroll.addSelectionListener(new SelectionListener() {
+            public void widgetSelected(SelectionEvent e) {
+                onScrollSelection();
+            }
+
+            public void widgetDefaultSelected(SelectionEvent e) {
+            }
+        });
+    }
+
+    /**
+     * Sets the focus renderer.
+     * 
+     * @param focusRenderer The focusRenderer to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setFocusRenderer(IRenderer focusRenderer)
+    {
+        checkWidget();
+        this.focusRenderer = focusRenderer;
+    }
+
+    /**
+     * Marks the receiver's header as visible if the argument is {@code true},
+     * and marks it invisible otherwise.
+     * 
+     * @param show the new visibility state
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setHeaderVisible(boolean show)
+    {
+        checkWidget();
+        this.columnHeadersVisible = show;
+        redraw();
+    }
+
+    /**
+     * Sets the line color.
+     * 
+     * @param lineColor The lineColor to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setLineColor(Color lineColor)
+    {
+        checkWidget();
+        this.lineColor = lineColor;
+    }
+
+    /**
+     * Sets the line visibility.
+     * 
+     * @param linesVisible Te linesVisible to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setLinesVisible(boolean linesVisible)
+    {
+        checkWidget();
+        this.linesVisible = linesVisible;
+        redraw();
+    }
+
+    /**
+     * Sets the tree line visibility.
+     * 
+     * @param treeLinesVisible
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setTreeLinesVisible(boolean treeLinesVisible) {
+        checkWidget();
+        this.treeLinesVisible = treeLinesVisible;
+        redraw();
+    }
+
+    /**
+     * Sets the row header renderer.
+     * 
+     * @param rowHeaderRenderer The rowHeaderRenderer to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setRowHeaderRenderer(IRenderer rowHeaderRenderer)
+    {
+        checkWidget();
+        rowHeaderRenderer.setDisplay(getDisplay());
+        this.rowHeaderRenderer = rowHeaderRenderer;
+    }
+
+    /**
+     * Marks the receiver's row header as visible if the argument is
+     * {@code true}, and marks it invisible otherwise. When row headers are
+     * visible, horizontal scrolling is always done by column rather than by
+     * pixel.
+     * 
+     * @param show the new visibility state
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setRowHeaderVisible(boolean show)
+    {
+        checkWidget();
+        this.rowHeaderVisible = show;
+        setColumnScrolling(true);
+        
+        if (show)
+        {
+            rowHeaderWidth = 1;
+            
+            for (Iterator iter = items.iterator(); iter.hasNext();)
+            {
+                GridItem iterItem = (GridItem)iter.next();
+                rowHeaderWidth = Math.max(rowHeaderWidth,rowHeaderRenderer.computeSize(sizingGC, SWT.DEFAULT,SWT.DEFAULT,iterItem).x);
+            }
+        }
+        
+        redraw();
+    }
+
+    /**
+     * Selects the item at the given zero-relative index in the receiver. The
+     * current selection is first cleared, then the new item is selected.
+     * <p>
+     * If cell selection is enabled, all cells within the item at the given index
+     * are selected.
+     * 
+     * @param index the index of the item to select
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setSelection(int index)
+    {
+        checkWidget();        
+        
+        if (!selectionEnabled) return;
+        
+        if (index >= 0 && index < items.size())
+        {
+            if (!cellSelectionEnabled)
+            {
+                selectedItems.clear();
+                selectedItems.add((GridItem)items.get(index));
+                redraw();
+            }
+            else
+            {
+                selectedCells.clear();
+                selectCells(getCells((GridItem)items.get(index)));
+            }
+        }
+    }
+
+    /**
+     * Selects the items in the range specified by the given zero-relative
+     * indices in the receiver. The range of indices is inclusive. The current
+     * selection is cleared before the new items are selected.
+     * <p>
+     * Indices that are out of range are ignored and no items will be selected
+     * if start is greater than end. If the receiver is single-select and there
+     * is more than one item in the given range, then all indices are ignored.
+     * <p>
+     * If cell selection is enabled, all cells within the given range are selected.
+     * 
+     * @param start the start index of the items to select
+     * @param end the end index of the items to select
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see Grid#deselectAll()
+     * @see Grid#select(int,int)
+     */
+    public void setSelection(int start, int end)
+    {
+        checkWidget();
+        
+        if (!selectionEnabled) return;
+        
+        if (selectionType == SWT.SINGLE && start != end) return;
+
+        if (!cellSelectionEnabled)
+        {
+            selectedItems.clear();    
+        }
+        else
+        {
+            selectedCells.clear();
+        }
+        
+        for (int i = start; i <= end; i++)
+        {
+            if (i < 0)
+            {
+                continue;
+            }
+            if (i > items.size() - 1)
+            {
+                break;
+            }
+
+            GridItem item = (GridItem)items.get(i);
+            
+            if (!cellSelectionEnabled)
+            {
+                selectedItems.add(item);
+            }
+            else
+            {
+                selectCells(getCells(item));
+            }
+        }
+        redraw();
+    }
+
+    /**
+     * Selects the items at the given zero-relative indices in the receiver. The
+     * current selection is cleared before the new items are selected.
+     * <p>
+     * Indices that are out of range and duplicate indices are ignored. If the
+     * receiver is single-select and multiple indices are specified, then all
+     * indices are ignored.
+     * <p>
+     * If cell selection is enabled, all cells within the given indices are selected.
+     * 
+     * @param indices the indices of the items to select
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see Grid#deselectAll()
+     * @see Grid#select(int[])
+     */
+    public void setSelection(int[] indices)
+    {
+        checkWidget();
+        
+        if (!selectionEnabled) return;
+        
+        if (selectionType == SWT.SINGLE && indices.length > 1) return;
+
+        if (!cellSelectionEnabled)
+        {
+            selectedItems.clear();    
+        }
+        else
+        {
+            selectedCells.clear();
+        }
+        
+        for (int i = 0; i < indices.length; i++)
+        {
+            int j = indices[i];
+
+            if (j < 0)
+            {
+                continue;
+            }
+            if (j > items.size() - 1)
+            {
+                break;
+            }
+
+            GridItem item = (GridItem)items.get(j);
+            
+            if (!cellSelectionEnabled)
+            {
+                selectedItems.add(item);    
+            }
+            else
+            {
+                selectCells(getCells(item));
+            }
+        }
+        redraw();
+    }
+
+    /**
+     * Sets the receiver's selection to be the given array of items. The current
+     * selection is cleared before the new items are selected.
+     * <p>
+     * Items that are not in the receiver are ignored. If the receiver is
+     * single-select and multiple items are specified, then all items are
+     * ignored.  If cell selection is enabled, all cells within the given items
+     * are selected.
+     * 
+     * @param _items the array of items
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li>
+     * <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     * @see Grid#deselectAll()
+     * @see Grid#select(int[])
+     * @see Grid#setSelection(int[])
+     */
+    public void setSelection(GridItem[] _items)
+    {
+        checkWidget();
+        
+        if (!selectionEnabled) return;
+        
+        if (_items == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        if (selectionType == SWT.SINGLE && _items.length > 1) return;
+        
+        if (!cellSelectionEnabled)
+        {
+            selectedItems.clear();
+        }
+        else
+        {
+            selectedCells.clear();
+        }
+        
+        for (int i = 0; i < _items.length; i++)
+        {
+            GridItem item = _items[i];
+            if (item == null) continue;
+            if (item.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            if (item.getParent() != this) continue;
+            
+            if (!cellSelectionEnabled)
+            {
+                selectedItems.add(item);
+            }
+            else
+            {
+                selectCells(getCells(item));
+            }
+        }
+        
+        redraw();
+    }
+
+    /**
+     * Sets the zero-relative index of the item which is currently at the top of
+     * the receiver. This index can change when items are scrolled or new items
+     * are added and removed.
+     * 
+     * @param index the index of the top item
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setTopIndex(int index)
+    {
+        checkWidget();
+        if (index < 0 || index >= items.size())
+        {
+            return;
+        }
+
+        GridItem item = (GridItem)items.get(index);
+        if (!item.isVisible())
+        {
+            return;
+        }
+
+        if (!vScroll.getVisible())
+        {
+            return;
+        }
+
+        int vScrollAmount = 0;
+
+        for (int i = 0; i < index; i++)
+        {
+            if (((GridItem)items.get(i)).isVisible())
+            {
+                vScrollAmount++;
+            }
+        }
+
+        vScroll.setSelection(vScrollAmount);
+        topIndex = -1;
+        bottomIndex = -1;
+        redraw();
+    }
+
+    /**
+     * Sets the top left renderer.
+     * 
+     * @param topLeftRenderer The topLeftRenderer to set.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setTopLeftRenderer(IRenderer topLeftRenderer)
+    {
+        checkWidget();
+        topLeftRenderer.setDisplay(getDisplay());
+        this.topLeftRenderer = topLeftRenderer;
+    }
+
+    /**
+     * Shows the column. If the column is already showing in the receiver, this
+     * method simply returns. Otherwise, the columns are scrolled until the
+     * column is visible.
+     * 
+     * @param col the column to be shown
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void showColumn(GridColumn col)
+    {
+        checkWidget();
+        
+        if (!col.isVisible())
+        {
+            GridColumnGroup group = col.getColumnGroup();
+            group.setExpanded(!group.getExpanded());
+            if (group.getExpanded())
+            {
+                group.notifyListeners(SWT.Expand,new Event());
+            }
+            else
+            {
+                group.notifyListeners(SWT.Collapse,new Event());
+            }
+        }
+
+        if (!hScroll.getVisible())
+        {
+            return;
+        }
+
+        int x = getColumnHeaderXPosition(col);
+        
+        int firstVisibleX = 0;
+        if (rowHeaderVisible)
+        {
+            firstVisibleX = rowHeaderWidth;
+        }
+        
+        // if its visible just return
+        if (x >= firstVisibleX
+            && (x + col.getWidth()) <= (firstVisibleX + (getClientArea().width - firstVisibleX)))
+        {
+            return;
+        }
+
+        if (!getColumnScrolling())
+        {
+            if (x < firstVisibleX)
+            {
+                hScroll.setSelection(getHScrollSelectionInPixels() - (firstVisibleX - x));
+            }
+            else
+            {
+                if (col.getWidth() > getClientArea().width - firstVisibleX)
+                {
+                    hScroll.setSelection(getHScrollSelectionInPixels() + (x - firstVisibleX));
+                }
+                else
+                {
+                    x -= getClientArea().width - firstVisibleX - col.getWidth();
+                    hScroll.setSelection(getHScrollSelectionInPixels() + (x - firstVisibleX));
+                }
+            }
+        }
+        else
+        {
+            if (x < firstVisibleX || col.getWidth() > getClientArea().width - firstVisibleX)
+            {
+                int sel = displayOrderedColumns.indexOf(col);
+                hScroll.setSelection(sel);
+            }
+            else
+            {
+                int availableWidth = getClientArea().width - firstVisibleX - col.getWidth();
+                
+                GridColumn prevCol = getPreviousVisibleColumn(col);
+                GridColumn currentScrollTo = col;
+                
+                while (true)
+                {
+                    if (prevCol == null || prevCol.getWidth() > availableWidth)
+                    {
+                        int sel = displayOrderedColumns.indexOf(currentScrollTo);
+                        hScroll.setSelection(sel);
+                        break;
+                    }
+                    else
+                    {
+                        availableWidth -= prevCol.getWidth();
+                        currentScrollTo = prevCol;
+                        prevCol = getPreviousVisibleColumn(prevCol);
+                    }
+                }
+            }
+        }
+
+        redraw();
+    }
+
+    /**
+     * Returns true if 'item' is currently being <em>completely</em>
+     * shown in this <code>Grid</code>'s visible on-screen area.
+     * 
+     * <p>Here, "completely" only refers to the item's height, not its
+     * width. This means this method returns true also if some cells
+     * are horizontally scrolled away.
+     * 
+     * @param item
+     * @return true if 'item' is shown
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * <li>ERROR_INVALID_ARGUMENT - if 'item' is not contained in the receiver</li>
+     * </ul>
+     */
+    boolean isShown(GridItem item)
+    {
+        checkWidget();
+
+        if(!item.isVisible())
+            return false;
+
+        int itemIndex = items.indexOf(item);
+
+        if (itemIndex == -1)
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+        int firstVisibleIndex = getTopIndex();
+        int lastVisibleIndex = getBottomIndex();
+
+        return (itemIndex >= firstVisibleIndex && itemIndex < lastVisibleIndex)
+               ||
+               (itemIndex == lastVisibleIndex && bottomIndexShownCompletely);
+    }
+    /**
+     * Shows the item. If the item is already showing in the receiver, this
+     * method simply returns. Otherwise, the items are scrolled until the item
+     * is visible.
+     * 
+     * @param item the item to be shown
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * <li>ERROR_INVALID_ARGUMENT - if 'item' is not contained in the receiver</li>
+     * </ul>
+     */
+    public void showItem(GridItem item)
+    {        
+        checkWidget();
+        
+        updateScrollbars();
+
+        // if no items are visible on screen then abort
+        if (getVisibleGridHeight()<1)
+        {
+            return;
+        }
+
+        // if its visible just return
+        if (isShown(item))
+        {
+            return;
+        }
+
+        if (!item.isVisible())
+        {
+            GridItem parent = item.getParentItem();
+            do
+            {
+                if (!parent.isExpanded())
+                {
+                    parent.setExpanded(true);
+                    parent.fireEvent(SWT.Expand);
+                }
+                parent = parent.getParentItem();
+            }
+            while (parent != null);            
+        }
+
+        int newTopIndex = items.indexOf(item);
+
+        if (newTopIndex >= getBottomIndex())
+        {
+            RowRange range = getRowRange(newTopIndex,getVisibleGridHeight(),true,true);    // note: inverse==true
+            newTopIndex = range.startIndex;        // note: use startIndex because of inverse==true
+        }
+
+        setTopIndex(newTopIndex);
+    }
+
+    /**
+     * Shows the selection. If the selection is already showing in the receiver,
+     * this method simply returns. Otherwise, the items are scrolled until the
+     * selection is visible.
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void showSelection()
+    {
+        checkWidget();
+        
+        if (scrollValuesObsolete) 
+            updateScrollbars();
+        
+        GridItem item = null;
+
+        if (!cellSelectionEnabled)
+        {
+            if (selectedItems.size() == 0)
+            {
+                return;
+            }
+    
+            item = (GridItem)selectedItems.get(0);
+            showItem(item);
+        }
+        else
+        {
+            if (selectedCells.size() == 0) return;
+            
+            Point cell = (Point)selectedCells.get(0);
+            item = getItem(cell.y);
+            showItem(item);
+            GridColumn col = getColumn(cell.x);
+            showColumn(col);
+        }
+        
+    }
+    
+    /**
+     * Enables selection highlighting if the argument is <code>true</code>.  
+     * 
+     * @param selectionEnabled the selection enabled state
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setSelectionEnabled(boolean selectionEnabled)
+    {
+        checkWidget();
+        
+        if (!selectionEnabled)
+        {
+            selectedItems.clear();
+            redraw();
+        }
+        
+        this.selectionEnabled = selectionEnabled;
+    }
+    
+    /**
+     * Returns <code>true</code> if selection is enabled, false otherwise.
+     * 
+     * @return the selection enabled state
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean getSelectionEnabled()
+    {
+        checkWidget();
+        return selectionEnabled;
+    }
+    
+
+    /**
+     * Computes and sets the height of the header row. This method will ask for
+     * the preferred size of all the column headers and use the max.
+     * 
+     * @param gc GC for font metrics, etc.
+     */
+    private void computeHeaderHeight(GC gc)
+    {
+
+        int colHeaderHeight = 0;
+        for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext(); )
+        {
+            GridColumn column = (GridColumn) columnsIterator.next();
+            colHeaderHeight = Math
+                .max(column.getHeaderRenderer().computeSize(gc, column.getWidth(), SWT.DEFAULT,
+                                                            column).y, colHeaderHeight);
+        }
+
+        int groupHeight = 0;
+        for (int groupIndex = 0; groupIndex < columnGroups.length; groupIndex++)
+        {
+            GridColumnGroup group = (GridColumnGroup) columnGroups[groupIndex];
+            groupHeight = Math.max(group.getHeaderRenderer().computeSize(gc, SWT.DEFAULT,
+                                                                         SWT.DEFAULT, group).y,
+                                   groupHeight);
+        }
+
+        headerHeight = colHeaderHeight + groupHeight;
+        groupHeaderHeight = groupHeight;
+    }
+
+    /**
+     * Returns the computed default item height. Currently this method just gets the
+     * preferred size of all the cells in the given row and returns that (it is
+     * then used as the height of all rows with items having a height of -1).
+     * 
+     * @param item item to use for sizing
+     * @param gc GC used to perform font metrics,etc.
+     * @return the row height
+     */
+    private int computeItemHeight(GridItem item, GC gc)
+    {
+        int height = 1;
+
+        if (columns.size() == 0 || items.size() == 0)
+        {
+            return height;
+        }
+
+        for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext(); )
+        {
+            GridColumn column = (GridColumn) columnsIterator.next();
+            height = Math.max(height, column.getCellRenderer().computeSize(gc, SWT.DEFAULT,
+                                                                           SWT.DEFAULT,
+                                                                           item).y);
+        }
+
+        return height <= 0 ? 16 : height;
+    }
+
+    /**
+     * Returns the x position of the given column. Takes into account scroll
+     * position.
+     * 
+     * @param column given column
+     * @return x position
+     */
+    private int getColumnHeaderXPosition(GridColumn column)
+    {
+        if (!column.isVisible())
+        {
+            return -1;
+        }
+
+        int x = 0;
+
+        x -= getHScrollSelectionInPixels();
+
+        if (rowHeaderVisible)
+        {
+            x += rowHeaderWidth;
+        }
+        for (Iterator column2Iterator = displayOrderedColumns.iterator(); column2Iterator.hasNext(); )
+        {
+            GridColumn column2 = (GridColumn) column2Iterator.next();
+
+            if (!column2.isVisible())
+            {
+                continue;
+            }
+
+            if (column2 == column)
+            {
+                break;
+            }
+
+            x += column2.getWidth();
+        }
+
+        return x;
+    }
+
+    /**
+     * Returns the hscroll selection in pixels. This method abstracts away the
+     * differences between column by column scrolling and pixel based scrolling.
+     * 
+     * @return the horizontal scroll selection in pixels
+     */
+    private int getHScrollSelectionInPixels()
+    {
+        int selection = hScroll.getSelection();
+        if (columnScrolling)
+        {
+            int pixels = 0;
+            for (int i = 0; i < selection; i++)
+            {
+                pixels += ((GridColumn)displayOrderedColumns.get(i)).getWidth();
+            }
+            selection = pixels;
+        }
+        return selection;
+    }
+
+    /**
+     * Returns the size of the preferred size of the inner table.
+     * 
+     * @return the preferred size of the table.
+     */
+    private Point getTableSize()
+    {
+        int x = 0;
+        int y = 0;
+
+        if (columnHeadersVisible)
+        {
+            y += headerHeight;
+        }
+
+        y += getGridHeight();
+
+        if (rowHeaderVisible)
+        {
+            x += rowHeaderWidth;
+        }
+
+        for (Iterator columnIterator = columns.iterator(); columnIterator.hasNext(); )
+        {
+            GridColumn column = (GridColumn) columnIterator.next();
+            if (column.isVisible())
+            {
+                x += column.getWidth();
+            }
+        }
+
+        return new Point(x, y);
+    }
+
+    /**
+     * Manages the header column dragging and calculates the drop point,
+     * triggers a redraw.
+     * 
+     * @param x mouse x
+     * @return true if this event has been consumed.
+     */
+    private boolean handleColumnDragging(int x)
+    {
+
+        GridColumn local_dragDropBeforeColumn = null;
+        GridColumn local_dragDropAfterColumn = null;
+
+        int x2 = 1;
+
+        if (rowHeaderVisible)
+        {
+            x2 += rowHeaderWidth + 1;
+        }
+
+        x2 -= getHScrollSelectionInPixels();
+
+        int i = 0;
+        GridColumn previousVisibleCol = null;
+        boolean nextVisibleColumnIsBeforeCol = false;
+        GridColumn firstVisibleCol = null;
+        GridColumn lastVisibleCol = null;
+
+        if (x < x2)
+        {
+            for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
+            {
+                GridColumn column = (GridColumn) columnIterator.next();
+                if (!column.isVisible())
+                {
+                    continue;
+                }
+                local_dragDropBeforeColumn = column;
+                break;
+            }
+            local_dragDropAfterColumn = null;
+        }
+        else
+        {
+            for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
+            {
+                GridColumn column = (GridColumn) columnIterator.next();
+                if (!column.isVisible())
+                {
+                    continue;
+                }
+
+                i++;
+
+                if (firstVisibleCol == null)
+                {
+                    firstVisibleCol = column;
+                }
+                lastVisibleCol = column;
+
+                if (nextVisibleColumnIsBeforeCol)
+                {
+                    local_dragDropBeforeColumn = column;
+                    nextVisibleColumnIsBeforeCol = false;
+                }
+
+                if (x >= x2 && x <= (x2 + column.getWidth()))
+                {
+                    if (x <= (x2 + column.getWidth() / 2))
+                    {
+                        local_dragDropBeforeColumn = column;
+                        local_dragDropAfterColumn = previousVisibleCol;
+                    }
+                    else
+                    {
+                        local_dragDropAfterColumn = column;
+
+                        // the next visible column is the before col
+                        nextVisibleColumnIsBeforeCol = true;
+                    }
+                }
+
+                x2 += column.getWidth();
+                previousVisibleCol = column;
+            }
+
+            if (local_dragDropBeforeColumn == null)
+            {
+                local_dragDropAfterColumn = lastVisibleCol;
+            }
+        }
+
+        currentHeaderDragX = x;
+
+        if (local_dragDropBeforeColumn != dragDropBeforeColumn
+            || (dragDropBeforeColumn == null && dragDropAfterColumn == null))
+        {
+            dragDropPointValid = true;
+
+            // Determine if valid drop point
+            if (columnGroups.length != 0)
+            {
+
+                if (columnBeingPushed.getColumnGroup() == null)
+                {
+                    if (local_dragDropBeforeColumn != null
+                        && local_dragDropAfterColumn != null
+                        && local_dragDropBeforeColumn.getColumnGroup() != null
+                        && local_dragDropBeforeColumn.getColumnGroup() == local_dragDropAfterColumn
+                            .getColumnGroup())
+                    {
+                        // Dont move a column w/o a group in between two columns
+                        // in the same group
+                        dragDropPointValid = false;
+                    }
+                }
+                else
+                {
+                    if (!(local_dragDropBeforeColumn != null && local_dragDropBeforeColumn
+                        .getColumnGroup() == columnBeingPushed.getColumnGroup())
+                        && !(local_dragDropAfterColumn != null && local_dragDropAfterColumn
+                            .getColumnGroup() == columnBeingPushed.getColumnGroup()))
+                    {
+                        // Dont move a column with a group
+                        dragDropPointValid = false;
+                    }
+                }
+            }
+            else
+            {
+                dragDropPointValid = true;
+            }
+        }
+
+        dragDropBeforeColumn = local_dragDropBeforeColumn;
+        dragDropAfterColumn = local_dragDropAfterColumn;
+
+        Rectangle clientArea = getClientArea();
+        redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+
+        return true;
+    }
+
+    /**
+     * Handles the moving of columns after a column is dropped.
+     */
+    private void handleColumnDrop()
+    {
+        draggingColumn = false;
+
+        if ((dragDropBeforeColumn != columnBeingPushed && dragDropAfterColumn != columnBeingPushed)
+            && (columnGroups.length == 0 || dragDropPointValid))
+        {
+
+            int notifyFrom = displayOrderedColumns.indexOf(columnBeingPushed);
+            int notifyTo = notifyFrom;
+                
+            displayOrderedColumns.remove(columnBeingPushed);
+
+            if (dragDropBeforeColumn == null)
+            {
+                
+                notifyTo = displayOrderedColumns.size();
+                displayOrderedColumns.add(columnBeingPushed);
+            }
+            else if (dragDropAfterColumn == null)
+            {
+                displayOrderedColumns.add(0, columnBeingPushed);
+                notifyFrom = 0;
+            }
+            else
+            {
+                int insertAtIndex = 0;
+
+                if (columnGroups.length != 0)
+                {
+                    // ensure that we aren't putting this column into a group,
+                    // this is possible if
+                    // there are invisible columns between the after and before
+                    // cols
+
+                    if (dragDropBeforeColumn.getColumnGroup() == columnBeingPushed.getColumnGroup())
+                    {
+                        insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+                    }
+                    else if (dragDropAfterColumn.getColumnGroup() == columnBeingPushed
+                        .getColumnGroup())
+                    {
+                        insertAtIndex = displayOrderedColumns.indexOf(dragDropAfterColumn) + 1;
+                    }
+                    else
+                    {
+                        if (dragDropBeforeColumn.getColumnGroup() == null)
+                        {
+                            insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+                        }
+                        else
+                        {
+                            GridColumnGroup beforeGroup = dragDropBeforeColumn.getColumnGroup();
+                            insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+                            while (insertAtIndex > 0
+                                   && ((GridColumn)displayOrderedColumns.get(insertAtIndex -1)).getColumnGroup() == beforeGroup)
+                            {
+                                insertAtIndex--;
+                            }
+
+                        }
+                    }
+                }
+                else
+                {
+                    insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+                }
+                displayOrderedColumns.add(insertAtIndex, columnBeingPushed);
+                notifyFrom = Math.min(notifyFrom, insertAtIndex);
+                notifyTo = Math.max(notifyTo, insertAtIndex);
+            }
+
+            for (int i = notifyFrom; i <= notifyTo; i++)
+            {
+                ((GridColumn)displayOrderedColumns.get(i)).fireMoved();
+            }
+        }
+
+        redraw();
+    }
+
+    /**
+     * Determines if the mouse is pushing the header but has since move out of
+     * the header bounds and therefore should be drawn unpushed. Also initiates
+     * a column header drag when appropriate.
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return true if this event has been consumed.
+     */
+    private boolean handleColumnHeaderHoverWhilePushing(int x, int y)
+    {
+        GridColumn overThis = overColumnHeader(x, y);
+
+        if ((overThis == columnBeingPushed) != pushingAndHovering)
+        {
+            pushingAndHovering = (overThis == columnBeingPushed);
+            redraw();
+        }
+        if (columnBeingPushed.getMoveable())
+        {
+
+            if (pushingAndHovering && Math.abs(startHeaderPushX - x) > 3)
+            {
+
+                // stop pushing
+                pushingColumn = false;
+                columnBeingPushed.getHeaderRenderer().setMouseDown(false);
+                columnBeingPushed.getHeaderRenderer().setHover(false);
+
+                // now dragging
+                draggingColumn = true;
+                columnBeingPushed.getHeaderRenderer().setMouseDown(false);
+
+                startHeaderDragX = x;
+
+                dragDropAfterColumn = null;
+                dragDropBeforeColumn = null;
+                dragDropPointValid = true;
+
+                handleColumnDragging(x);
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Determines if a column group header has been clicked and forwards the
+     * event to the header renderer.
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return true if this event has been consumed.
+     */
+    private boolean handleColumnGroupHeaderClick(int x, int y)
+    {
+
+        if (!columnHeadersVisible)
+        {
+            return false;
+        }
+
+        GridColumnGroup overThis = overColumnGroupHeader(x, y);
+
+        if (overThis == null)
+        {
+            return false;
+        }
+
+        int headerX = 0;
+        if (rowHeaderVisible)
+        {
+            headerX += rowHeaderWidth;
+        }
+
+        int width = 0;
+        boolean firstCol = false;
+
+        for (Iterator colIterator = displayOrderedColumns.iterator(); colIterator.hasNext(); )
+        {
+            GridColumn col = (GridColumn) colIterator.next();
+            if (col.getColumnGroup() == overThis && col.isVisible())
+            {
+                firstCol = true;
+                width += col.getWidth();
+            }
+            if (!firstCol && col.isVisible())
+            {
+                headerX += col.getWidth();
+            }
+        }
+
+        overThis.getHeaderRenderer().setBounds(headerX - getHScrollSelectionInPixels(), 0, width,
+                                               groupHeaderHeight);
+        return overThis.getHeaderRenderer()
+            .notify(IInternalWidget.LeftMouseButtonDown, new Point(x, y), overThis);
+    }
+
+    /**
+     * Determines if a column header has been clicked, updates the renderer
+     * state and triggers a redraw if necesary.
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return true if this event has been consumed.
+     */
+    private boolean handleColumnHeaderPush(int x, int y)
+    {
+        if (!columnHeadersVisible)
+        {
+            return false;
+        }
+
+        GridColumn overThis = overColumnHeader(x, y);
+
+        if (overThis == null)
+        {
+            return false;
+        }
+        
+        if (cellSelectionEnabled && overThis.getMoveable() == false)
+        {
+            return false;
+        }      
+
+        columnBeingPushed = overThis;
+
+        // draw pushed
+        columnBeingPushed.getHeaderRenderer().setMouseDown(true);
+        columnBeingPushed.getHeaderRenderer().setHover(true);
+        pushingAndHovering = true;
+        redraw();
+
+        startHeaderPushX = x;
+        pushingColumn = true;
+        
+        setCapture(true);
+
+        return true;
+    }
+
+    /**
+     * Sets the new width of the column being resized and fires the appropriate
+     * listeners.
+     * 
+     * @param x mouse x
+     */
+    private void handleColumnResizerDragging(int x)
+    {
+        int newWidth = resizingColumnStartWidth + (x - resizingStartX);
+        if (newWidth < MIN_COLUMN_HEADER_WIDTH)
+        {
+            newWidth = MIN_COLUMN_HEADER_WIDTH;
+        }
+        
+        if (columnScrolling)
+        {
+            int maxWidth = getClientArea().width;
+            if (rowHeaderVisible)
+                maxWidth -= rowHeaderWidth;
+            if (newWidth > maxWidth)
+                newWidth = maxWidth;            
+        }
+        
+        if (newWidth == columnBeingResized.getWidth())
+        {
+            return;
+        }
+        
+        columnBeingResized.setWidth(newWidth,false);
+        scrollValuesObsolete = true;
+
+        Rectangle clientArea = getClientArea();
+        redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+        
+        columnBeingResized.fireResized();
+        
+        for (int index = displayOrderedColumns.indexOf(columnBeingResized) + 1; index < displayOrderedColumns.size(); index ++)
+        {
+            GridColumn col = (GridColumn)displayOrderedColumns.get(index);
+            if (col.isVisible()) col.fireMoved();
+        }
+    }
+    /**
+     * Sets the new height of the item of the row being resized and fires the appropriate
+     * listeners.
+     * 
+     * @param x mouse x
+     */
+    private void handleRowResizerDragging(int y)
+    {
+        int newHeight = resizingRowStartHeight + (y - resizingStartY);
+        if (newHeight < MIN_ROW_HEADER_HEIGHT)
+        {
+            newHeight = MIN_ROW_HEADER_HEIGHT;
+        }
+
+        if (newHeight > getClientArea().height)
+        {
+            newHeight = getClientArea().height;
+        }
+
+        if (newHeight == rowBeingResized.getHeight())
+        {
+            return;
+        }
+        
+        Event e = new Event();
+        e.item = rowBeingResized;
+        e.widget = this;
+        e.detail = newHeight;
+        
+        rowBeingResized.notifyListeners(SWT.Resize, e);
+        
+        if (e.doit == false)
+            return;
+
+        newHeight = e.detail;
+        
+        if (newHeight < MIN_ROW_HEADER_HEIGHT)
+        {
+            newHeight = MIN_ROW_HEADER_HEIGHT;
+        }
+
+        if (newHeight > getClientArea().height)
+        {
+            newHeight = getClientArea().height;
+        }
+        
+        rowBeingResized.setHeight(newHeight);
+        scrollValuesObsolete = true;
+
+        Rectangle clientArea = getClientArea();
+        redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+    }
+
+    /**
+     * Determines if the mouse is hovering on a column resizer and changes the
+     * pointer and sets field appropriately.
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return true if this event has been consumed.
+     */
+    private boolean handleHoverOnColumnResizer(int x, int y)
+    {
+        boolean over = false;
+        if (y <= headerHeight)
+        {
+            int x2 = 0;
+
+            if (rowHeaderVisible)
+            {
+                x2 += rowHeaderWidth;
+            }
+
+            x2 -= getHScrollSelectionInPixels();
+
+            for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
+            {
+                GridColumn column = (GridColumn) columnIterator.next();
+                if (!column.isVisible())
+                {
+                    continue;
+                }
+                x2 += column.getWidth();
+
+                if (x2 >= (x - COLUMN_RESIZER_THRESHOLD) && x2 <= (x + COLUMN_RESIZER_THRESHOLD))
+                {
+                    if (column.getResizeable())
+                    {
+                        if (column.getColumnGroup() != null && y <= groupHeaderHeight)
+                        {
+                            // if this is not the last column
+                            if (column != column.getColumnGroup().getLastVisibleColumn())
+                            {
+                                break;
+                            }
+                        }
+
+                        over = true;
+                        columnBeingResized = column;
+                    }
+                    break;
+                }
+            }
+        }
+
+        if (over != hoveringOnColumnResizer)
+        {
+            if (over)
+            {
+                setCursor(getDisplay().getSystemCursor(SWT.CURSOR_SIZEWE));
+            }
+            else
+            {
+                columnBeingResized = null;
+                setCursor(null);
+            }
+            hoveringOnColumnResizer = over;
+        }
+        return over;
+    }
+
+    /**
+     * Determines if the mouse is hovering on a row resizer and changes the
+     * pointer and sets field appropriately.
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return true if this event has been consumed.
+     */
+    private boolean handleHoverOnRowResizer(int x, int y)
+    {
+        rowBeingResized = null;
+        boolean over = false;
+        if (x <= rowHeaderWidth)
+        {
+            int y2 = 0;
+
+            if (columnHeadersVisible)
+            {
+                y2 += headerHeight;
+            }
+
+            int row=getTopIndex();
+            while(row<items.size() && y2<=getClientArea().height)
+            {
+                GridItem currItem = (GridItem)items.get(row);
+                if (currItem.isVisible())
+                {
+                    y2 += currItem.getHeight() +1;
+
+                    if (y2 >= (y - ROW_RESIZER_THRESHOLD) && y2 <= (y + ROW_RESIZER_THRESHOLD))
+                    {
+//                        if (currItem.isResizeable())
+                        {
+                            over = true;
+                            rowBeingResized = currItem;
+                        }
+                        // do not brake here, because in case of overlapping
+                        // row resizers we need to find the last one
+                    }
+                    else
+                    {
+                        if(rowBeingResized != null)
+                        {
+                            // we have passed all (overlapping) row resizers, so break
+                            break;
+                        }
+                    }
+                }
+                row++;
+            }
+        }
+
+        if (over != hoveringOnRowResizer)
+        {
+            if (over)
+            {
+                setCursor(getDisplay().getSystemCursor(SWT.CURSOR_SIZENS));
+            }
+            else
+            {
+                rowBeingResized = null;
+                setCursor(null);
+            }
+            hoveringOnRowResizer = over;
+        }
+        return over;
+    }
+    
+    /**
+     * Returns the cell at the given point in the receiver or null if no such
+     * cell exists. The point is in the coordinate system of the receiver.
+     * 
+     * @param point the point used to locate the item
+     * @return the cell at the given point
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public Point getCell(Point point)
+    {
+        checkWidget();
+        
+        if (point == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+        if (point.x < 0 || point.x > getClientArea().width) return null;
+
+        GridItem item = getItem(point);
+        GridColumn column = getColumn(point);
+
+        if (item!=null && column!=null)
+        {
+            return new Point(columns.indexOf(column),items.indexOf(item));
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    /**
+     * Paints.
+     * 
+     * @param e paint event
+     */
+    private void onPaint(PaintEvent e)
+    {
+        int insertMarkPosX1 = -1;        // we will populate these values while drawing the cells
+        int insertMarkPosX2 = -1;
+        int insertMarkPosY = -1;
+        boolean insertMarkPosFound = false;
+        
+        e.gc.setBackground(getBackground());
+        this.drawBackground(e.gc,0,0,getSize().x,getSize().y);
+        
+        if (scrollValuesObsolete)
+        {
+            updateScrollbars();
+            scrollValuesObsolete = false;
+        }
+
+        int x = 0;
+        int y = 0;
+        
+        if (columnHeadersVisible)
+        {
+            paintHeader(e.gc);
+            y += headerHeight;
+        }
+
+        int firstVisibleIndex = 0;
+        int availableHeight = getClientArea().height-y;
+        int visibleRows = availableHeight / getItemHeight() + 1;
+        if (items.size()>0 && availableHeight>0)
+        {
+            RowRange range = getRowRange(getTopIndex(),availableHeight,false,false);
+            if (range.height >= availableHeight)
+                visibleRows = range.rows;
+            else
+                visibleRows = range.rows + (availableHeight-range.height) / getItemHeight() + 1;
+        }
+
+        firstVisibleIndex = getTopIndex();
+
+        int row = firstVisibleIndex;
+        
+        for (int i = 0; i < visibleRows; i++)
+        {
+
+            x = 0;
+
+            x -= getHScrollSelectionInPixels();
+            
+            // get the item to draw
+            GridItem item = null;
+            if (row < items.size())
+            {
+                item = (GridItem)items.get(row);
+
+                while (!item.isVisible() && row < items.size() - 1)
+                {
+                    row++;
+                    item = (GridItem)items.get(row);
+                }
+            }
+            if (item != null && !item.isVisible())
+            {
+                item = null;
+            }
+
+            if (item != null)
+            {
+                boolean cellInRowSelected = false;
+                
+
+                if (rowHeaderVisible)
+                {
+
+                    // row header is actually painted later
+                    x += rowHeaderWidth;
+                }                
+
+                int focusY = y;
+
+                // This variable is used to count how many columns are
+                // skipped because the previous column spanned over them
+                int skipBecauseSpanned = 0;
+
+                int colIndex = 0;
+
+                // draw regular cells for each column
+                for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
+                {
+                    
+                    GridColumn column = (GridColumn) columnIterator.next();
+                                       
+                    if (!column.isVisible())
+                    {
+                        colIndex++;
+                        if (skipBecauseSpanned > 0)
+                        {
+                            skipBecauseSpanned--;
+                        }
+                        continue;
+                    }
+
+                    if (skipBecauseSpanned == 0)
+                    {
+                        skipBecauseSpanned = item.getColumnSpan(indexOf(column));
+
+                        int width = column.getWidth();
+
+                        if (skipBecauseSpanned > 0)
+                        {
+                            for (int j = 0; j < skipBecauseSpanned; j++)
+                            {
+                                if (getColumnCount() <= colIndex + j + 1)
+                                {
+                                    break;
+                                }
+                                if (((GridColumn)displayOrderedColumns.get(colIndex + j + 1)).isVisible())
+                                {
+                                    width += ((GridColumn)displayOrderedColumns.get(colIndex + j + 1)).getWidth();
+                                }
+                            }
+                        }
+                        
+                        if (x + width >= 0 && x < getClientArea().width )
+                        {
+
+                            column.getCellRenderer().setBounds(x, y, width, item.getHeight());
+    
+                            e.gc.setClipping(new Rectangle(x -1,y -1,width +1,item.getHeight() + 2));
+                            
+                            column.getCellRenderer().setRow(i + 1);
+    
+                            column.getCellRenderer().setSelected(selectedItems.contains(item));
+                            column.getCellRenderer().setFocus(this.isFocusControl());
+                            column.getCellRenderer().setRowFocus(focusItem == item);
+                            column.getCellRenderer().setCellFocus(cellSelectionEnabled && focusItem == item && focusColumn == column);
+                            
+                            column.getCellRenderer().setRowHover(hoveringItem == item);
+                            column.getCellRenderer().setColumnHover(hoveringColumn == column);
+     
+                            if (selectedCells.contains(new Point(indexOf(column),row)))
+                            {
+                                column.getCellRenderer().setCellSelected(true);
+                                cellInRowSelected = true;
+                            }
+                            else
+                            {
+                                column.getCellRenderer().setCellSelected(false);                            
+                            }
+    
+                            if (hoveringItem == item && hoveringColumn == column)
+                            {
+                                column.getCellRenderer().setHoverDetail(hoveringDetail);
+                            }
+                            else
+                            {
+                                column.getCellRenderer().setHoverDetail("");
+                            }
+    
+                            column.getCellRenderer().paint(e.gc, item);
+    
+                            e.gc.setClipping((Rectangle)null);
+                            
+                            // collect the insertMark position
+                            if (!insertMarkPosFound && insertMarkItem == item && (insertMarkColumn == null || insertMarkColumn == column))
+                            {
+                                // y-pos
+                                insertMarkPosY = y - 1;
+                                if (!insertMarkBefore)
+                                    insertMarkPosY += item.getHeight() + 1;
+                                // x1-pos
+                                insertMarkPosX1 = x;
+                                if (column.isTree())
+                                {
+                                    insertMarkPosX1 += Math.min(
+                                            width,
+                                            column.getCellRenderer().getTextBounds(item, false).x);
+                                }
+
+                                // x2-pos
+                                if (insertMarkColumn == null)
+                                {
+                                    insertMarkPosX2 = getClientArea().x + getClientArea().width;
+                                }
+                                else
+                                {
+                                    insertMarkPosX2 = x + width;
+                                }
+
+                                insertMarkPosFound = true;
+                            }
+                        }
+
+
+                        x += width;
+
+                    }
+                    else
+                    {
+                        skipBecauseSpanned--;
+                    }
+                    colIndex++;
+
+                }
+
+                if (x < getClientArea().width)
+                {
+                    // insertMarkPos needs correction
+                    if(insertMarkPosFound && insertMarkColumn == null)
+                        insertMarkPosX2 = x;
+                    
+                    emptyCellRenderer.setSelected(selectedItems.contains(item));
+                    emptyCellRenderer.setFocus(this.isFocusControl());
+                    emptyCellRenderer.setRow(i + 1);
+                    emptyCellRenderer.setBounds(x, y, getClientArea().width - x + 1, item.getHeight());
+                    emptyCellRenderer.setColumn(getColumnCount());
+                    emptyCellRenderer.paint(e.gc, item);
+                }
+                
+                x = 0;
+
+                if (rowHeaderVisible)
+                {
+
+                    if (!cellSelectionEnabled)
+                    {
+                        rowHeaderRenderer.setSelected(selectedItems.contains(item));
+                    }
+                    else
+                    {
+                        rowHeaderRenderer.setSelected(cellInRowSelected);
+                    }
+
+                    rowHeaderRenderer.setBounds(0, y, rowHeaderWidth, item.getHeight() + 1);
+                    rowHeaderRenderer.paint(e.gc, item);
+                    
+                    x += rowHeaderWidth;
+                }                
+                
+                // focus
+                if (isFocusControl() && !cellSelectionEnabled)
+                {
+                    if (item == focusItem)
+                    {
+                        if (focusRenderer != null)
+                        {
+                            int focusX = 0;
+                            if (rowHeaderVisible)
+                            {
+                                focusX = rowHeaderWidth;
+                            }
+                            focusRenderer
+                                .setBounds(focusX, focusY - 1, getClientArea().width - focusX - 1,
+                                        item.getHeight() + 1);
+                            focusRenderer.paint(e.gc, item);
+                        }
+                    }
+                }
+
+                y += item.getHeight() + 1;
+            }
+            else
+            {
+
+                if (rowHeaderVisible)
+                {
+                    //row header is actually painted later
+                    x += rowHeaderWidth;
+                }
+
+                emptyCellRenderer.setBounds(x, y, getClientArea().width - x, getItemHeight());
+                emptyCellRenderer.setFocus(false);
+                emptyCellRenderer.setSelected(false);
+                emptyCellRenderer.setRow(i + 1);
+
+                for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
+                {
+                    GridColumn column = (GridColumn) columnIterator.next();
+                    
+                    if (column.isVisible())
+                    {
+                        emptyCellRenderer.setBounds(x, y, column.getWidth(), getItemHeight());
+                        emptyCellRenderer.setColumn(indexOf(column));
+                        emptyCellRenderer.paint(e.gc, this);
+
+                        x += column.getWidth();
+                    }
+                }
+                
+                if (x < getClientArea().width)
+                {
+                    emptyCellRenderer.setBounds(x, y, getClientArea().width - x + 1, getItemHeight());
+                    emptyCellRenderer.setColumn(getColumnCount());
+                    emptyCellRenderer.paint(e.gc, this);
+                }
+                
+
+                x = 0;
+                
+                if (rowHeaderVisible)
+                {
+                    emptyRowHeaderRenderer.setBounds(x, y, rowHeaderWidth, getItemHeight() + 1);
+                    emptyRowHeaderRenderer.paint(e.gc, this);
+
+                    x += rowHeaderWidth;
+                }
+
+                y += getItemHeight() + 1;
+            }
+
+            row++;
+        }
+
+        // draw drop point
+        if (draggingColumn)
+        {
+            if ((dragDropAfterColumn != null || dragDropBeforeColumn != null)
+                && (dragDropAfterColumn != columnBeingPushed && dragDropBeforeColumn != columnBeingPushed)
+                && dragDropPointValid)
+            {
+                if (dragDropBeforeColumn != null)
+                {
+                    x = getColumnHeaderXPosition(dragDropBeforeColumn);
+                }
+                else
+                {
+                    x = getColumnHeaderXPosition(dragDropAfterColumn)
+                        + dragDropAfterColumn.getWidth();
+                }
+
+                Point size = dropPointRenderer.computeSize(e.gc, SWT.DEFAULT, SWT.DEFAULT, null);
+                x -= size.x / 2;
+                if (x < 0)
+                {
+                    x = 0;
+                }
+                dropPointRenderer.setBounds(x - 1, headerHeight + DROP_POINT_LOWER_OFFSET, size.x,
+                                            size.y);
+                dropPointRenderer.paint(e.gc, null);
+            }
+        }
+
+        // draw insertion mark
+        if (insertMarkPosFound)
+        {
+            e.gc.setClipping(
+                    rowHeaderVisible ? rowHeaderWidth : 0,
+                    columnHeadersVisible ? headerHeight : 0,
+                    getClientArea().width,
+                    getClientArea().height);
+            insertMarkRenderer.paint(e.gc, new Rectangle(insertMarkPosX1, insertMarkPosY, insertMarkPosX2 - insertMarkPosX1, 0));
+        }
+    }
+
+    /**
+     * Returns a column reference if the x,y coordinates are over a column
+     * header (header only).
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return column reference which mouse is over, or null.
+     */
+    private GridColumn overColumnHeader(int x, int y)
+    {
+        GridColumn col = null;
+
+        if (y <= headerHeight && y > 0)
+        {
+            col = getColumn(new Point(x, y));
+            if (col != null && col.getColumnGroup() != null)
+            {
+                if (y <= groupHeaderHeight)
+                {
+                    return null;
+                }
+            }
+        }
+
+        return col;
+    }
+
+    /**
+     * Returns a column group reference if the x,y coordinates are over a column
+     * group header (header only).
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return column group reference which mouse is over, or null.
+     */
+    private GridColumnGroup overColumnGroupHeader(int x, int y)
+    {
+        GridColumnGroup group = null;
+
+        if (y <= groupHeaderHeight && y > 0)
+        {
+            GridColumn col = getColumn(new Point(x, y));
+            if (col != null)
+            {
+                group = col.getColumnGroup();
+            }
+        }
+
+        return group;
+    }
+
+    /**
+     * Paints the header.
+     * 
+     * @param gc gc from paint event
+     */
+    private void paintHeader(GC gc)
+    {
+        int x = 0;
+        int y = 0;
+
+        x -= getHScrollSelectionInPixels();
+        
+        if (rowHeaderVisible)
+        {
+            // paint left corner
+            // topLeftRenderer.setBounds(0, y, rowHeaderWidth, headerHeight);
+            // topLeftRenderer.paint(gc, null);
+            x += rowHeaderWidth;
+        }
+
+        GridColumnGroup previousPaintedGroup = null;
+
+        for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
+        {
+            if (x > getClientArea().width)
+                break;
+            
+            GridColumn column = (GridColumn) columnIterator.next();
+            int height = 0;
+            
+            if (!column.isVisible())
+            {
+                continue;
+            }
+
+            if (column.getColumnGroup() != null)
+            {
+
+                if (column.getColumnGroup() != previousPaintedGroup)
+                {
+                    int width = column.getWidth();
+
+                    GridColumn nextCol = null;
+                    if (displayOrderedColumns.indexOf(column) + 1 < displayOrderedColumns.size())
+                    {
+                        nextCol = (GridColumn)displayOrderedColumns
+                            .get(displayOrderedColumns.indexOf(column) + 1);
+                    }
+
+                    while (nextCol != null && nextCol.getColumnGroup() == column.getColumnGroup())
+                    {
+
+                        if ((nextCol.getColumnGroup().getExpanded() && !nextCol.isDetail())
+                            || (!nextCol.getColumnGroup().getExpanded() && !nextCol.isSummary()))
+                        {
+                        }
+                        else
+                        {
+                            width += nextCol.getWidth();
+                        }
+
+                        if (displayOrderedColumns.indexOf(nextCol) + 1 < displayOrderedColumns
+                            .size())
+                        {
+                            nextCol = (GridColumn)displayOrderedColumns.get(displayOrderedColumns
+                                .indexOf(nextCol) + 1);
+                        }
+                        else
+                        {
+                            nextCol = null;
+                        }
+                    }
+                    
+                    boolean selected = true;
+                    
+                    for (int i = 0; i < column.getColumnGroup().getColumns().length; i++)
+                    {
+                        GridColumn col = column.getColumnGroup().getColumns()[i];
+                        if (col.isVisible() && (column.getMoveable() || !selectedColumns.contains(col)))
+                        {
+                            selected = false;
+                            break;
+                        }
+                    }
+
+                    
+                    column.getColumnGroup().getHeaderRenderer().setSelected(selected);
+                    column.getColumnGroup().getHeaderRenderer()
+                        .setHover(hoverColumnGroupHeader == column.getColumnGroup());
+                    column.getColumnGroup().getHeaderRenderer().setHoverDetail(hoveringDetail);
+
+                    column.getColumnGroup().getHeaderRenderer().setBounds(x, 0, width,
+                                                                          groupHeaderHeight);
+
+                    column.getColumnGroup().getHeaderRenderer().paint(gc, column.getColumnGroup());
+
+                    previousPaintedGroup = column.getColumnGroup();
+                }
+
+                height = headerHeight - groupHeaderHeight;
+                y = groupHeaderHeight;
+            }
+            else
+            {
+                height = headerHeight;
+                y = 0;
+            }
+
+            if (pushingColumn)
+            {
+                column.getHeaderRenderer().setHover(
+                                                    columnBeingPushed == column
+                                                        && pushingAndHovering);
+            }
+            else
+            {
+                column.getHeaderRenderer().setHover(hoveringColumnHeader == column);
+            }
+
+            column.getHeaderRenderer().setHoverDetail(hoveringDetail);
+
+            column.getHeaderRenderer().setBounds(x, y, column.getWidth(), height);
+            
+            if (cellSelectionEnabled)
+                column.getHeaderRenderer().setSelected(selectedColumns.contains(column));
+            
+            if (x + column.getWidth() >= 0)
+            {
+                column.getHeaderRenderer().paint(gc, column);    
+            }
+
+            x += column.getWidth();
+        }
+
+        if (x < getClientArea().width)
+        {
+            emptyColumnHeaderRenderer.setBounds(x, 0, getClientArea().width - x, headerHeight);
+            emptyColumnHeaderRenderer.paint(gc, null);
+        }
+        
+        x = 0;
+
+        if (rowHeaderVisible)
+        {
+            // paint left corner
+            topLeftRenderer.setBounds(0, 0, rowHeaderWidth, headerHeight);
+            topLeftRenderer.paint(gc, this);
+            x += rowHeaderWidth;
+        }
+
+        if (draggingColumn)
+        {
+
+            gc.setAlpha(COLUMN_DRAG_ALPHA);
+
+            columnBeingPushed.getHeaderRenderer().setSelected(false);
+
+            int height = 0;
+
+            if (columnBeingPushed.getColumnGroup() != null)
+            {
+                height = headerHeight - groupHeaderHeight;
+                y = groupHeaderHeight;
+            }
+            else
+            {
+                height = headerHeight;
+                y = 0;
+            }
+
+            columnBeingPushed.getHeaderRenderer()
+                .setBounds(
+                           getColumnHeaderXPosition(columnBeingPushed)
+                               + (currentHeaderDragX - startHeaderDragX), y,
+                           columnBeingPushed.getWidth(), height);
+            columnBeingPushed.getHeaderRenderer().paint(gc, columnBeingPushed);
+            columnBeingPushed.getHeaderRenderer().setSelected(false);
+
+            gc.setAlpha(-1);
+            gc.setAdvanced(false);
+        }
+
+    }
+
+    /**
+     * Manages the state of the scrollbars when new items are added or the
+     * bounds are changed.
+     */
+    private void updateScrollbars()
+    {
+        Point preferredSize = getTableSize();
+
+        Rectangle clientArea = getClientArea();
+
+        // First, figure out if the scrollbars should be visible and turn them
+        // on right away
+        // this will allow the computations further down to accommodate the
+        // correct client
+        // area
+
+        // Turn the scrollbars on if necessary and do it all over again if
+        // necessary. This ensures
+        // that if a scrollbar is turned on/off, the other scrollbar's
+        // visibility may be affected (more
+        // area may have been added/removed.
+        for (int doublePass = 1; doublePass <= 2; doublePass++)
+        {
+
+            if (preferredSize.y > clientArea.height)
+            {
+                vScroll.setVisible(true);
+            }
+            else
+            {
+                vScroll.setVisible(false);
+                vScroll.setValues(0, 0, 1, 1, 1, 1);
+            }
+            if (preferredSize.x > clientArea.width)
+            {
+                hScroll.setVisible(true);
+            }
+            else
+            {
+                hScroll.setVisible(false);
+                hScroll.setValues(0, 0, 1, 1, 1, 1);
+            }
+
+            // get the clientArea again with the now visible/invisible
+            // scrollbars
+            clientArea = getClientArea();
+        }
+
+        // if the scrollbar is visible set its values
+        if (vScroll.getVisible())
+        {
+            int max = currentVisibleItems;
+            int thumb = 1;
+
+            if(!hasDifferingHeights)
+            {
+                // in this case, the number of visible rows on screen is constant,
+                // so use this as thumb
+                thumb = ( getVisibleGridHeight() + 1 ) / ( getItemHeight() + 1 );
+            }
+            else
+            {
+                // in this case, the number of visible rows on screen is variable,
+                // so we have to use 1 as thumb and decrease max by the number of
+                // rows on the last page
+                if(getVisibleGridHeight()>=1) {
+                    RowRange range = getRowRange(-1,getVisibleGridHeight(),true,true);
+                    max -= range.rows - 1;
+                }
+            }
+
+            // if possible, remember selection, if selection is too large, just
+            // make it the max you can
+            int selection = Math.min(vScroll.getSelection(), max);
+
+            vScroll.setValues(selection, 0, max, thumb, 1, thumb);
+        }
+
+        // if the scrollbar is visible set its values
+        if (hScroll.getVisible())
+        {
+
+            if (!columnScrolling)
+            {
+                // horizontal scrolling works pixel by pixel
+
+                int hiddenArea = preferredSize.x - clientArea.width + 1;
+
+                // if possible, remember selection, if selection is too large,
+                // just
+                // make it the max you can
+                int selection = Math.min(hScroll.getSelection(), hiddenArea - 1);
+
+                hScroll.setValues(selection, 0, hiddenArea + clientArea.width - 1, clientArea.width,
+                                 HORZ_SCROLL_INCREMENT, clientArea.width);
+            }
+            else
+            {
+                // horizontal scrolling is column by column
+
+                int hiddenArea = preferredSize.x - clientArea.width + 1;
+
+                int max = 0;
+                int i = 0;
+     
+                while (hiddenArea > 0 && i < getColumnCount())
+                {
+                    GridColumn col = (GridColumn)displayOrderedColumns.get(i);
+                    
+                    i++;
+                    
+                    if (col.isVisible())
+                    {
+                        hiddenArea -= col.getWidth();
+                        max++;
+                    }
+                }
+
+                max++;
+
+                // max should never be greater than the number of visible cols
+                int visCols = 0;
+                for (Iterator iter = columns.iterator(); iter.hasNext();)
+                {
+                    GridColumn element = (GridColumn)iter.next();
+                    if (element.isVisible())
+                    {
+                        visCols++;
+                    }
+                }
+                max = Math.min(visCols, max);
+
+                // if possible, remember selection, if selection is too large,
+                // just
+                // make it the max you can
+                int selection = Math.min(hScroll.getSelection(), max);
+
+                hScroll.setValues(selection, 0, max, 1, 1, 1);
+            }
+        }
+
+    }
+
+    /**
+     * Adds/removes items from the selected items list based on the
+     * selection/deselection of the given item.
+     * 
+     * @param item item being selected/unselected
+     * @param stateMask key state during selection
+     * 
+     * @return selection event that needs to be fired or null
+     */
+    private Event updateSelection(GridItem item, int stateMask)
+    {
+        if (!selectionEnabled)
+        {
+            return null;
+        }
+        
+        Event selectionEvent = null;
+        
+        if (selectionType == SWT.SINGLE)
+        {
+            if (selectedItems.contains(item)) return null;
+            
+            selectedItems.clear();
+            selectedItems.add(item);
+
+            Rectangle clientArea = getClientArea();
+            redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+
+            selectionEvent = new Event();
+            selectionEvent.item = item;
+        }
+        else if (selectionType == SWT.MULTI)
+        {
+            boolean shift = false;
+            boolean ctrl = false;
+
+            if ((stateMask & SWT.SHIFT) == SWT.SHIFT)
+            {
+                shift = true;
+            }
+
+            if ((stateMask & SWT.CTRL) == SWT.CTRL)
+            {
+                ctrl = true;
+            }
+
+            if (!shift && !ctrl)
+            {
+                if (selectedItems.size() == 1 && selectedItems.contains(item)) return null;
+                
+                selectedItems.clear();
+
+                selectedItems.add(item);
+
+                Rectangle clientArea = getClientArea();
+                redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+
+                shiftSelectionAnchorItem = null;
+
+                selectionEvent = new Event();
+                selectionEvent.item = item;
+            }
+            else if (shift)
+            {
+
+                if (shiftSelectionAnchorItem == null)
+                {
+                    shiftSelectionAnchorItem = focusItem;
+                }
+
+//                if (shiftSelectionAnchorItem == item)
+//                {
+//                    return;
+//                }
+
+                boolean maintainAnchorSelection = false;
+
+                if (!ctrl)
+                {
+                    if (selectedItems.contains(shiftSelectionAnchorItem))
+                    {
+                        maintainAnchorSelection = true;
+                    }
+                    selectedItems.clear();
+                }
+
+                int anchorIndex = items.indexOf(shiftSelectionAnchorItem);
+                int itemIndex = items.indexOf(item);
+
+                int min = 0;
+                int max = 0;
+
+                if (anchorIndex < itemIndex)
+                {
+                    if (maintainAnchorSelection)
+                    {
+                        min = anchorIndex;
+                    }
+                    else
+                    {
+                        min = anchorIndex + 1;
+                    }
+                    max = itemIndex;
+                }
+                else
+                {
+                    if (maintainAnchorSelection)
+                    {
+                        max = anchorIndex;
+                    }
+                    else
+                    {
+                        max = anchorIndex - 1;
+                    }
+                    min = itemIndex;
+                }
+
+                for (int i = min; i <= max; i++)
+                {
+                    if (!selectedItems.contains(items.get(i)) && ((GridItem)items.get(i)).isVisible())
+                    {
+                        selectedItems.add((GridItem)items.get(i));
+                    }
+                }
+                Rectangle clientArea = getClientArea();
+                redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+
+                selectionEvent = new Event();
+            }
+            else if (ctrl)
+            {
+                if (selectedItems.contains(item))
+                {
+                    selectedItems.remove(item);
+                }
+                else
+                {
+                    selectedItems.add(item);
+                }
+                Rectangle clientArea = getClientArea();
+                redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+
+                shiftSelectionAnchorItem = null;
+
+                selectionEvent = new Event();
+                selectionEvent.item = item;
+            }
+        }
+        
+        Rectangle clientArea = getClientArea();
+        redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+        
+        return selectionEvent;
+    }
+    
+    /**
+     * Updates cell selection.
+     * 
+     * @param newCell newly clicked, navigated to cell.
+     * @param stateMask statemask during preceeding mouse or key event.
+     * @param dragging true if the user is dragging.
+     * @param reverseDuplicateSelections true if the user is reversing selection rather than adding to.
+     * 
+     * @return selection event that will need to be fired or null.
+     */
+    private Event updateCellSelection(Point newCell, int stateMask, boolean dragging, boolean reverseDuplicateSelections)
+    {
+        Vector v = new Vector();
+        v.add(newCell);
+        return updateCellSelection(v, stateMask, dragging, reverseDuplicateSelections);
+    }
+
+    /**
+     * Updates cell selection.
+     * 
+     * @param newCell newly clicked, navigated to cells.
+     * @param stateMask statemask during preceeding mouse or key event.
+     * @param dragging true if the user is dragging.
+     * @param reverseDuplicateSelections true if the user is reversing selection rather than adding to.
+     * 
+     * @return selection event that will need to be fired or null.
+     */
+    private Event updateCellSelection(Vector newCells, int stateMask, boolean dragging, boolean reverseDuplicateSelections)
+    {
+        boolean shift = false;
+        boolean ctrl = false;
+
+        if ((stateMask & SWT.SHIFT) == SWT.SHIFT)
+        {
+            shift = true;
+        }
+        else
+        {
+            shiftSelectionAnchorColumn = null;
+            shiftSelectionAnchorItem = null;
+        }
+        
+        if ((stateMask & SWT.CTRL) == SWT.CTRL)
+        {
+            ctrl = true;
+        }
+
+        if (!shift && !ctrl)
+        {
+            if (newCells.equals(selectedCells)) return null;
+            
+            selectedCells.clear();            
+            for (int i = 0; i < newCells.size(); i++)
+            {
+                addToCellSelection((Point)newCells.get(i));
+            }
+            
+        }
+        else if (shift)
+        {
+            
+            Point newCell = (Point)newCells.get(0); //shift selection should only occur with one
+            //cell, ignoring others
+            
+            if ((focusColumn == null) || (focusItem == null))
+            {
+                return null;
+            }
+            
+            shiftSelectionAnchorColumn = getColumn(newCell.x);
+            shiftSelectionAnchorItem = getItem(newCell.y);
+            
+            if (ctrl)
+            {
+                selectedCells.clear();
+                selectedCells.addAll(selectedCellsBeforeRangeSelect);
+            }
+            else
+            {
+                selectedCells.clear();
+            }
+            
+           
+            
+            
+            GridColumn currentColumn = focusColumn;
+            GridItem currentItem = focusItem;
+            
+            GridColumn endColumn = getColumn(newCell.x);
+            GridItem endItem = getItem(newCell.y);
+            
+            Point newRange = getSelectionRange(currentItem,currentColumn,endItem,endColumn);
+            
+            currentColumn = getColumn(newRange.x);
+            endColumn = getColumn(newRange.y);
+            
+            GridColumn startCol = currentColumn;
+            
+            if (indexOf(currentItem) > indexOf(endItem))
+            {
+                GridItem temp = currentItem;
+                currentItem = endItem;
+                endItem = temp;
+            }
+            
+            boolean firstLoop = true;
+            
+            do
+            {
+                if (!firstLoop)
+                {
+                    currentItem = getNextVisibleItem(currentItem);
+                }
+                
+                firstLoop = false;
+                
+                boolean firstLoop2 = true;
+                
+                currentColumn = startCol;
+                
+                do
+                {   
+                    if (!firstLoop2)
+                    {
+                        int index = displayOrderedColumns.indexOf(currentColumn) + 1;
+                        
+                        if (index < displayOrderedColumns.size())
+                        {
+                            currentColumn = getVisibleColumn_DegradeRight(currentItem,(GridColumn)displayOrderedColumns.get(index));
+                        }
+                        else
+                        {
+                            currentColumn = null;
+                        }
+                        
+                        if (currentColumn!= null)
+                            if (displayOrderedColumns.indexOf(currentColumn) > displayOrderedColumns.indexOf(endColumn))
+                                currentColumn = null;
+                    }
+                    
+                    firstLoop2 = false;
+                    
+                    if (currentColumn != null)
+                    {
+                        Point cell = new Point(indexOf(currentColumn),indexOf(currentItem));
+                        addToCellSelection(cell);
+                    }
+                } while (currentColumn != endColumn && currentColumn != null);                
+            } while (currentItem != endItem);            
+        }
+        else if (ctrl)
+        {
+            boolean reverse = reverseDuplicateSelections;
+            if (!selectedCells.containsAll(newCells))
+                reverse = false;
+            
+            if (dragging)
+            {
+                selectedCells.clear();
+                selectedCells.addAll(selectedCellsBeforeRangeSelect);
+            }
+            
+            if (reverse)
+            {
+                selectedCells.removeAll(newCells);
+            }
+            else
+            {            
+                for (int i = 0; i < newCells.size(); i++)
+                {
+                    addToCellSelection((Point)newCells.get(i));
+                }
+            }
+        }
+        
+        updateColumnSelection();
+        
+        Event e = new Event();
+        if (dragging)
+        {
+            e.detail = SWT.DRAG;
+            followupCellSelectionEventOwed = true;
+        }
+
+        Rectangle clientArea = getClientArea();
+        redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+        
+        return e;
+    }
+    
+    private void addToCellSelection(Point newCell)
+    {
+        if (newCell.x < 0 || newCell.x >= columns.size())
+            return;
+        
+        if (newCell.y < 0 || newCell.y >= items.size())
+            return;
+        
+        if (getColumn(newCell.x).getCellSelectionEnabled())
+        {
+            selectedCells.add(newCell);
+        }
+    }
+    
+    void updateColumnSelection()
+    {
+        //Update the list of which columns have all their cells selected
+        selectedColumns.clear();
+        
+        for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
+        {
+            Point cell = (Point)iter.next();
+            
+            GridColumn col = getColumn(cell.x);
+            
+            selectedColumns.add(col);
+        } 
+    }
+    
+    /**
+     * Initialize all listeners.
+     */
+    private void initListeners()
+    {
+        disposeListener = new Listener()
+        {
+            public void handleEvent(Event e)
+            {
+                onDispose(e);
+            }
+        };
+        addListener(SWT.Dispose,disposeListener);
+        
+        addPaintListener(new PaintListener()
+        {
+            public void paintControl(PaintEvent e)
+            {
+                onPaint(e);
+            }
+        });
+
+        addListener(SWT.Resize, new Listener()
+        {
+            public void handleEvent(Event e)
+            {
+                onResize();
+            }
+        });
+
+        if (getVerticalBar() != null)
+        {
+            getVerticalBar().addListener(SWT.Selection, new Listener()
+            {
+                public void handleEvent(Event e)
+                {
+                    onScrollSelection();
+                }
+            });
+        }
+
+        if (getHorizontalBar() != null)
+        {
+            getHorizontalBar().addListener(SWT.Selection, new Listener()
+            {
+                public void handleEvent(Event e)
+                {
+                    onScrollSelection();
+                }
+            });
+        }
+
+        addListener(SWT.KeyDown, new Listener()
+        {
+            public void handleEvent(Event e)
+            {
+                onKeyDown(e);
+            }
+        });
+
+        addTraverseListener(new TraverseListener()
+        {
+            public void keyTraversed(TraverseEvent e)
+            {
+                e.doit = true;
+            }
+        });
+
+        addMouseListener(new MouseListener()
+        {
+            public void mouseDoubleClick(MouseEvent e)
+            {
+                onMouseDoubleClick(e);
+            }
+
+            public void mouseDown(MouseEvent e)
+            {
+                onMouseDown(e);
+            }
+
+            public void mouseUp(MouseEvent e)
+            {
+                onMouseUp(e);
+            }
+        });
+
+        addMouseMoveListener(new MouseMoveListener()
+        {
+            public void mouseMove(MouseEvent e)
+            {
+                onMouseMove(e);
+            }
+        });
+
+        addMouseTrackListener(new MouseTrackListener()
+        {
+            public void mouseEnter(MouseEvent e)
+            {
+            }
+
+            public void mouseExit(MouseEvent e)
+            {
+                onMouseExit(e);
+            }
+
+            public void mouseHover(MouseEvent e)
+            {
+            }
+        });
+
+        addFocusListener(new FocusListener()
+        {
+            public void focusGained(FocusEvent e)
+            {
+                onFocusIn();
+                redraw();                
+            }
+
+            public void focusLost(FocusEvent e)
+            {
+                redraw();
+            }
+        });
+
+        // Special code to reflect mouse wheel events if using an external
+        // scroller
+        addListener(SWT.MouseWheel, new Listener()
+        {
+            public void handleEvent(Event e)
+            {
+                onMouseWheel(e);
+            }
+        });
+    }
+    
+    private void onFocusIn()
+    {
+        if (!items.isEmpty() && focusItem == null)
+        {
+            focusItem = (GridItem) items.get(0);
+        }
+    }
+    
+    private void onDispose(Event event)
+    {   
+        //We only want to dispose of our items and such *after* anybody else who may have been 
+        //listening to the dispose has had a chance to do whatever.
+        removeListener(SWT.Dispose, disposeListener);
+        notifyListeners(SWT.Dispose, event);
+        event.type = SWT.None;
+        
+        disposing = true;
+        
+        cellHeaderSelectionBackground.dispose();
+
+        for (Iterator iterator = items.iterator(); iterator.hasNext();)
+        {
+            GridItem item = (GridItem)iterator.next();
+            item.dispose();
+        }
+        
+        for (int i = 0; i < columnGroups.length; i++)
+        {
+            columnGroups[i].dispose();
+        }
+        
+        for (Iterator iterator = columns.iterator(); iterator.hasNext();)
+        {
+            GridColumn col = (GridColumn)iterator.next();
+            col.dispose();
+        }
+        
+        sizingGC.dispose();
+    }
+
+    /**
+     * Mouse wheel event handler.
+     * 
+     * @param e event
+     */
+    private void onMouseWheel(Event e)
+    {
+        if (vScroll.getVisible())
+        {
+            vScroll.handleMouseWheel(e);
+            if (getVerticalBar() == null)
+                e.doit = false;    
+        }
+        else if (hScroll.getVisible())
+        {
+            hScroll.handleMouseWheel(e);
+            if (getHorizontalBar() == null)
+                e.doit = false;    
+        }
+    }
+
+    /**
+     * Mouse down event handler.
+     * 
+     * @param e event
+     */
+    private void onMouseDown(MouseEvent e)
+    {
+        // for some reason, SWT prefers the children to get focus if
+        // there are any children
+        // the setFocus method on Composite will not set focus to the
+        // Composite if one of its
+        // children can get focus instead. This only affects the table
+        // when an editor is open
+        // and therefore the table has a child. The solution is to
+        // forceFocus()
+        if ((getStyle() & SWT.NO_FOCUS) != SWT.NO_FOCUS)
+        {
+            forceFocus();
+        }        
+        
+        hideToolTip();
+        
+        //if populated will be fired at end of method.
+        Event selectionEvent = null;
+        
+        cellSelectedOnLastMouseDown = false;
+        cellRowSelectedOnLastMouseDown = false;
+        cellColumnSelectedOnLastMouseDown = false;
+
+        if (hoveringOnColumnResizer)
+        {
+            if (e.button == 1)
+            {
+                resizingColumn = true;
+                resizingStartX = e.x;
+                resizingColumnStartWidth = columnBeingResized.getWidth();
+            }
+            return;
+        }
+        if (rowsResizeable && hoveringOnRowResizer)
+        {
+            if (e.button == 1)
+            {
+                resizingRow = true;
+                resizingStartY = e.y;
+                resizingRowStartHeight = rowBeingResized.getHeight();
+            }
+            return;
+        }
+
+
+        if (e.button == 1 && handleColumnHeaderPush(e.x, e.y))
+        {
+            return;
+        }
+
+        if (e.button == 1 && handleColumnGroupHeaderClick(e.x, e.y))
+        {
+            return;
+        }
+
+        GridItem item = getItem(new Point(e.x, e.y));
+        
+        if (e.button == 1 && item != null && handleCellClick(item,e.x, e.y))
+        {
+            return;
+        }
+        
+        if (isListening(SWT.DragDetect))
+        {
+            if ((cellSelectionEnabled && hoveringOnSelectionDragArea) ||
+                (!cellSelectionEnabled && item != null && selectedItems.contains(item)))
+            {
+                if(dragDetect(e))
+                {
+                    return;
+                }
+            }
+        }
+        
+        if (item != null)
+        {
+            if (cellSelectionEnabled)
+            {
+                GridColumn col = getColumn(new Point(e.x, e.y));
+                boolean isSelectedCell = false;
+                if (col != null)
+                    isSelectedCell = selectedCells.contains(new Point(indexOf(col),indexOf(item)));
+                
+                if (e.button == 1 || (e.button == 3 && col != null && !isSelectedCell))
+                {
+                    if (col != null)
+                    {
+                        selectionEvent = updateCellSelection(new Point(indexOf(col),indexOf(item)), e.stateMask, false, true);
+                        cellSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
+                        
+                        if (e.stateMask != SWT.SHIFT)
+                        {
+                            focusColumn = col;
+                            focusItem = item;
+                        }
+                        //showColumn(col);
+                        showItem(item);
+                        redraw();
+                    }      
+                    else if (rowHeaderVisible)
+                    {
+                        if (e.x <= rowHeaderWidth)
+                        {
+                            
+                            boolean shift = ((e.stateMask & SWT.SHIFT) != 0);
+                            boolean ctrl = false;
+                            if (!shift)
+                            {
+                                ctrl = ((e.stateMask & SWT.CTRL) != 0);
+                            }
+                            
+                            Vector cells = new Vector();
+                            
+                            if (shift)
+                            {
+                                getCells(item,focusItem,cells);
+                            }
+                            else
+                            {
+                                getCells(item,cells);
+                            }
+                            
+                            int newStateMask = SWT.NONE;
+                            if (ctrl) newStateMask = SWT.CTRL;
+                            
+                            selectionEvent = updateCellSelection(cells, newStateMask, shift, ctrl);
+                            cellRowSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
+                            
+                            if (!shift)
+                            {
+                                //set focus back to the first visible column
+                                focusColumn = getColumn(new Point(rowHeaderWidth + 1,e.y));
+                                
+                                focusItem = item;
+                            }
+                            showItem(item);
+                            redraw();
+                        }
+                    }
+                    intendedFocusColumn = focusColumn;
+                }
+            }
+            else
+            {
+                if (e.button == 2 || e.button > 3)
+                {
+                    return;
+                }
+                
+                if (e.button == 3 && selectionType == SWT.MULTI)
+                {
+                    if ((e.stateMask & SWT.SHIFT) == SWT.SHIFT)
+                    {
+                        return;
+                    }
+
+                    if ((e.stateMask & SWT.CTRL) == SWT.CTRL)
+                    {
+                        return;
+                    }                        
+                    
+                    if (selectedItems.contains(item))
+                    {
+                        return;
+                    }                    
+                }
+                selectionEvent = updateSelection(item, e.stateMask);
+                
+                
+                focusItem = item;
+                showItem(item);
+                redraw();
+            }
+        }
+        else if (cellSelectionEnabled && e.button == 1 && rowHeaderVisible && e.x <= rowHeaderWidth && e.y < headerHeight)
+        {            
+            //click on the top left corner means select everything
+            selectAllCells();
+            
+            focusColumn = getColumn(new Point(rowHeaderWidth + 1,1));
+            focusItem = getItem(getTopIndex());
+        }
+        else if (cellSelectionEnabled && e.button == 1 && columnHeadersVisible && e.y <= headerHeight)
+        {
+            //column cell selection
+            GridColumn col = getColumn(new Point(e.x,e.y));
+            
+            if (col == null) return;
+            
+            if (col.getColumnGroup() != null && e.y < groupHeaderHeight)
+                return;
+            
+            if (getItemCount() == 0)
+                return;
+
+            
+            Vector cells = new Vector();
+            
+            getCells(col,cells);
+            
+            selectionEvent = updateCellSelection(cells, e.stateMask, false, true);
+            cellColumnSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
+            
+            GridItem newFocusItem = getItem(0);
+            
+            while (newFocusItem != null && getSpanningColumn(newFocusItem, col) != null)
+            {
+                newFocusItem = getNextVisibleItem(newFocusItem);
+            }
+
+            if (newFocusItem != null)
+            {
+                focusColumn = col;
+                focusItem = newFocusItem;
+            }
+           
+            showColumn(col);
+            redraw();
+        }
+        
+        if (selectionEvent != null)
+        {
+            selectionEvent.stateMask = e.stateMask;
+            notifyListeners(SWT.Selection, selectionEvent);
+            
+            if (!cellSelectionEnabled)
+            {
+                if (isListening(SWT.DragDetect))
+                {
+                    dragDetect(e);
+                }
+            }
+        }
+        
+        
+    }
+
+    /**
+     * Mouse double click event handler.
+     * 
+     * @param e event
+     */
+    private void onMouseDoubleClick(MouseEvent e)
+    {
+        if (e.button == 1)
+        {
+            
+            if (hoveringOnColumnResizer)
+            {
+                columnBeingResized.pack();
+                resizingColumn = false;
+                handleHoverOnColumnResizer(e.x, e.y);
+                return;
+            }
+            else if (rowsResizeable && hoveringOnRowResizer) {
+                List sel = Arrays.asList(getSelection());
+                if(sel.contains(rowBeingResized))
+                {
+                    // the user double-clicked a row resizer of a selected row
+                    // so update all selected rows
+                    for(int cnt=0;cnt<sel.size();cnt++)
+                        ((GridItem)sel.get(cnt)).pack();
+                    redraw();
+                }
+                else
+                {
+                    // otherwise only update the row the user double-clicked
+                    rowBeingResized.pack();
+                }
+
+                resizingRow = false;
+                handleHoverOnRowResizer(e.x, e.y);
+                return;
+            }
+
+            GridItem item = getItem(new Point(e.x, e.y));
+            if (item != null)
+            {
+                if (isListening(SWT.DefaultSelection))
+                {
+                Event newEvent = new Event();
+                newEvent.item = item;
+    
+                notifyListeners(SWT.DefaultSelection, newEvent);
+                }
+                else if (item.getItemCount() > 0)
+                {
+                      item.setExpanded(!item.isExpanded());
+                      
+                    if (item.isExpanded())
+                    {
+                        item.fireEvent(SWT.Expand);
+                    }
+                    else
+                    {
+                        item.fireEvent(SWT.Collapse);
+                    }
+                }
+            }        
+        }
+    }
+
+    /**
+     * Mouse up handler.
+     * 
+     * @param e event
+     */
+    private void onMouseUp(MouseEvent e)
+    {
+        cellSelectedOnLastMouseDown = false;
+        
+        if (resizingColumn)
+        {
+            resizingColumn = false;
+            handleHoverOnColumnResizer(e.x, e.y); // resets cursor if
+            // necessary
+            return;
+        }
+        if (resizingRow)
+        {
+            resizingRow = false;
+            handleHoverOnRowResizer(e.x, e.y); // resets cursor if
+            // necessary
+            return;
+        }
+
+        if (pushingColumn)
+        {
+            pushingColumn = false;
+            columnBeingPushed.getHeaderRenderer().setMouseDown(false);
+            columnBeingPushed.getHeaderRenderer().setHover(false);
+            redraw();
+            if (pushingAndHovering)
+            {
+                columnBeingPushed.fireListeners();
+            }
+            setCapture(false);
+            return;
+        }
+
+        if (draggingColumn)
+        {
+            handleColumnDrop();
+            return;
+        }
+        
+        if (cellDragSelectionOccuring || cellRowDragSelectionOccuring || cellColumnDragSelectionOccuring)
+        {
+            cellDragSelectionOccuring = false;
+            cellRowDragSelectionOccuring = false;
+            cellColumnDragSelectionOccuring = false;
+            setCursor(null);
+            
+            if (followupCellSelectionEventOwed)
+            {
+                notifyListeners(SWT.Selection, new Event());
+                followupCellSelectionEventOwed = false;
+            }
+        }
+    }
+
+    /**
+     * Mouse move event handler.
+     * 
+     * @param e event
+     */
+    private void onMouseMove(MouseEvent e)
+    {
+        //check to see if the mouse is outside the grid
+        //this should only happen when the mouse is captured for inplace
+        //tooltips - see bug 203364
+        if (inplaceTooltipCapture && (e.x < 0 || e.y < 0 || e.x >= getBounds().width || e.y >= getBounds().height))
+        {
+            setCapture(false);
+            inplaceTooltipCapture = false;
+            return;  //a mouseexit event should occur immediately
+        }
+
+        
+        //if populated will be fired at end of method.
+        Event selectionEvent = null;
+        
+        
+        if ((e.stateMask & SWT.BUTTON1) == 0)
+        {
+            handleHovering(e.x, e.y);
+        }
+        else
+        {
+            if (draggingColumn)
+            {
+                handleColumnDragging(e.x);
+                return;
+            }
+
+            if (resizingColumn)
+            {
+                handleColumnResizerDragging(e.x);
+                return;
+            }
+            if (resizingRow)
+            {
+                handleRowResizerDragging(e.y);
+                return;
+            }
+            if (pushingColumn)
+            {
+                handleColumnHeaderHoverWhilePushing(e.x, e.y);
+                return;
+            }
+            if (cellSelectionEnabled)
+            {                
+                if (!cellDragSelectionOccuring && cellSelectedOnLastMouseDown)
+                {
+                    cellDragSelectionOccuring = true;
+                    //XXX: make this user definable
+                    setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
+                    cellDragCTRL = ((e.stateMask & SWT.CTRL) != 0);
+                    if (cellDragCTRL)
+                    {
+                        selectedCellsBeforeRangeSelect.clear();
+                        selectedCellsBeforeRangeSelect.addAll(selectedCells);
+                    }
+                }
+                if (!cellRowDragSelectionOccuring && cellRowSelectedOnLastMouseDown)
+                {
+                    cellRowDragSelectionOccuring = true;
+                    setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
+                    cellDragCTRL = ((e.stateMask & SWT.CTRL) != 0);
+                    if (cellDragCTRL)
+                    {
+                        selectedCellsBeforeRangeSelect.clear();
+                        selectedCellsBeforeRangeSelect.addAll(selectedCells);
+                    }
+                }
+                
+                if (!cellColumnDragSelectionOccuring && cellColumnSelectedOnLastMouseDown)
+                {
+                    cellColumnDragSelectionOccuring = true;
+                    setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
+                    cellDragCTRL = ((e.stateMask & SWT.CTRL) != 0);
+                    if (cellDragCTRL)
+                    {
+                        selectedCellsBeforeRangeSelect.clear();
+                        selectedCellsBeforeRangeSelect.addAll(selectedCells);
+                    }
+                }
+                
+                int ctrlFlag = (cellDragCTRL ? SWT.CTRL : SWT.NONE);
+                
+                if (cellDragSelectionOccuring && handleCellHover(e.x, e.y))
+                {
+                    GridColumn intentColumn = hoveringColumn;
+                    GridItem intentItem = hoveringItem;
+                    
+                    if (hoveringItem == null)
+                    {
+                        if (e.y > headerHeight)
+                        {
+                            //then we must be hovering way to the bottom
+                            intentItem = getPreviousVisibleItem(null);
+                        }
+                        else
+                        {
+                            intentItem = (GridItem)items.get(0);
+                        }
+                    }
+                    
+                    
+                    if (hoveringColumn == null)
+                    {                      
+                        if (e.x > rowHeaderWidth)
+                        {
+                            //then we must be hovering way to the right
+                            intentColumn = getVisibleColumn_DegradeLeft(intentItem,(GridColumn)displayOrderedColumns.get(displayOrderedColumns.size() - 1));
+                        }
+                        else
+                        {
+                            GridColumn firstCol = (GridColumn)displayOrderedColumns.get(0);
+                            if (!firstCol.isVisible())
+                            {
+                                firstCol = getNextVisibleColumn(firstCol);
+                            }
+                            intentColumn = firstCol;
+                        }
+                    }
+                    
+                    showColumn(intentColumn);
+                    showItem(intentItem);
+                    selectionEvent = updateCellSelection(new Point(indexOf(intentColumn),indexOf(intentItem)),ctrlFlag | SWT.SHIFT, true, false);
+                }
+                if (cellRowDragSelectionOccuring && handleCellHover(e.x, e.y))
+                {
+                    GridItem intentItem = hoveringItem;
+                    
+                    if (hoveringItem == null)
+                    {
+                        if (e.y > headerHeight)
+                        {
+                            //then we must be hovering way to the bottom
+                            intentItem = getPreviousVisibleItem(null);
+                        }
+                        else
+                        {
+                            if (getTopIndex() > 0)
+                            {
+                                intentItem = getPreviousVisibleItem((GridItem)items.get(getTopIndex()));
+                            }
+                            else
+                            {
+                                intentItem = (GridItem)items.get(0);
+                            }
+                        }
+                    }
+
+                    Vector cells = new Vector();
+                    
+                    getCells(intentItem,focusItem,cells);
+                                        
+                    showItem(intentItem);
+                    selectionEvent = updateCellSelection(cells,ctrlFlag, true, false);
+                }
+                if (cellColumnDragSelectionOccuring && handleCellHover(e.x, e.y))
+                {
+                    GridColumn intentCol = hoveringColumn;
+                    
+                    if (intentCol == null)
+                    {
+                        if (e.y < rowHeaderWidth)
+                        {
+                            //TODO: get the first col to the left
+                        }
+                        else
+                        {
+                            //TODO: get the first col to the right
+                        }
+                    }
+                    
+                    if (intentCol == null) return;  //temporary
+                    
+                    GridColumn iterCol = intentCol;
+                    
+                    Vector newSelected = new Vector();
+                    
+                    boolean decreasing = (displayOrderedColumns.indexOf(iterCol) > displayOrderedColumns.indexOf(focusColumn));
+                                      
+                    do
+                    {
+                        getCells(iterCol, newSelected);
+                                                
+                        if (iterCol == focusColumn)
+                        {
+                            break;
+                        }
+                         
+                        if (decreasing)
+                        {
+                            iterCol = getPreviousVisibleColumn(iterCol);
+                        }
+                        else
+                        {
+                            iterCol = getNextVisibleColumn(iterCol);
+                        }
+   
+                    } while (true);                    
+                    
+                    selectionEvent = updateCellSelection(newSelected, ctrlFlag, true, false);
+                }
+                
+            }
+        }
+        
+        if (selectionEvent != null)
+        {
+            selectionEvent.stateMask = e.stateMask;
+            notifyListeners(SWT.Selection, selectionEvent);
+        }
+    }
+
+    /**
+     * Handles the assignment of the correct values to the hover* field
+     * variables that let the painting code now what to paint as hovered.
+     * 
+     * @param x mouse x coordinate
+     * @param y mouse y coordinate
+     */
+    private void handleHovering(int x, int y)
+    {
+        // TODO: need to clean up and refactor hover code
+        handleCellHover(x, y);
+
+        // Is this Grid a DragSource ??
+        if (cellSelectionEnabled && getData("DragSource") != null) {
+            if (handleHoverOnSelectionDragArea(x, y))
+            {
+                return;
+            }
+        }
+
+        if (columnHeadersVisible)
+        {
+            if (handleHoverOnColumnResizer(x, y))
+            {
+//                if (hoveringItem != null || !hoveringDetail.equals("") || hoveringColumn != null
+//                    || hoveringColumnHeader != null || hoverColumnGroupHeader != null)
+//                {
+//                    hoveringItem = null;
+//                    hoveringDetail = "";
+//                    hoveringColumn = null;
+//                    hoveringColumnHeader = null;
+//                    hoverColumnGroupHeader = null;
+//
+//                    Rectangle clientArea = getClientArea();
+//                    redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+//                }
+                return;
+            }
+        }
+        if (rowsResizeable && rowHeaderVisible)
+        {
+            if (handleHoverOnRowResizer(x, y))
+            {
+                return;
+            }
+        }
+
+       // handleCellHover(x, y);
+    }
+
+    /**
+     * Refreshes the hover* variables according to the mouse location and
+     * current state of the table. This is useful is some method call, caused
+     * the state of the table to change and therefore the hover effects may have
+     * become out of date.
+     */
+    protected void refreshHoverState()
+    {
+        Point p = getDisplay().map(null, this, getDisplay().getCursorLocation());
+        handleHovering(p.x, p.y);
+    }
+
+    /**
+     * Mouse exit event handler.
+     * 
+     * @param e event
+     */
+    private void onMouseExit(MouseEvent e)
+    {
+            hoveringItem = null;
+            hoveringDetail = "";
+            hoveringColumn = null;
+            hoveringOverText = false;
+            hideToolTip();
+            redraw();
+    }
+
+    /**
+     * Key down event handler.
+     * 
+     * @param e event
+     */
+    private void onKeyDown(Event e)
+    {  
+        if (focusColumn == null)
+        {
+            if (columns.size() == 0)
+                return;
+            
+            focusColumn = getColumn(0);
+            intendedFocusColumn = focusColumn;
+        }
+        
+        if (e.character == '\r' && focusItem != null)
+        {
+            Event newEvent = new Event();
+            newEvent.item = focusItem;
+
+            notifyListeners(SWT.DefaultSelection, newEvent);
+            return;
+        }
+        
+        int attemptExpandCollapse = 0;
+        if ((e.character == '-' || (!cellSelectionEnabled && e.keyCode == SWT.ARROW_LEFT)) && focusItem != null && focusItem.isExpanded())
+        {
+            attemptExpandCollapse = SWT.Collapse;
+        }
+        else if ((e.character == '+' || (!cellSelectionEnabled && e.keyCode == SWT.ARROW_RIGHT)) && focusItem != null && !focusItem.isExpanded())
+        {
+            attemptExpandCollapse = SWT.Expand;
+        }
+               
+        if (attemptExpandCollapse != 0 && focusItem != null && focusItem.hasChildren())
+        {
+            int performExpandCollapse = 0;
+            
+            if (cellSelectionEnabled && focusColumn != null && focusColumn.isTree())
+            {
+                performExpandCollapse = attemptExpandCollapse;
+            }
+            else if (!cellSelectionEnabled)
+            {
+                performExpandCollapse = attemptExpandCollapse;
+            }
+
+            if (performExpandCollapse == SWT.Expand)
+            {
+                focusItem.setExpanded(true);
+                focusItem.fireEvent(SWT.Expand);
+                return;
+            }
+            if (performExpandCollapse == SWT.Collapse)
+            {
+                focusItem.setExpanded(false);
+                focusItem.fireEvent(SWT.Collapse);
+                return;
+            }
+        }
+        
+        if (e.character == ' ')
+        {
+            handleSpaceBarDown(e);
+        }
+        
+        
+        GridItem newSelection = null;
+        GridColumn newColumnFocus = null;
+        
+        //These two variables are used because the key navigation when the shift key is down is
+        //based, not off the focus item/column, but rather off the implied focus (i.e. where the 
+        //keyboard has extended focus to).  
+        GridItem impliedFocusItem = focusItem;
+        GridColumn impliedFocusColumn = focusColumn;
+        
+        if (cellSelectionEnabled && e.stateMask == SWT.SHIFT)
+        {
+            if (shiftSelectionAnchorColumn != null)
+            {
+                impliedFocusItem = shiftSelectionAnchorItem;
+                impliedFocusColumn = shiftSelectionAnchorColumn;
+            }
+        }
+        
+        switch (e.keyCode)
+        {
+            case SWT.ARROW_RIGHT :
+                if (cellSelectionEnabled)
+                {
+                    if (impliedFocusItem != null && impliedFocusColumn != null)
+                    {                    
+                        newSelection = impliedFocusItem;                    
+                        
+                        int index = displayOrderedColumns.indexOf(impliedFocusColumn);
+                        
+                        int jumpAhead = impliedFocusItem.getColumnSpan(indexOf(impliedFocusColumn));
+                        
+                        jumpAhead ++;
+                        
+                        while (jumpAhead > 0)
+                        {
+                            index ++;
+                            if (index < displayOrderedColumns.size())
+                            {
+                                if (((GridColumn)displayOrderedColumns.get(index)).isVisible())
+                                    jumpAhead --;
+                            }
+                            else
+                            {
+                                break;
+                            }
+                        }
+                        
+                        if (index < displayOrderedColumns.size())
+                        {
+                            newColumnFocus = (GridColumn)displayOrderedColumns.get(index);                    
+                        }
+                        else
+                        {
+                            newColumnFocus = impliedFocusColumn;
+                        }                    
+                    }      
+                    intendedFocusColumn = newColumnFocus;
+                }
+                else
+                {
+                    if (impliedFocusItem != null && impliedFocusItem.hasChildren())
+                    {   
+                        newSelection = impliedFocusItem.getItem(0);
+                    }
+                }
+                break;            
+            case SWT.ARROW_LEFT :
+                if (cellSelectionEnabled)
+                {
+                    if (impliedFocusItem != null && impliedFocusColumn != null)
+                    {                    
+                        newSelection = impliedFocusItem;
+                        
+                        int index = displayOrderedColumns.indexOf(impliedFocusColumn);
+                        
+                        if (index != 0)
+                        {
+                            newColumnFocus = (GridColumn)displayOrderedColumns.get(index -1);
+                            
+                            newColumnFocus = getVisibleColumn_DegradeLeft(impliedFocusItem, newColumnFocus);
+                        }
+                        else
+                        {
+                            newColumnFocus = impliedFocusColumn;
+                        }                    
+                    }
+                    intendedFocusColumn = newColumnFocus;
+                }
+                else
+                {
+                    if (impliedFocusItem != null && impliedFocusItem.getParentItem() != null)
+                    {
+                        newSelection = impliedFocusItem.getParentItem();
+                    }
+                }
+                break;
+            case SWT.ARROW_UP :
+                if (impliedFocusItem != null)
+                {
+                    newSelection = getPreviousVisibleItem(impliedFocusItem); 
+                }
+                
+                if (impliedFocusColumn != null)
+                {
+                    if (newSelection != null)
+                    {
+                        newColumnFocus = getVisibleColumn_DegradeLeft(newSelection, intendedFocusColumn);
+                    }
+                    else
+                    {
+                        newColumnFocus = impliedFocusColumn;
+                    }
+                }
+                
+                break;
+            case SWT.ARROW_DOWN :
+                if (impliedFocusItem != null)
+                {
+                    newSelection = getNextVisibleItem(impliedFocusItem); 
+                }
+                else
+                {
+                    if (items.size() > 0)
+                    {
+                        newSelection = (GridItem)items.get(0);
+                    }                  
+                }
+                
+                if (impliedFocusColumn != null)
+                {
+                    if (newSelection != null)
+                    {
+                        newColumnFocus = getVisibleColumn_DegradeLeft(newSelection, intendedFocusColumn);
+                    }
+                    else
+                    {
+                        newColumnFocus = impliedFocusColumn;
+                    }
+                }                
+                break;
+            case SWT.HOME :
+                
+                if (!cellSelectionEnabled)
+                {
+                    if (items.size() > 0)
+                    {
+                        newSelection = (GridItem)items.get(0);
+                    }
+                }
+                else
+                {
+                    newSelection = impliedFocusItem;
+                    newColumnFocus = getVisibleColumn_DegradeRight(newSelection,(GridColumn)displayOrderedColumns.get(0));
+                }
+
+                break;                
+            case SWT.END :
+                if (!cellSelectionEnabled)
+                {
+                    if (items.size() > 0)
+                    {
+                        newSelection = getPreviousVisibleItem(null);
+                    } 
+                }
+                else
+                {
+                    newSelection = impliedFocusItem;
+                    newColumnFocus = getVisibleColumn_DegradeLeft(newSelection,(GridColumn)displayOrderedColumns.get(displayOrderedColumns.size() - 1));                    
+                }
+                
+                break;
+            case SWT.PAGE_UP :
+                int topIndex = getTopIndex();
+
+                newSelection = (GridItem)items.get(topIndex);
+                
+                if (focusItem == newSelection)
+                {
+                    RowRange range = getRowRange(getTopIndex(),getVisibleGridHeight(),false,true);
+                    newSelection = (GridItem)items.get(range.startIndex);
+                }
+                
+                newColumnFocus = focusColumn;
+                break;
+            case SWT.PAGE_DOWN :
+                int bottomIndex = getBottomIndex();
+                
+                newSelection = (GridItem)items.get(bottomIndex);
+
+                if(!isShown(newSelection))
+                {
+                    // the item at bottom index is not shown completely
+                    GridItem tmpItem = getPreviousVisibleItem(newSelection);
+                    if(tmpItem!=null)
+                        newSelection = tmpItem;
+                }
+
+                if (focusItem == newSelection)
+                {
+                    RowRange range = getRowRange(getBottomIndex(),getVisibleGridHeight(),true,false);
+                    newSelection = (GridItem)items.get(range.endIndex);
+                }
+                
+                newColumnFocus = focusColumn;
+                break;
+            default :
+                break;
+        }
+        
+        if (newSelection == null)
+        {
+            return;
+        }
+
+        if (cellSelectionEnabled)
+        {  
+            if (e.stateMask != SWT.SHIFT)
+                focusColumn = newColumnFocus;
+            showColumn(newColumnFocus);
+            
+            if (e.stateMask != SWT.SHIFT)
+                focusItem = newSelection;
+            showItem(newSelection);
+            
+            if (e.stateMask != SWT.CTRL)
+            {
+                Event selEvent = updateCellSelection(new Point(indexOf(newColumnFocus),indexOf(newSelection)),e.stateMask, false, false);
+                if (selEvent != null)
+                {
+                    selEvent.stateMask = e.stateMask;
+                    notifyListeners(SWT.Selection, selEvent);
+                }                
+            }
+            
+            redraw();
+        }
+        else
+        {            
+            Event selectionEvent = null;
+            if (selectionType == SWT.SINGLE || e.stateMask != SWT.CTRL)
+            {
+                selectionEvent = updateSelection(newSelection, e.stateMask);
+                if (selectionEvent != null) 
+                    selectionEvent.stateMask = e.stateMask;
+            }
+            
+            focusItem = newSelection;
+            showItem(newSelection);            
+            redraw();
+            
+            if (selectionEvent != null) 
+                notifyListeners(SWT.Selection, selectionEvent);
+        }
+    }
+    
+    private void handleSpaceBarDown(Event event)
+    {        
+        if (focusItem == null)
+            return;
+        
+        if (selectionEnabled && !cellSelectionEnabled && !selectedItems.contains(focusItem))
+        {
+            selectedItems.add(focusItem);
+            redraw();
+            Event e = new Event();
+            e.item = focusItem;
+            e.stateMask = event.stateMask;
+            notifyListeners(SWT.Selection, e);
+        }
+        
+        if (!cellSelectionEnabled)
+        {
+            boolean checkFirstCol = false;
+            boolean first = true;
+            
+            for (Iterator iter = columns.iterator(); iter.hasNext();)
+            {
+                GridColumn col = (GridColumn)iter.next();
+                
+                if (first)
+                {
+                    if (!col.isCheck()) break;
+                    
+                    first = false;
+                    checkFirstCol = true;
+                }
+                else
+                {
+                    if (col.isCheck())
+                    {
+                        checkFirstCol = false;
+                        break;
+                    }
+                }
+            }
+         
+            if (checkFirstCol)
+            {
+                focusItem.setChecked(!focusItem.getChecked());
+                redraw();
+                focusItem.fireCheckEvent(0);            
+            }
+        }
+    }
+
+    /**
+     * Resize event handler.
+     */
+    private void onResize()
+    {
+        
+        //CGross 1/2/08 - I don't really want to be doing this....
+        //I shouldn't be changing something you user configured...
+        //leaving out for now
+//        if (columnScrolling)
+//        {
+//            int maxWidth = getClientArea().width;
+//            if (rowHeaderVisible)
+//                maxWidth -= rowHeaderWidth;
+//            
+//            for (Iterator cols = columns.iterator(); cols.hasNext();) {
+//                GridColumn col = (GridColumn) cols.next();
+//                if (col.getWidth() > maxWidth)
+//                    col.setWidth(maxWidth);
+//            }
+//        }
+        
+        scrollValuesObsolete = true;
+        topIndex = -1;
+        bottomIndex = -1;
+    }
+
+    /**
+     * Scrollbar selection event handler.
+     */
+    private void onScrollSelection()
+    {
+        topIndex = -1;
+        bottomIndex = -1;
+        refreshHoverState();
+        redraw(getClientArea().x, getClientArea().y, getClientArea().width, getClientArea().height,
+               false);
+    }
+
+    /**
+     * Returns the intersection of the given column and given item.
+     * 
+     * @param column column
+     * @param item item
+     * @return x,y of top left corner of the cell
+     */
+    Point getOrigin(GridColumn column, GridItem item)
+    {
+        int x = 0;
+
+        if (rowHeaderVisible)
+        {
+            x += rowHeaderWidth;
+        }
+        
+        x -= getHScrollSelectionInPixels();
+
+        for (Iterator colIterIterator = displayOrderedColumns.iterator(); colIterIterator.hasNext(); )
+        {
+            GridColumn colIter = (GridColumn) colIterIterator.next();
+            
+            if (colIter == column)
+            {
+                break;
+            }
+
+            if (colIter.isVisible())
+            {
+                x += colIter.getWidth();
+            }
+        }
+
+        int y = 0;
+        if (item != null)
+        {
+            if (columnHeadersVisible)
+            {
+                y += headerHeight;
+            }
+
+            int currIndex=getTopIndex();
+            int itemIndex=items.indexOf(item);
+            
+            if (itemIndex == -1)
+            {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+            
+            while(currIndex!=itemIndex)
+            {
+                if(currIndex<itemIndex)
+                {
+                    GridItem currItem = (GridItem)items.get(currIndex);
+                    if(currItem.isVisible())
+                    {
+                        y += currItem.getHeight() + 1;
+                    }
+                    currIndex++;
+                }
+                else if(currIndex>itemIndex)
+                {
+                    currIndex--;
+                    GridItem currItem = (GridItem)items.get(currIndex);
+                    if(currItem.isVisible())
+                    {
+                        y -= currItem.getHeight() + 1;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (column.getColumnGroup() != null)
+            {
+                y += groupHeaderHeight;
+            }
+        }
+
+        return new Point(x, y);
+    }
+
+    /**
+     * Determines (which cell/if a cell) has been clicked (mouse down really)
+     * and notifies the appropriate renderer. Returns true when a cell has
+     * responded to this event in some way and prevents the event from
+     * triggering an action further down the chain (like a selection).
+     * 
+     * @param item item clicked
+     * @param x mouse x
+     * @param y mouse y
+     * @return true if this event has been consumed.
+     */
+    private boolean handleCellClick(GridItem item, int x, int y)
+    {
+
+        // if(!isTree)
+        // return false;
+
+        GridColumn col = getColumn(new Point(x, y));
+        if (col == null)
+        {
+            return false;
+        }
+
+        col.getCellRenderer().setBounds(item.getBounds(indexOf(col)));
+        return col.getCellRenderer().notify(IInternalWidget.LeftMouseButtonDown, new Point(x, y), item);
+
+    }
+
+    /**
+     * Sets the hovering variables (hoverItem,hoveringColumn) as well as
+     * hoverDetail by talking to the cell renderers. Triggers a redraw if
+     * necessary.
+     * 
+     * @param x mouse x
+     * @param y mouse y
+     * @return true if a new section of the table is now being hovered
+     */
+    private boolean handleCellHover(int x, int y)
+    {
+
+        String detail = "";
+        
+        boolean overText = false;
+
+        final GridColumn col = getColumn(new Point(x, y));
+        final GridItem item = getItem(new Point(x, y));
+
+        GridColumnGroup hoverColGroup = null;
+        GridColumn hoverColHeader = null;
+
+        if (col != null)
+        {
+            if (item != null)
+            {
+                col.getCellRenderer().setBounds(item.getBounds(columns.indexOf(col)));
+
+                if (col.getCellRenderer().notify(IInternalWidget.MouseMove, new Point(x, y), item))
+                {
+                    detail = col.getCellRenderer().getHoverDetail();
+                }
+
+                Rectangle textBounds = col.getCellRenderer().getTextBounds(item,false);
+                
+                if (textBounds != null)
+                {
+                    Point p = new Point(x - col.getCellRenderer().getBounds().x, y - col.getCellRenderer().getBounds().y);
+                    overText = textBounds.contains(p);                  
+                }               
+            }
+            else
+            {
+                if (y < headerHeight)
+                {
+                    if (columnGroups.length != 0 && y < groupHeaderHeight
+                        && col.getColumnGroup() != null)
+                    {
+                        hoverColGroup = col.getColumnGroup();
+                        hoverColGroup.getHeaderRenderer().setBounds(hoverColGroup.getBounds());
+                        if (hoverColGroup.getHeaderRenderer()
+                            .notify(IInternalWidget.MouseMove, new Point(x, y), hoverColGroup))
+                        {
+                            detail = hoverColGroup.getHeaderRenderer().getHoverDetail();
+                        }
+                        
+                        Rectangle textBounds = hoverColGroup.getHeaderRenderer().getTextBounds(hoverColGroup,false);
+                        
+                        if (textBounds != null)
+                        {
+                            Point p = new Point(x - hoverColGroup.getHeaderRenderer().getBounds().x, y - hoverColGroup.getHeaderRenderer().getBounds().y);
+                            overText = textBounds.contains(p);                  
+                        }  
+                    }
+                    else
+                    {
+                        // on col header
+                        hoverColHeader = col;
+
+                        col.getHeaderRenderer().setBounds(col.getBounds());
+                        if (col.getHeaderRenderer().notify(IInternalWidget.MouseMove, new Point(x, y),
+                                                           col))
+                        {
+                            detail = col.getHeaderRenderer().getHoverDetail();
+                        }
+                        
+                        Rectangle textBounds = col.getHeaderRenderer().getTextBounds(col,false);
+                        
+                        if (textBounds != null)
+                        {
+                            Point p = new Point(x - col.getHeaderRenderer().getBounds().x, y - col.getHeaderRenderer().getBounds().y);
+                            overText = textBounds.contains(p);                  
+                        }  
+                    }
+                }
+            }
+        }
+
+        boolean hoverChange = false;
+        
+        if (hoveringItem != item || !hoveringDetail.equals(detail) || hoveringColumn != col
+            || hoverColGroup != hoverColumnGroupHeader || hoverColHeader != hoveringColumnHeader)
+        {
+            hoveringItem = item;
+            hoveringDetail = detail;
+            hoveringColumn = col;
+            hoveringColumnHeader = hoverColHeader;
+            hoverColumnGroupHeader = hoverColGroup;
+            
+            Rectangle clientArea = getClientArea();
+            redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+
+            hoverChange = true;
+        }
+        
+        //do inplace toolTip stuff
+        if (hoverChange || hoveringOverText != overText)
+        {
+            hoveringOverText = overText;
+            
+            if (overText){
+                
+                Rectangle cellBounds = null;
+                Rectangle textBounds = null;
+                Rectangle preferredTextBounds = null;
+                
+                if (hoveringItem != null && hoveringItem.getToolTipText(indexOf(col)) == null && //no inplace tooltips when regular tooltip
+                        !col.getWordWrap()) //dont show inplace tooltips for cells with wordwrap
+                {                    
+                    cellBounds = col.getCellRenderer().getBounds();                    
+                    if (cellBounds.x + cellBounds.width > getSize().x)
+                    {
+                        cellBounds.width = getSize().x - cellBounds.x;
+                    }                    
+                    textBounds = col.getCellRenderer().getTextBounds(item,false);
+                    preferredTextBounds = col.getCellRenderer().getTextBounds(item,true);
+                }
+                else if (hoveringColumnHeader != null)
+                {
+                    cellBounds = hoveringColumnHeader.getHeaderRenderer().getBounds();
+                    if (cellBounds.x + cellBounds.width > getSize().x)
+                    {
+                        cellBounds.width = getSize().x - cellBounds.x;
+                    }
+                    textBounds = hoveringColumnHeader.getHeaderRenderer().getTextBounds(col,false);
+                    preferredTextBounds = hoveringColumnHeader.getHeaderRenderer().getTextBounds(col,true);
+                }
+                else if (hoverColumnGroupHeader != null)
+                {
+                    cellBounds = hoverColumnGroupHeader.getHeaderRenderer().getBounds();
+                    if (cellBounds.x + cellBounds.width > getSize().x)
+                    {
+                        cellBounds.width = getSize().x - cellBounds.x;
+                    }
+                    textBounds = hoverColumnGroupHeader.getHeaderRenderer().getTextBounds(hoverColumnGroupHeader,false);
+                    preferredTextBounds = hoverColumnGroupHeader.getHeaderRenderer().getTextBounds(hoverColumnGroupHeader,true);
+                }
+                
+                //if we are truncated
+                if (textBounds != null && textBounds.width < preferredTextBounds.width)
+                {
+                    showToolTip(item,col, hoverColumnGroupHeader, new Point(cellBounds.x + textBounds.x,cellBounds.y + 
+                                                    textBounds.y));
+                    //the following 2 lines are done here rather than in showToolTip to allow
+                    //that method to be overridden yet still capture the mouse.
+                    setCapture(true);
+                    inplaceTooltipCapture = true;
+                }
+            }
+            else
+            {                        
+                hideToolTip();
+            }
+        }
+        
+        //do normal cell specific tooltip stuff
+        if (hoverChange)
+        {            
+            String newTip = null;
+            if (hoveringItem == null || hoveringColumn == null)
+            {
+                //we're not over a cell so no cell tooltip - use base one
+                newTip = getToolTipText();
+            }
+            else
+            {
+                newTip = hoveringItem.getToolTipText(indexOf(hoveringColumn));
+                if (newTip == null)
+                {
+                    //no cell specific tooltip then use base Grid tooltip
+                    newTip = getToolTipText();                                    
+                }
+            }
+            //Avoid unnecessarily resetting tooltip - this will cause the tooltip to jump around
+            if (newTip != null && !newTip.equals(displayedToolTipText))
+            {
+                updateToolTipText(newTip);
+            }
+            else if(newTip == null && displayedToolTipText != null)
+            {
+                updateToolTipText(null);
+            }
+            displayedToolTipText = newTip;
+        }
+        
+        return hoverChange;
+    }
+
+    /**
+     * Sets the tooltip for the whole Grid to the given text.  This method is made available
+     * for subclasses to override, when a subclass wants to display a different than the standard 
+     * SWT/OS tooltip.  Generally, those subclasses would override this event and use this tooltip 
+     * text in their own tooltip or just override this method to prevent the SWT/OS tooltip from 
+     * displaying.
+     * 
+     * @param text
+     */
+    protected void updateToolTipText(String text)
+    {
+        super.setToolTipText(text);
+    }
+    
+    /**
+     * Marks the scroll values obsolete so they will be recalculated.
+     */
+    protected void setScrollValuesObsolete()
+    {
+        this.scrollValuesObsolete = true;
+        redraw();
+    }
+
+    /**
+     * Inserts a new column into the table.
+     * 
+     * @param column new column
+     * @param index index to insert new column
+     * @return current number of columns
+     */
+    int newColumn(GridColumn column, int index)
+    {
+
+        if (index == -1)
+        {
+            columns.add(column);
+            displayOrderedColumns.add(column);
+        }
+        else
+        {
+            columns.add(index, column);
+            displayOrderedColumns.add(index, column);
+        }
+
+        computeHeaderHeight(sizingGC);
+
+        updatePrimaryCheckColumn();
+        
+        for (Iterator iterator = items.iterator(); iterator.hasNext();)
+        {
+            GridItem item = (GridItem)iterator.next();
+            item.columnAdded(index);
+        }
+        
+        scrollValuesObsolete = true;
+        redraw();
+
+        return columns.size() - 1;
+    }
+
+    /**
+     * Removes the given column from the table.
+     * 
+     * @param column column to remove
+     */
+    void removeColumn(GridColumn column)
+    {
+        boolean selectionModified = false; 
+        
+        int index = indexOf(column);
+        
+        if (cellSelectionEnabled)
+        {
+            Vector removeSelectedCells = new Vector();
+            
+            for (Iterator iterator = selectedCells.iterator(); iterator.hasNext();)
+            {
+                Point cell = (Point)iterator.next();
+                if (cell.x == index)
+                {
+                    removeSelectedCells.add(cell);
+                }
+            }
+            
+            if (removeSelectedCells.size() > 0)
+            {
+                selectedCells.removeAll(removeSelectedCells);
+                selectionModified = true;
+            }
+            
+            for (Iterator iterator = selectedCells.iterator(); iterator.hasNext();)
+            {
+                Point cell = (Point)iterator.next();
+                if (cell.x >= index)
+                {
+                    cell.x--;
+                    selectionModified = true;
+                }
+            }
+        }
+            
+        columns.remove(column);
+        displayOrderedColumns.remove(column);
+        
+        updatePrimaryCheckColumn();
+        
+        scrollValuesObsolete = true;
+        redraw();
+        
+        for (Iterator iterator = items.iterator(); iterator.hasNext();)
+        {
+            GridItem item = (GridItem)iterator.next();
+            item.columnRemoved(index);
+        }
+        
+        int i = 0;
+        for (Iterator iterator = columns.iterator(); iterator.hasNext();)
+        {
+            GridColumn col = (GridColumn)iterator.next();
+            col.setColumnIndex(i);
+            i++;
+        }
+        
+        if (selectionModified && !disposing)
+        {
+            updateColumnSelection();
+        }
+    }
+    
+    /**
+     * Manages the setting of the checkbox column when the SWT.CHECK style was given to the 
+     * table.  This method will ensure that the first column of the table always has a checkbox
+     * when SWT.CHECK is given to the table.
+     */
+    private void updatePrimaryCheckColumn()
+    {
+        if ((getStyle() & SWT.CHECK) == SWT.CHECK)
+        {
+            boolean firstCol = true;
+            
+            for (Iterator iter = columns.iterator(); iter.hasNext();)
+            {
+                GridColumn col = (GridColumn)iter.next();
+                col.setTableCheck(firstCol);
+                firstCol = false;
+            }
+        }
+    }
+
+    void newRootItem(GridItem item, int index)
+    {
+        if (index == -1 || index >= rootItems.size())
+        {
+            rootItems.add(item);
+        }
+        else
+        {
+            rootItems.add(index,item);
+        }
+    }
+    
+    void removeRootItem(GridItem item)
+    {
+        rootItems.remove(item);
+    }
+    
+    /**
+     * Creates the new item at the given index. Only called from GridItem
+     * constructor.
+     * 
+     * @param item new item
+     * @param index index to insert the item at
+     * @return the index where the item was insert
+     */
+    int newItem(GridItem item, int index, boolean root)
+    {
+        int row = 0;
+        
+        if (!isTree)
+        {
+            if (item.getParentItem() != null)
+            {
+                isTree = true;
+            }
+        }
+
+        //Have to convert indexes, this method needs a flat index, the method is called with indexes
+        //that are relative to the level
+        if (root && index != -1)
+        {
+            if (index >= rootItems.size())
+            {
+                index = -1;
+            }
+            else
+            {
+                index = items.indexOf(rootItems.get(index));
+            }
+        }
+        else if (!root)
+        {
+            if (index >= item.getParentItem().getItems().length || index == -1)
+            {
+              GridItem rightMostDescendent = item.getParentItem();
+
+                while (rightMostDescendent.getItems().length > 0)
+                {
+                    rightMostDescendent = rightMostDescendent.getItems()[rightMostDescendent
+                        .getItems().length - 1];
+                }
+
+                index = indexOf(rightMostDescendent) + 1;               
+            }
+            else
+            {
+                index = indexOf(item.getParentItem().getItems()[index]);
+            }
+        }
+        
+        if (index == -1)
+        {
+            items.add(item);
+            row = items.size() - 1;
+        }
+        else
+        {
+            items.add(index, item);
+            row = index;
+        }
+
+        if (items.size() == 1 && !userModifiedItemHeight)
+            itemHeight = computeItemHeight(item,sizingGC);
+
+        item.initializeHeight(itemHeight);
+        
+        if (isRowHeaderVisible())
+        {
+            rowHeaderWidth = Math.max(rowHeaderWidth,rowHeaderRenderer
+                .computeSize(sizingGC, SWT.DEFAULT, SWT.DEFAULT, item).x);
+        }
+
+        scrollValuesObsolete = true;
+        topIndex = -1;
+        bottomIndex = -1;
+
+        currentVisibleItems++;
+
+        redraw();
+
+        return row;
+    }
+
+    /**
+     * Removes the given item from the table. This method is only called from
+     * the item's dispose method.
+     * 
+     * @param item item to remove
+     */
+    void removeItem(GridItem item)
+    {
+        Point[] cells = getCells(item);
+        boolean selectionModified = false;
+
+        items.remove(item);
+        
+        if (disposing)
+            return;
+        
+        if (selectedItems.remove(item))
+            selectionModified = true;
+
+        for (int i = 0; i < cells.length; i++)
+        {
+            if (selectedCells.remove(cells[i]))
+                selectionModified = true;
+        }
+
+        if (focusItem == item)
+        {
+            focusItem = null;
+        }
+
+        scrollValuesObsolete = true;
+        topIndex = -1;
+        bottomIndex = -1;
+        if (item.isVisible())
+        {
+            currentVisibleItems--;
+        }
+
+        if (selectionModified && !disposing)
+        {
+            updateColumnSelection();
+        }
+
+        redraw();
+    }
+
+    /**
+     * Creates the given column group at the given index. This method is only
+     * called from the {@code GridColumnGroup}'s constructor.
+     * 
+     * @param group group to add.
+     */
+    void newColumnGroup(GridColumnGroup group)
+    {
+        GridColumnGroup[] newColumnGroups = new GridColumnGroup[columnGroups.length + 1];
+        System.arraycopy(columnGroups, 0, newColumnGroups, 0, columnGroups.length);
+        newColumnGroups[newColumnGroups.length - 1] = group;
+        columnGroups = newColumnGroups;
+
+        // if we just added the first col group, then we need to up the row
+        // height
+        if (columnGroups.length == 1)
+        {
+            computeHeaderHeight(sizingGC);
+        }
+
+        scrollValuesObsolete = true;
+        redraw();
+    }
+
+    /**
+     * Removes the given column group from the table. This method is only called
+     * from the {@code GridColumnGroup}'s dispose method.
+     * 
+     * @param group group to remove.
+     */
+    void removeColumnGroup(GridColumnGroup group)
+    {
+        GridColumnGroup[] newColumnGroups = new GridColumnGroup[columnGroups.length - 1];
+        int newIndex = 0;
+        for (int i = 0; i < columnGroups.length; i++)
+        {
+            if (columnGroups[i] != group)
+            {
+                newColumnGroups[newIndex] = columnGroups[i];
+                newIndex++;
+            }
+        }
+        columnGroups = newColumnGroups;
+
+        if (columnGroups.length == 0)
+        {
+            computeHeaderHeight(sizingGC);
+        }
+
+        scrollValuesObsolete = true;
+        redraw();
+    }
+
+    /**
+     * Updates the cached number of visible items by the given amount.
+     * 
+     * @param amount amount to update cached total
+     */
+    void updateVisibleItems(int amount)
+    {
+        currentVisibleItems += amount;
+    }
+
+    /**
+     * Returns the current item in focus.
+     * 
+     * @return item in focus or {@code null}.
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public GridItem getFocusItem()
+    {
+        checkWidget();
+        return focusItem;
+    }
+    
+    /**
+     * Returns the current cell in focus.  If cell selection is disabled, this method returns null.
+     * 
+     * @return cell in focus or {@code null}. x represents the column and y the row the cell is in
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public Point getFocusCell()
+    {
+        checkWidget();
+        if (!cellSelectionEnabled) return null;
+        
+        int x = -1;
+        int y = -1;
+        
+        if (focusColumn != null)
+            x = indexOf(focusColumn);
+        
+        if (focusItem != null)
+            y = indexOf(focusItem);
+        
+        return new Point(x,y);
+    }
+
+    /**
+     * Sets the focused item to the given item.  
+     * 
+     * @param item item to focus.
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_ARGUMENT - if item is disposed</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setFocusItem(GridItem item)
+    {
+        checkWidget();
+        //TODO: check and make sure this item is valid for focus
+        if (item == null || item.isDisposed() || item.getParent() != this)
+        {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        focusItem = item;
+    }
+
+    /**
+     * Sets the focused item to the given column. Column focus is only applicable when cell 
+     * selection is enabled. 
+     * 
+     * @param column column to focus.
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_INVALID_ARGUMENT - if item is disposed</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setFocusColumn(GridColumn column)
+    {
+        checkWidget();
+        //TODO: check and make sure this item is valid for focus
+        if (column == null || column.isDisposed() || column.getParent() != this || !column.isVisible())
+        {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }       
+        
+        focusColumn = column;
+        intendedFocusColumn = column;
+    }
+    
+
+    /**
+     * Returns an array of the columns in their display order.
+     * 
+     * @return columns in display order
+     */
+    GridColumn[] getColumnsInOrder()
+    {
+        checkWidget();
+        return (GridColumn[])displayOrderedColumns.toArray(new GridColumn[columns.size()]);
+    }
+
+    /**
+     * Returns true if the table is set to horizontally scroll column-by-column
+     * rather than pixel-by-pixel.
+     * 
+     * @return true if the table is scrolled horizontally by column
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean getColumnScrolling()
+    {
+        checkWidget();
+        return columnScrolling;
+    }
+
+    /**
+     * Sets the table scrolling method to either scroll column-by-column (true)
+     * or pixel-by-pixel (false).
+     * 
+     * @param columnScrolling true to horizontally scroll by column, false to
+     * scroll by pixel
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setColumnScrolling(boolean columnScrolling)
+    {
+        checkWidget();
+        if (rowHeaderVisible && !columnScrolling)
+        {
+            return;
+        }
+        
+        this.columnScrolling = columnScrolling;
+        scrollValuesObsolete = true;
+        redraw();        
+    }
+    
+    /**
+     * Returns the first visible column that is not spanned by any other column that is either the 
+     * given column or any of the columns displaying to the left of the given column.  If the
+     * given column and subsequent columns to the right are either not visible or spanned, this 
+     * method will return null.
+     * 
+     * @param item
+     * @param col
+     * @return
+     */
+    private GridColumn getVisibleColumn_DegradeLeft(GridItem item, GridColumn col)
+    {
+        int index = displayOrderedColumns.indexOf(col);
+        
+        GridColumn prevCol = col;
+        
+        int i = 0;
+        while (!prevCol.isVisible())
+        {
+            i ++;
+            if (index - i < 0)
+                return null;
+            
+            prevCol = (GridColumn)displayOrderedColumns.get(index - i);
+        }
+        
+        index = displayOrderedColumns.indexOf(prevCol);
+        
+        for (int j = 0; j < index; j++)
+        {
+            GridColumn tempCol = (GridColumn)displayOrderedColumns.get(j);
+            
+            if (!tempCol.isVisible())
+            {
+                continue;
+            }
+            
+            if (item.getColumnSpan(indexOf(tempCol)) >= index - j)
+            {
+                prevCol = tempCol;
+                break;
+            }            
+        }
+        
+        return prevCol;
+    }
+    
+    /**
+     * Returns the first visible column that is not spanned by any other column that is either the 
+     * given column or any of the columns displaying to the right of the given column.  If the
+     * given column and subsequent columns to the right are either not visible or spanned, this 
+     * method will return null.
+     * 
+     * @param item
+     * @param col
+     * @return
+     */
+    private GridColumn getVisibleColumn_DegradeRight(GridItem item, GridColumn col)
+    {
+        int index = displayOrderedColumns.indexOf(col);
+        
+        int i = 0;
+        GridColumn nextCol = col;
+        while (!nextCol.isVisible())
+        {
+            i ++;
+            if (index + i == displayOrderedColumns.size())
+                return null;
+            
+            nextCol = (GridColumn)displayOrderedColumns.get(index + i);
+        }
+        
+        
+        index = displayOrderedColumns.indexOf(nextCol);
+        int startIndex = index;
+        
+        while (index > 0)
+        {
+
+            index --;
+            GridColumn prevCol = (GridColumn)displayOrderedColumns.get(index);
+            
+            if (item.getColumnSpan(indexOf(prevCol)) >= startIndex - index)
+            {
+                if (startIndex == displayOrderedColumns.size() - 1)
+                {
+                    return null;
+                }
+                else
+                {
+                    return getVisibleColumn_DegradeRight(item, (GridColumn)displayOrderedColumns.get(startIndex + 1));
+                }
+            }
+            
+        }
+        
+        return nextCol;
+    }
+
+    /**
+     * Returns true if the cells are selectable in the reciever.
+     * 
+     * @return cell selection enablement status. 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public boolean getCellSelectionEnabled()
+    {
+        checkWidget();
+        return cellSelectionEnabled;
+    }
+
+    /**
+     * Sets whether cells are selectable in the receiver.
+     * 
+     * @param cellSelection the cellSelection to set
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setCellSelectionEnabled(boolean cellSelection)
+    {
+        checkWidget();
+        if (!cellSelection)
+        {
+            selectedCells.clear();
+            redraw();
+        }
+        else
+        {
+            selectedItems.clear();
+            redraw();
+        }
+        
+        this.cellSelectionEnabled = cellSelection;        
+    }
+    
+    /**
+     * Deselects the given cell in the receiver.  If the given cell is already
+     * deselected it remains deselected.  Invalid cells are ignored.
+     * 
+     * @param cell cell to deselect. 
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the cell is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void deselectCell(Point cell)
+    {
+        checkWidget();
+        
+        if (cell == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        selectedCells.remove(cell);
+        updateColumnSelection();
+        redraw();
+    }
+    
+    /**
+     * Deselects the given cells.  Invalid cells are ignored.
+     * 
+     * @param cells the cells to deselect.
+     * 
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the set of cells or any cell is null</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void deselectCells(Point[] cells)
+    {
+        checkWidget();
+        
+        if (cells == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        for (int i = 0; i < cells.length; i++)
+        {
+            if (cells[i] == null)
+                SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        
+        for (int i = 0; i < cells.length; i++)
+        {
+            selectedCells.remove(cells[i]);
+        }
+        
+        updateColumnSelection();
+        
+        redraw();
+    }
+    
+    /**
+     * Deselects all selected cells in the receiver.
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void deselectAllCells()
+    {
+        checkWidget();
+        selectedCells.clear();
+        updateColumnSelection();
+        redraw();
+    }
+    
+    /**
+     * Selects the given cell.  Invalid cells are ignored.
+     * 
+     * @param cell point whose x values is a column index and y value is an item index
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the item is null</li> 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void selectCell(Point cell)
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled) return;
+        
+        if (cell == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        addToCellSelection(cell);
+        updateColumnSelection();
+        redraw();
+    }
+    
+    /**
+     * Selects the given cells.  Invalid cells are ignored.
+     * 
+     * @param cells an arry of points whose x value is a column index and y value is an item index
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the set of cells or an individual cell is null</li> 
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void selectCells(Point[] cells)
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled) return;
+        
+        if (cells == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        for (int i = 0; i < cells.length; i++)
+        {
+            if (cells[i] == null)
+                SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        
+        for (int i = 0; i < cells.length; i++)
+        {
+            addToCellSelection(cells[i]);
+        }
+        
+        updateColumnSelection();
+        redraw();
+    }
+    
+    /**
+     * Selects all cells in the receiver.
+     * 
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void selectAllCells()
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled) return;
+        
+        if (columns.size() == 0)
+            return;
+        
+        int index = 0;
+        GridColumn column = (GridColumn)displayOrderedColumns.get(index);
+        
+        while (!column.isVisible())
+        {
+            index ++;
+            
+            if (index >= columns.size())
+                return;
+            
+            column = (GridColumn)displayOrderedColumns.get(index);                 
+        }            
+        
+        GridColumn oldFocusColumn = focusColumn;
+        GridItem oldFocusItem = focusItem;
+        
+        focusColumn = column;        
+        focusItem = (GridItem)items.get(0);
+        
+        GridItem lastItem = getPreviousVisibleItem(null);
+        GridColumn lastCol = getVisibleColumn_DegradeLeft(lastItem,(GridColumn)displayOrderedColumns.get(displayOrderedColumns.size() -1));
+        
+        updateCellSelection(new Point(indexOf(lastCol),indexOf(lastItem)),SWT.SHIFT, true, false);
+        
+        focusColumn = oldFocusColumn;
+        focusItem = oldFocusItem;
+        
+        updateColumnSelection();
+        
+        redraw();
+    }
+    
+    /**
+     * Selects the selection to the given cell.  The existing selection is cleared before
+     * selecting the given cell.
+     * 
+     * @param cell point whose x values is a column index and y value is an item index
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the item is null</li> 
+     * <li>ERROR_INVALID_ARGUMENT - if the cell is invalid</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setCellSelection(Point cell)
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled) return;
+        
+        if (cell == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        if (!isValidCell(cell))
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        
+        selectedCells.clear();
+        addToCellSelection(cell);
+        updateColumnSelection();
+        redraw();
+    }
+    
+    /**
+     * Selects the selection to the given set of cell.  The existing selection is cleared before
+     * selecting the given cells.
+     * 
+     * @param cells point array whose x values is a column index and y value is an item index
+     * @throws IllegalArgumentException
+     * <ul>
+     * <li>ERROR_NULL_ARGUMENT - if the cell array or an individual cell is null</li> 
+     * <li>ERROR_INVALID_ARGUMENT - if the a cell is invalid</li>
+     * </ul>
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public void setCellSelection(Point[] cells)
+    {
+        checkWidget();
+        
+        if (!cellSelectionEnabled) return;
+        
+        if (cells == null)
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        
+        for (int i = 0; i < cells.length; i++)
+        {
+            if (cells[i] == null)
+                SWT.error(SWT.ERROR_NULL_ARGUMENT);
+            
+            if (!isValidCell(cells[i]))
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        
+        selectedCells.clear();
+        for (int i = 0; i < cells.length; i++)
+        {
+            addToCellSelection(cells[i]);
+        }
+        
+        updateColumnSelection();
+        redraw();
+    }
+    
+    /**
+     * Returns an array of cells that are currently selected in the
+     * receiver. The order of the items is unspecified. An empty array indicates
+     * that no items are selected.
+     * <p>
+     * Note: This is not the actual structure used by the receiver to maintain
+     * its selection, so modifying the array will not affect the receiver.
+     * </p>
+     * 
+     * @return an array representing the cell selection
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public Point[] getCellSelection()
+    {
+        checkWidget();        
+        return (Point[])selectedCells.toArray(new Point[selectedCells.size()]);
+    }
+    
+    
+    
+    
+    GridColumn getFocusColumn()
+    {
+        return focusColumn;
+    }
+    
+    void updateColumnFocus()
+    {
+        if (!focusColumn.isVisible())
+        {
+            int index = displayOrderedColumns.indexOf(focusColumn);
+            if (index > 0)
+            {
+                GridColumn prev = (GridColumn)displayOrderedColumns.get(index - 1);
+                prev = getVisibleColumn_DegradeLeft(focusItem,prev);
+                if (prev == null)
+                {
+                    prev = getVisibleColumn_DegradeRight(focusItem,focusColumn);
+                }
+                focusColumn = prev;
+            }
+            else
+            {
+                focusColumn = getVisibleColumn_DegradeRight(focusItem,focusColumn);
+            }
+        }
+    }
+    
+    private void getCells(GridColumn col, Vector cells)
+    {        
+        int colIndex = indexOf(col);
+        
+        int columnAtPosition = 0;
+        for (Iterator iter = displayOrderedColumns.iterator(); iter.hasNext();)
+        {
+            GridColumn nextCol = (GridColumn)iter.next();                    
+            if (!nextCol.isVisible()) continue;
+            
+            if (nextCol == col) break;
+            
+            columnAtPosition ++;
+        }           
+        
+        
+        GridItem item = null;
+        if (getItemCount() > 0)
+            item = getItem(0);    
+        
+        while (item != null)
+        {
+            //is cell spanned
+            int position = -1;
+            boolean spanned = false;
+            for (Iterator iter = displayOrderedColumns.iterator(); iter.hasNext();)
+            {
+                GridColumn nextCol = (GridColumn)iter.next();                    
+                if (!nextCol.isVisible()) continue;
+                
+                if (nextCol == col) break;                    
+                
+                int span = item.getColumnSpan(indexOf(nextCol));
+                
+                if (position + span >= columnAtPosition){
+                    spanned = true;
+                    break;
+                }
+            }
+            
+            if (!spanned && item.getColumnSpan(colIndex) == 0)
+            {
+                cells.add(new Point(colIndex,indexOf(item)));
+            }
+            
+            item = getNextVisibleItem(item);
+        }            
+    }
+    
+    private void getCells(GridItem item, Vector cells)
+    {
+        int itemIndex = indexOf(item);
+        
+        int span = 0;
+        
+        for (Iterator iter = displayOrderedColumns.iterator(); iter.hasNext();)
+        {
+            GridColumn nextCol = (GridColumn)iter.next();   
+            
+            if (span > 0)
+            {
+                span --;
+                continue;
+            }
+            
+            if (!nextCol.isVisible()) continue;                                       
+            
+            span = item.getColumnSpan(indexOf(nextCol));
+            
+            cells.add(new Point(indexOf(nextCol),itemIndex));
+        }
+    } 
+    
+    private Point[] getCells(GridItem item)
+    {
+        Vector cells = new Vector();
+        
+        int itemIndex = indexOf(item);
+        
+        int span = 0;
+        
+        for (Iterator iter = displayOrderedColumns.iterator(); iter.hasNext();)
+        {
+            GridColumn nextCol = (GridColumn)iter.next();   
+            
+            if (span > 0)
+            {
+                span --;
+                continue;
+            }
+            
+            if (!nextCol.isVisible()) continue;                                       
+            
+            span = item.getColumnSpan(indexOf(nextCol));
+            
+            cells.add(new Point(indexOf(nextCol),itemIndex));
+        } 
+        return (Point[])cells.toArray(new Point[]{});
+    }
+        
+
+    private void getCells(GridItem fromItem, GridItem toItem, Vector cells)
+    {
+        boolean descending = (indexOf(fromItem) < indexOf(toItem));
+        
+        GridItem iterItem = toItem;
+        
+        do
+        {
+            getCells(iterItem,cells);
+            
+            if (iterItem == fromItem) break;
+            
+            if (descending)
+            {
+                iterItem = getPreviousVisibleItem(iterItem);
+            }
+            else
+            {
+                iterItem = getNextVisibleItem(iterItem);
+            }
+        } while (true);
+    }
+    
+    private int blend(int v1, int v2, int ratio) {
+        return (ratio*v1 + (100-ratio)*v2)/100;
+    }
+    
+    private RGB blend(RGB c1, RGB c2, int ratio) {
+        int r = blend(c1.red, c2.red, ratio);
+        int g = blend(c1.green, c2.green, ratio);
+        int b = blend(c1.blue, c2.blue, ratio);
+        return new RGB(r, g, b);
+    }
+    
+    /**
+     * Returns a point whose x and y values are the to and from column indexes of the new selection
+     * range inclusive of all spanned columns.
+     * 
+     * @param fromItem
+     * @param fromColumn
+     * @param toItem
+     * @param toColumn
+     * @return
+     */
+    private Point getSelectionRange(GridItem fromItem, GridColumn fromColumn, GridItem toItem, GridColumn toColumn)
+    {
+        if (displayOrderedColumns.indexOf(fromColumn) > displayOrderedColumns.indexOf(toColumn))
+        {
+            GridColumn temp = fromColumn;
+            fromColumn = toColumn;
+            toColumn = temp;
+        }
+        
+        if (indexOf(fromItem) > indexOf(toItem))
+        {
+            GridItem temp = fromItem;
+            fromItem = toItem;
+            toItem = temp;
+        }
+        
+        boolean firstTime = true;
+        GridItem iterItem = fromItem;
+        
+        int fromIndex = indexOf(fromColumn);
+        int toIndex = indexOf(toColumn);
+        
+        do
+        {
+            if (!firstTime)
+            {
+                iterItem = getNextVisibleItem(iterItem);
+            }
+            else
+            {
+                firstTime = false;
+            }
+            
+            Point cols = getRowSelectionRange(iterItem, fromColumn, toColumn);
+            
+            //check and see if column spanning means that the range increased
+            if (cols.x != fromIndex || cols.y != toIndex)
+            {
+                GridColumn newFrom = getColumn(cols.x);
+                GridColumn newTo = getColumn(cols.y);
+                
+                //Unfortunately we have to start all over again from the top with the new range
+                return getSelectionRange(fromItem, newFrom, toItem, newTo);                
+            }
+        } while (iterItem != toItem);
+        
+        return new Point(indexOf(fromColumn),indexOf(toColumn));
+    }
+    
+    /**
+     * Returns a point whose x and y value are the to and from column indexes of the new selection 
+     * range inclusive of all spanned columns.
+     * 
+     * @param item
+     * @param fromColumn
+     * @param toColumn
+     * @return
+     */
+    private Point getRowSelectionRange(GridItem item, GridColumn fromColumn, GridColumn toColumn)
+    {                
+        int newFrom = indexOf(fromColumn);
+        int newTo = indexOf(toColumn);
+        
+        int span = 0;
+        int spanningColIndex = -1;
+        boolean spanningBeyondToCol = false;
+        
+        for (Iterator iter = displayOrderedColumns.iterator(); iter.hasNext();)
+        {
+            GridColumn col = (GridColumn)iter.next();
+                        
+            if (!col.isVisible())
+            {
+                if (span > 0) span --;
+                continue;
+            }
+                
+            if (span > 0)
+            {
+                if (col == fromColumn)
+                {
+                    newFrom = spanningColIndex;
+                }
+                else if (col == toColumn && span > 1)
+                {
+                    spanningBeyondToCol = true;
+                }
+                
+                span --;
+                
+                if (spanningBeyondToCol && span == 0)
+                {
+                    newTo = indexOf(col);
+                    break;
+                }
+            }
+            else
+            {
+                int index = indexOf(col);
+                span = item.getColumnSpan(index);
+                if (span > 0) spanningColIndex = index; 
+                
+                if (col == toColumn && span > 0)
+                    spanningBeyondToCol = true;
+            }
+           
+                
+            if (col == toColumn && !spanningBeyondToCol)
+                break;
+            
+        }
+
+        return new Point(newFrom,newTo);
+    }
+    
+    /**
+     * Returns the column which is spanning the given column for the given item or null if it is not
+     * being spanned.
+     * 
+     * @param item
+     * @param column
+     * @return
+     */
+    private GridColumn getSpanningColumn(GridItem item, GridColumn column)
+    {
+        int span = 0;
+        GridColumn spanningCol = null;
+        
+        for (Iterator iter = displayOrderedColumns.iterator(); iter.hasNext();)
+        {
+            GridColumn col = (GridColumn)iter.next();
+                       
+            if (col == column)
+            {
+                return spanningCol;
+            }
+            
+            if (span > 0)
+            {
+                span --;
+                if (span == 0) spanningCol = null;
+            }
+            else
+            {
+                int index = indexOf(col);
+                span = item.getColumnSpan(index);
+                
+                if (span > 0) spanningCol = col;
+            }
+        }
+        return spanningCol;
+    }
+    
+    /**
+     * Returns true if the given cell's x and y values are valid column and
+     * item indexes respectively.
+     * 
+     * @param cell
+     * @return
+     */
+    private boolean isValidCell(Point cell)
+    {
+        if (cell.x < 0 || cell.x >= columns.size())
+            return false;
+        
+        if (cell.y < 0 || cell.y >= items.size())
+            return false;
+        
+        return true;
+    }
+
+    /**
+     * Shows the inplace tooltip for the given item and column.  The location is the x and y origin 
+     * of the text in the cell.
+     * <p>
+     * This method may be overriden to provide their own custom tooltips.
+     * 
+     * @param item the item currently hovered over or null. 
+     * @param column the column currently hovered over or null.
+     * @param group the group currently hovered over or null.
+     * @param location the x,y origin of the text in the hovered object.
+     */
+    protected void showToolTip(GridItem item, GridColumn column, GridColumnGroup group, Point location)
+    {
+        if (inplaceToolTip == null)
+        {
+            inplaceToolTip = new GridToolTip(this);
+        }
+        
+        if (group != null)
+        {
+            inplaceToolTip.setFont(getFont());
+            inplaceToolTip.setText(group.getText());
+        }
+        else if (item != null)
+        {
+            inplaceToolTip.setFont(item.getFont(item.getParent().indexOf(column)));
+            inplaceToolTip.setText(item.getText(item.getParent().indexOf(column)));  
+        }
+        else if (column != null)
+        {
+            inplaceToolTip.setFont(getFont());
+            inplaceToolTip.setText(column.getText());           
+        }
+        
+
+        
+        Point p = getDisplay().map(this, null, location);
+        
+        inplaceToolTip.setLocation(p);
+        
+        inplaceToolTip.setVisible(true);
+    }
+    
+    /**
+     * Hides the inplace tooltip.
+     * <p>
+     * This method must be overriden when showToolTip is overriden.  Subclasses must 
+     * call super when overriding this method.
+     */
+    protected void hideToolTip()
+    {
+        if (inplaceToolTip != null)
+        {
+            inplaceToolTip.setVisible(false);
+        }
+        if (inplaceTooltipCapture) 
+        {
+            setCapture(false);
+            inplaceTooltipCapture = false;
+        }
+    }
+    
+    void recalculateRowHeaderWidth(GridItem item,int oldWidth, int newWidth)
+    {
+        if (newWidth > rowHeaderWidth)
+        {
+            rowHeaderWidth = newWidth;
+        }
+        else if (newWidth < rowHeaderWidth && oldWidth == rowHeaderWidth)
+        {
+            //if the changed width is smaller, and the previous width of that rows header was equal 
+            //to the current row header width then its possible that we may need to make the new 
+            //row header width smaller, but to do that we need to ask all the rows all over again           
+            for (Iterator iter = items.iterator(); iter.hasNext();)
+            {
+                GridItem iterItem = (GridItem)iter.next();
+                newWidth = Math.max(newWidth,rowHeaderRenderer.computeSize(sizingGC, SWT.DEFAULT,SWT.DEFAULT,iterItem).x);
+            }
+            
+            rowHeaderWidth = newWidth;
+        }
+        redraw();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void setFont(Font font)
+    {
+        super.setFont(font);
+        sizingGC.setFont(font);
+    }
+
+    /**
+     * Returns the row header width or 0 if row headers are not visible.
+     * 
+     * @return the width of the row headers
+     * @throws org.eclipse.swt.SWTException
+     * <ul>
+     * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+     * created the receiver</li>
+     * </ul>
+     */
+    public int getItemHeaderWidth()
+    {
+        checkWidget();
+        if (!rowHeaderVisible)
+            return 0;
+        return rowHeaderWidth;
+    }
+    
+    /**
+     * Sets the number of items contained in the receiver.
+     *
+     * @param count the number of items
+     *
+     * @exception org.eclipse.swt.SWTException
+     * <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     */
+    public void setItemCount(int count)
+    {
+        checkWidget();
+        setRedraw(false);
+        if (count < 0)
+            count = 0;
+        
+               
+        if (count < items.size())
+        {
+          //TODO delete and clear items if necessary 
+        }
+
+        while (count > items.size())
+        {
+            new GridItem(this,SWT.NONE);
+        }
+        setRedraw(true);
+    }
+    
+    /**
+     * Initialize accessibility.
+     */
+    private void initAccessible()
+    {
+        final Accessible accessible = getAccessible();
+        accessible.addAccessibleListener(new AccessibleAdapter()
+        {
+            public void getDescription(AccessibleEvent e)
+            {
+                int childID = e.childID;
+                if (childID >= 0 && childID < items.size())
+                {
+                    String descrption = "";
+                    for (int i = 0; i < columns.size(); i++)
+                    {
+                        if (i != 0)
+                        {
+                            descrption += ((GridColumn)columns.get(i)).getText() + " : ";
+                            descrption += ((GridItem)items.get(childID)).getText(i) + " ";
+                        }
+                    }
+                    e.result = descrption;
+                }
+            }
+
+            public void getName(AccessibleEvent e)
+            {
+                int childID = e.childID;
+                if (childID >= 0 && childID < items.size())
+                {
+                    // Name of the items
+                    e.result = ((GridItem)items.get(childID)).getText();
+                }
+                else if (childID >= items.size() && childID < items.size() + columns.size())
+                {
+                    // Name of the column headers
+                    e.result = ((GridColumn)columns.get(childID - items.size())).getText();
+                }
+                else if (childID >= items.size() + columns.size()
+                         && childID < items.size() + columns.size() + columnGroups.length)
+                {
+                    // Name of the column group headers
+                    e.result = ((GridColumnGroup)columnGroups[childID - items.size()
+                                                              - columns.size()]).getText();
+                }
+                else if (childID >= items.size() + columns.size() + columnGroups.length
+                         && childID < items.size() + columns.size() + columnGroups.length
+                                      + columnGroups.length)
+                {
+                    // Name of the toggle button for column group headers
+                    e.result = ACC_TOGGLE_BUTTON_NAME;
+                }
+            }
+        });
+
+        accessible.addAccessibleControlListener(new AccessibleControlAdapter()
+        {
+            public void getChildAtPoint(AccessibleControlEvent e)
+            {
+                Point location = toControl(e.x, e.y);
+                e.childID = ACC.CHILDID_SELF;
+
+                // Grid Items
+                GridItem item = getItem(location);
+                if (item != null)
+                {
+                    for (int i = 0; i < getItems().length; i++)
+                    {
+                        if (item.equals(getItem(i)))
+                        {
+                            e.childID = i;
+                            return;
+                        }
+                    }
+                }
+                else
+                {
+                    // Column Headers
+                    GridColumn column = overColumnHeader(location.x, location.y);
+                    if (column != null)
+                    {
+                        for (int i = 0; i < getColumns().length; i++)
+                        {
+                            if (column.equals(getColumn(i)))
+                            {
+                                e.childID = getItems().length + i;
+                                return;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        // Column Group headers
+                        GridColumnGroup columnGroup = overColumnGroupHeader(location.x, location.y);
+                        if (columnGroup != null)
+                        {
+                            for (int i = 0; i < getColumnGroups().length; i++)
+                            {
+                                if (columnGroup.equals(getColumnGroup(i)))
+                                {
+                                    Rectangle toggle = ((DefaultColumnGroupHeaderRenderer)columnGroup
+                                        .getHeaderRenderer()).getToggleBounds();
+                                    if (toggle.contains(location.x, location.y))
+                                    {
+                                        // Toggle button for column group
+                                        // header
+                                        e.childID = getItems().length + getColumns().length
+                                                    + getColumnGroups().length + i;
+                                    }
+                                    else
+                                    {
+                                        // Column Group header
+                                        e.childID = getItems().length + getColumns().length + i;
+                                    }
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            public void getChildCount(AccessibleControlEvent e)
+            {
+                if (e.childID == ACC.CHILDID_SELF)
+                {
+                    int length = items.size();
+
+                    if (isTree)
+                    {
+                        // Child count for parent. Here if the item parent
+                        // is not an other item,
+                        // it is consider as children of Grid
+                        for (int i = 0; i < items.size(); i++)
+                        {
+                            if (((GridItem)items.get(i)).getParentItem() != null)
+                            {
+                                length--;
+                            }
+                        }
+                    }
+                    e.detail = length;
+                }
+            }
+
+            public void getChildren(AccessibleControlEvent e)
+            {
+                if (e.childID == ACC.CHILDID_SELF)
+                {
+                    int length = items.size();
+                    if (isTree)
+                    {
+                        for (int i = 0; i < items.size(); i++)
+                        {
+                            if (((GridItem)items.get(i)).getParentItem() != null)
+                            {
+                                length--;
+                            }
+                        }
+
+                        Object[] children = new Object[length];
+                        int j = 0;
+
+                        for (int i = 0; i < items.size(); i++)
+                        {
+                            if (((GridItem)items.get(i)).getParentItem() == null)
+                            {
+                                children[j] = new Integer(i);
+                                j++;
+                            }
+                        }
+                        e.children = children;
+                    }
+                    else
+                    {
+                        Object[] children = new Object[length];
+                        for (int i = 0; i < items.size(); i++)
+                        {
+                            children[i] = new Integer(i);
+                        }
+                        e.children = children;
+                    }
+                }
+            }
+
+            public void getDefaultAction(AccessibleControlEvent e)
+            {
+                int childID = e.childID;
+                if (childID >= 0 && childID < items.size())
+                {
+                    if (getItem(childID).hasChildren())
+                    {
+                        // Action of tree items
+                        if (getItem(childID).isExpanded())
+                        {
+                            e.result = ACC_ITEM_ACTION_COLLAPSE;
+                        }
+                        else
+                        {
+                            e.result = ACC_ITEM_ACTION_EXPAND;
+                        }
+                    }
+                    else
+                    {
+                        // action of default items
+                        e.result = ACC_ITEM_DEFAULT_ACTION;
+                    }
+                }
+                else if (childID >= items.size()
+                         && childID < items.size() + columns.size() + columnGroups.length)
+                {
+                    // action of column and column group header
+                    e.result = ACC_COLUMN_DEFAULT_ACTION;
+                }
+                else if (childID >= items.size() + columns.size() + columnGroups.length
+                         && childID < items.size() + columns.size() + columnGroups.length
+                                      + columnGroups.length)
+                {
+                    // action of toggle button of column group header
+                    e.result = SWT.getMessage("SWT_Press");
+                }
+            }
+
+            public void getLocation(AccessibleControlEvent e)
+            {
+                // location of parent
+                Rectangle location = getBounds();
+                location.x = 0;
+                location.y = 0;
+                int childID = e.childID;
+
+                if (childID >= 0 && childID < items.size())
+                {
+                    // location of items
+                    GridItem item = getItem(childID);
+                    if (item != null)
+                    {
+                        Point p = getOrigin((GridColumn)columns.get(0), item);
+                        location.y = p.y;
+                        location.height = item.getHeight();
+                    }
+                }
+                else if (childID >= items.size() && childID < items.size() + columns.size())
+                {
+                    // location of columns headers
+                    GridColumn column = getColumn(childID - items.size());
+                    if (column != null)
+                    {
+                        location.x = getColumnHeaderXPosition(column);
+                        if (column.getColumnGroup() == null)
+                        {
+                            location.y = 0;
+                        }
+                        else
+                        {
+                            location.y = groupHeaderHeight;
+                        }
+                        location.height = headerHeight;
+                        location.width = column.getWidth();
+                    }
+                }
+                else if (childID >= items.size() + columns.size()
+                         && childID < items.size() + columns.size() + columnGroups.length)
+                {
+                    // location of column group header
+                    GridColumnGroup columnGroup = getColumnGroup(childID - items.size()
+                                                                 - columns.size());
+                    if (columnGroup != null)
+                    {
+                        location.y = 0;
+                        location.height = groupHeaderHeight;
+                        location.x = getColumnHeaderXPosition(columnGroup.getFirstVisibleColumn());
+                        int width = 0;
+                        for (int i = 0; i < columnGroup.getColumns().length; i++)
+                        {
+                            if (columnGroup.getColumns()[i].isVisible())
+                            {
+                                width += columnGroup.getColumns()[i].getWidth();
+                            }
+                        }
+                        location.width = width;
+                    }
+                }
+                else if (childID >= items.size() + columns.size() + columnGroups.length
+                         && childID < items.size() + columns.size() + columnGroups.length
+                                      + columnGroups.length)
+                {
+                    // location of toggle button of column group header
+                    GridColumnGroup columnGroup = getColumnGroup(childID - items.size()
+                                                                 - columns.size()
+                                                                 - columnGroups.length);
+                    location = ((DefaultColumnGroupHeaderRenderer)columnGroup.getHeaderRenderer())
+                        .getToggleBounds();
+                }
+
+                if (location != null)
+                {
+                    Point pt = toDisplay(location.x, location.y);
+                    e.x = pt.x;
+                    e.y = pt.y;
+                    e.width = location.width;
+                    e.height = location.height;
+                }
+            }
+
+            public void getRole(AccessibleControlEvent e)
+            {
+                int childID = e.childID;
+                if (childID >= 0 && childID < items.size())
+                {
+                    // role of items
+                    if (isTree)
+                    {
+                        e.detail = ACC.ROLE_TREEITEM;
+                    }
+                    else
+                    {
+                        e.detail = ACC.ROLE_LISTITEM;
+                    }
+                }
+                else if (childID >= items.size()
+                         && childID < items.size() + columns.size() + columnGroups.length)
+                {
+                    // role of columns headers and column group headers
+                    e.detail = ACC.ROLE_TABLECOLUMNHEADER;
+                }
+                else if (childID >= items.size() + columns.size() + columnGroups.length
+                         && childID < items.size() + columns.size() + columnGroups.length
+                                      + columnGroups.length)
+                {
+                    // role of toggle button of column group headers
+                    e.detail = ACC.ROLE_PUSHBUTTON;
+                }
+                else if (childID == ACC.CHILDID_SELF)
+                {
+                    // role of parent
+                    if (isTree)
+                    {
+                        e.detail = ACC.ROLE_TREE;
+                    }
+                    else
+                    {
+                        e.detail = ACC.ROLE_TABLE;
+                    }
+                }
+            }
+
+            public void getSelection(AccessibleControlEvent e)
+            {
+                e.childID = ACC.CHILDID_NONE;
+                if (selectedItems.size() == 1)
+                {
+                    // Single selection
+                    e.childID = indexOf(((GridItem)selectedItems.get(0)));
+                }
+                else if (selectedItems.size() > 1)
+                {
+                    // multiple selection
+                    e.childID = ACC.CHILDID_MULTIPLE;
+                    int length = selectedItems.size();
+                    Object[] children = new Object[length];
+
+                    for (int i = 0; i < length; i++)
+                    {
+                        GridItem item = (GridItem)selectedItems.get(i);
+                        children[i] = new Integer(indexOf(item));
+                    }
+                    e.children = children;
+                }
+            }
+
+            public void getState(AccessibleControlEvent e)
+            {
+                int childID = e.childID;
+                if (childID >= 0 && childID < items.size())
+                {
+                    // state of items
+                    e.detail = ACC.STATE_SELECTABLE;
+                    if (getDisplay().getActiveShell() == getParent().getShell())
+                    {
+                        e.detail |= ACC.STATE_FOCUSABLE;
+                    }
+
+                    if (selectedItems.contains(getItem(childID)))
+                    {
+                        e.detail |= ACC.STATE_SELECTED;
+                        if (getDisplay().getActiveShell() == getParent().getShell())
+                        {
+                            e.detail |= ACC.STATE_FOCUSED;
+                        }
+                    }
+
+                    if (getItem(childID).getChecked())
+                    {
+                        e.detail |= ACC.STATE_CHECKED;
+                    }
+
+                    // only for tree type items
+                    if (getItem(childID).hasChildren())
+                    {
+                        if (getItem(childID).isExpanded())
+                        {
+                            e.detail |= ACC.STATE_EXPANDED;
+                        }
+                        else
+                        {
+                            e.detail |= ACC.STATE_COLLAPSED;
+                        }
+                    }
+
+                    if (!getItem(childID).isVisible())
+                    {
+                        e.detail |= ACC.STATE_INVISIBLE;
+                    }
+                }
+                else if (childID >= items.size()
+                         && childID < items.size() + columns.size() + columnGroups.length)
+                {
+                    // state of column headers and column group headers
+                    e.detail = ACC.STATE_READONLY;
+                }
+                else if (childID >= items.size() + columns.size() + columnGroups.length
+                         && childID < items.size() + columns.size() + columnGroups.length
+                                      + columnGroups.length)
+                {
+                    // state of toggle button of column group headers
+                    if (getColumnGroup(
+                                       childID - items.size() - columns.size()
+                                           - columnGroups.length).getExpanded())
+                    {
+                        e.detail = ACC.STATE_EXPANDED;
+                    }
+                    else
+                    {
+                        e.detail = ACC.STATE_COLLAPSED;
+                    }
+                }
+            }
+
+            public void getValue(AccessibleControlEvent e)
+            {
+                int childID = e.childID;
+                if (childID >= 0 && childID < items.size())
+                {
+                    // value for tree items
+                    if (isTree)
+                    {
+                        e.result = "" + getItem(childID).getLevel();
+                    }
+                }
+            }
+        });
+
+        addListener(SWT.Selection, new Listener()
+        {
+            public void handleEvent(Event event)
+            {
+                if (selectedItems.size() > 0)
+                {
+                    accessible.setFocus(items.indexOf(selectedItems.get(selectedItems.size() - 1)));
+                }
+            }
+        });
+
+        addTreeListener(new TreeListener()
+        {
+            public void treeCollapsed(TreeEvent e)
+            {
+                if (getFocusItem() != null)
+                {
+                    accessible.setFocus(items.indexOf(getFocusItem()));
+                }
+            }
+
+            public void treeExpanded(TreeEvent e)
+            {
+                if (getFocusItem() != null)
+                {
+                    accessible.setFocus(items.indexOf(getFocusItem()));
+                }
+            }
+        });
+    }
+
+    /**
+     * @return the disposing
+     */
+    boolean isDisposing()
+    {
+        return disposing;
+    }
+
+    /**
+     * @param hasSpanning the hasSpanning to set
+     */
+    void setHasSpanning(boolean hasSpanning)
+    {
+        this.hasSpanning = hasSpanning;
+    }
+
+    /**
+     * Returns the receiver's tool tip text, or null if it has
+     * not been set.
+     *
+     * @return the receiver's tool tip text
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     */
+    public String getToolTipText() {
+        checkWidget();
+        return toolTipText;
+    }
+
+
+    /**
+     * Sets the receiver's tool tip text to the argument, which
+     * may be null indicating that no tool tip text should be shown.
+     *
+     * @param string the new tool tip text (or null)
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     */
+    public void setToolTipText(String string) {
+        checkWidget();
+        toolTipText = string;
+    }
+    
+    /**
+     * Updates the row height when the first image is set on an item.
+     * 
+     * @param item item which images has just been set on.
+     */
+    void imageSetOnItem(GridItem item)
+    {
+        if (firstImageSet || userModifiedItemHeight) return;
+        
+        int height = computeItemHeight(item,sizingGC);
+        setItemHeight(height);
+        
+        firstImageSet = true;
+    }
+
+    /**
+     * Determines if the mouse is hovering on the selection drag area and changes the
+     * pointer and sets field appropriately.
+     * <p>
+     * Note:  The 'selection drag area' is that part of the selection,
+     * on which a drag event can be initiated.  This is either the border
+     * of the selection (i.e. a cell border between a slected and a non-selected
+     * cell) or the complete selection (i.e. anywhere on a selected cell).
+     * What area serves as drag area is determined by {@link #setDragOnFullSelection(boolean)}.
+     * 
+     * @param x
+     * @param y
+     * @return
+     * @see #setDragOnFullSelection(boolean)
+     */
+    private boolean handleHoverOnSelectionDragArea(int x, int y)
+    {
+        boolean over = false;
+//        Point inSelection = null;
+
+        if ( (!rowHeaderVisible || x > rowHeaderWidth-SELECTION_DRAG_BORDER_THRESHOLD)
+                && (!columnHeadersVisible || y > headerHeight-SELECTION_DRAG_BORDER_THRESHOLD) )
+        {
+            // not on a header
+
+//            if(!dragOnFullSelection)
+//            {
+//                // drag area is the border of the selection
+//
+//                if(cellSelectionEnabled)
+//                {
+//                    Point neP = new Point( x-SELECTION_DRAG_BORDER_THRESHOLD, y-SELECTION_DRAG_BORDER_THRESHOLD );
+//                    Point ne = getCell(neP);
+//                    Point nwP = new Point( x+SELECTION_DRAG_BORDER_THRESHOLD, y-SELECTION_DRAG_BORDER_THRESHOLD );
+//                    Point nw = getCell(nwP);
+//                    Point swP = new Point( x+SELECTION_DRAG_BORDER_THRESHOLD, y+SELECTION_DRAG_BORDER_THRESHOLD );
+//                    Point sw = getCell(swP);
+//                    Point seP = new Point( x-SELECTION_DRAG_BORDER_THRESHOLD, y+SELECTION_DRAG_BORDER_THRESHOLD );
+//                    Point se = getCell(seP);
+//
+//                    boolean neSel = ne != null && isCellSelected(ne);
+//                    boolean nwSel = nw != null && isCellSelected(nw);
+//                    boolean swSel = sw != null && isCellSelected(sw);
+//                    boolean seSel = se != null && isCellSelected(se);
+//
+//                    over = (neSel || nwSel || swSel || seSel) && (!neSel || !nwSel || !swSel || !seSel);
+////                    inSelection = neSel ? neP : nwSel ? nwP : swSel ? swP : seSel ? seP : null;
+//                }
+//                else
+//                {
+//                    Point nP = new Point( x, y-SELECTION_DRAG_BORDER_THRESHOLD );
+//                    GridItem n = getItem(nP);
+//                    Point sP = new Point( x, y+SELECTION_DRAG_BORDER_THRESHOLD );
+//                    GridItem s = getItem(sP);
+//
+//                    boolean nSel = n != null && isSelected(n);
+//                    boolean sSel = s != null && isSelected(s);
+//
+//                    over = nSel != sSel;
+////                    inSelection = nSel ? nP : sSel ? sP : null;
+//                }
+//            }
+//            else
+//            {
+                // drag area is the entire selection
+
+                if(cellSelectionEnabled)
+                {
+                    Point p = new Point(x,y);
+                    Point cell = getCell(p);
+                    over = cell !=null && isCellSelected(cell);
+//                    inSelection = over ? p : null;
+                }
+                else
+                {
+                    Point p = new Point(x,y);
+                    GridItem item = getItem(p);
+                    over = item != null && isSelected(item);
+//                    inSelection = over ? p : null;
+                }
+            }
+//        }
+
+        if (over != hoveringOnSelectionDragArea)
+        {
+//            if (over)
+//            {
+//                // use drag cursor only in border mode
+//                if (!dragOnFullSelection)
+//                    setCursor(getDisplay().getSystemCursor(SWT.CURSOR_SIZEALL));
+////                potentialDragStart = inSelection;
+//            }
+//            else
+//            {
+//                setCursor(null);
+////                potentialDragStart = null;
+//            }
+            hoveringOnSelectionDragArea = over;
+        }
+        return over;
+    }
+
+    /**
+     * Display a mark indicating the point at which an item will be inserted.
+     * This is used as a visual hint to show where a dragged item will be
+     * inserted when dropped on the grid.  This method should not be called
+     * directly, instead {@link DND#FEEDBACK_INSERT_BEFORE} or
+     * {@link DND#FEEDBACK_INSERT_AFTER} should be set in
+     * {@link DropTargetEvent#feedback} from within a {@link DropTargetListener}.
+     * 
+     * @param item  the insert item.  Null will clear the insertion mark.
+     * @param column  the column of the cell.  Null will make the insertion mark span all columns.
+     * @param before  true places the insert mark above 'item'. false places 
+     *                the insert mark below 'item'.
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_INVALID_ARGUMENT - if the item or column has been disposed</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     */
+    void setInsertMark (GridItem item, GridColumn column, boolean before) {
+        checkWidget ();
+        if (item != null) {
+            if (item.isDisposed())
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        if (column != null) {
+            if (column.isDisposed())
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        insertMarkItem = item;
+        insertMarkColumn = column;
+        insertMarkBefore = before;
+        redraw();
+    }
+
+    /**
+     * A helper method for {@link GridDropTargetEffect#dragOver(DropTargetEvent)}.
+     * 
+     * @param point
+     * @return true if point is near the top or bottom border of the visible grid area
+     */
+    boolean isInDragScrollArea(Point point) {
+        int rhw = rowHeaderVisible ? rowHeaderWidth : 0;
+        int chh = columnHeadersVisible ? headerHeight : 0;
+        Rectangle top = new Rectangle(rhw, chh, getClientArea().width - rhw, DRAG_SCROLL_AREA_HEIGHT);
+        Rectangle bottom = new Rectangle(rhw, getClientArea().height - DRAG_SCROLL_AREA_HEIGHT, getClientArea().width - rhw, DRAG_SCROLL_AREA_HEIGHT);
+        return top.contains(point) || bottom.contains(point);
+    }
+    
+    /**
+     * Clears the item at the given zero-relative index in the receiver.
+     * The text, icon and other attributes of the item are set to the default
+     * value.  If the table was created with the <code>SWT.VIRTUAL</code> style,
+     * these attributes are requested again as needed.
+     *
+     * @param index the index of the item to clear
+     * @param allChildren <code>true</code> if all child items of the indexed item should be
+     * cleared recursively, and <code>false</code> otherwise
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     * 
+     * @see SWT#VIRTUAL
+     * @see SWT#SetData
+     */
+    public void clear(int index, boolean allChildren) {
+        checkWidget();
+        if (index < 0 || index >= items.size()) {
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        }
+        
+        GridItem item = getItem(index);
+        item.clear(allChildren);
+        redraw();
+    }
+    
+    /**
+     * Clears the items in the receiver which are between the given
+     * zero-relative start and end indices (inclusive).  The text, icon
+     * and other attributes of the items are set to their default values.
+     * If the table was created with the <code>SWT.VIRTUAL</code> style,
+     * these attributes are requested again as needed.
+     *
+     * @param start the start index of the item to clear
+     * @param end the end index of the item to clear
+     * @param allChildren <code>true</code> if all child items of the range of items should be
+     * cleared recursively, and <code>false</code> otherwise
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     * 
+     * @see SWT#VIRTUAL
+     * @see SWT#SetData
+     */
+    public void clear(int start, int end, boolean allChildren) {
+        checkWidget();
+        if (start > end) return;
+        
+        int count = items.size();
+        if (!(0 <= start && start <= end && end < count)) {
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        }
+        for (int i=start; i<=end; i++) {
+            GridItem item = (GridItem)items.get(i);
+            item.clear(allChildren);
+        }
+        redraw();
+    }
+    
+    /**
+     * Clears the items at the given zero-relative indices in the receiver.
+     * The text, icon and other attributes of the items are set to their default
+     * values.  If the table was created with the <code>SWT.VIRTUAL</code> style,
+     * these attributes are requested again as needed.
+     *
+     * @param indices the array of indices of the items
+     * @param allChildren <code>true</code> if all child items of the indexed items should be
+     * cleared recursively, and <code>false</code> otherwise
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+     *    <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     * 
+     * @see SWT#VIRTUAL
+     * @see SWT#SetData
+     */
+    public void clear(int [] indices, boolean allChildren) {
+        checkWidget();
+        if (indices == null) {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        if (indices.length == 0) return;
+        
+        int count = items.size();
+        for (int i=0; i<indices.length; i++) {
+            if (!(0 <= indices[i] && indices[i] < count)) {
+                SWT.error(SWT.ERROR_INVALID_RANGE);
+            }
+        }
+        for (int i=0; i<indices.length; i++) {
+            GridItem item = (GridItem)items.get(indices[i]);
+            item.clear(allChildren);
+        }
+        redraw();
+    }
+    
+    /**
+     * Clears all the items in the receiver. The text, icon and other
+     * attributes of the items are set to their default values. If the
+     * table was created with the <code>SWT.VIRTUAL</code> style, these
+     * attributes are requested again as needed.
+     * 
+     * @param allChildren <code>true</code> if all child items of each item should be
+     * cleared recursively, and <code>false</code> otherwise
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+     * </ul>
+     * 
+     * @see SWT#VIRTUAL
+     * @see SWT#SetData
+     */
+    public void clearAll(boolean allChildren) {
+        checkWidget();
+        if (items.size() > 0)
+            clear(0, items.size()-1, allChildren);
+    }
+}
+
+
+
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/StateSample.state b/demos/org.eclipse.fx.xtext.sample.editor/src/StateSample.state
new file mode 100644
index 0000000..051a75c
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/StateSample.state
@@ -0,0 +1,13 @@
+/* This is an xtext sample */
+
+input signal TEST_IN
+output signal TEST_OUT
+
+
+state START
+	set TEST_IN = true
+end 
+
+state END
+	if TEST_IN == true goto END
+end
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/Util.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/Util.java
new file mode 100644
index 0000000..85a3f86
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/Util.java
@@ -0,0 +1,25 @@
+package org.eclipse.fx.xtext.sample.editor;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+public class Util {
+	public static String getFileContent(URI uri) {
+		StringBuilder b = new StringBuilder();
+		try {
+			BufferedReader reader = Files.newBufferedReader(Paths.get(uri));
+			String l;
+			while( (l = reader.readLine()) != null ) {
+				b.append(l + "\n");
+			}
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		
+		return b.toString();
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/SampleJavaCode.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/SampleJavaCode.java
new file mode 100644
index 0000000..7e28c20
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/SampleJavaCode.java
@@ -0,0 +1,88 @@
+package org.eclipse.fx.xtext.sample.editor.java;
+
+import org.eclipse.fx.xtext.sample.editor.Util;
+import org.eclipse.fx.xtext.sample.editor.java.text.FastJavaPartitionScanner;
+import org.eclipse.fx.xtext.sample.editor.java.text.IJavaPartitions;
+import org.eclipse.fx.xtext.sample.editor.java.text.JavaSourceConfiguration;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.jface.text.source.SourceViewer;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.HBox;
+import javafx.stage.Stage;
+
+public class SampleJavaCode extends Application {
+	private final static String[] LEGAL_CONTENT_TYPES = new String[] { IJavaPartitions.JAVA_DOC,
+			IJavaPartitions.JAVA_MULTI_LINE_COMMENT, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT,
+			IJavaPartitions.JAVA_STRING, IJavaPartitions.JAVA_CHARACTER };
+
+	private int count = 0;
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane container = new BorderPane();
+
+		HBox b = new HBox(10);
+
+		Document document = new Document();
+
+		{
+			Button load = new Button("Load");
+			load.setOnAction(e -> {
+				try {
+					if (count++ % 2 == 1) {
+						document.set(
+								Util.getFileContent(getClass().getClassLoader().getResource("Sample_big.txt").toURI()));
+					} else {
+						document.set(
+								Util.getFileContent(getClass().getClassLoader().getResource("Sample.txt").toURI()));
+					}
+				} catch (Exception e1) {
+					// TODO Auto-generated catch block
+					e1.printStackTrace();
+				}
+			} );
+			b.getChildren().add(load);
+		}
+
+		{
+			Button bright = new Button("Bright");
+			b.getChildren().add(bright);
+			bright.setOnAction(e -> bright.getScene().getStylesheets()
+					.setAll(getClass().getResource("bright.css").toExternalForm()));
+		}
+
+		{
+			Button dark = new Button("Dark");
+			b.getChildren().add(dark);
+			dark.setOnAction(
+					e -> dark.getScene().getStylesheets().setAll(getClass().getResource("dark.css").toExternalForm()));
+		}
+
+		container.setTop(b);
+
+		JavaSourceConfiguration configuration = new JavaSourceConfiguration();
+
+		SourceViewer viewer = new SourceViewer();
+
+		FastPartitioner partitioner = new FastPartitioner(new FastJavaPartitionScanner(), LEGAL_CONTENT_TYPES);
+		document.setDocumentPartitioner(configuration.getConfiguredDocumentPartitioning(viewer), partitioner);
+		partitioner.connect(document);
+
+		viewer.configure(configuration);
+		viewer.setDocument(document);
+		container.setCenter(viewer.getTextWidget());
+		Scene s = new Scene(container);
+		s.getStylesheets().add(getClass().getResource("bright.css").toExternalForm());
+		primaryStage.setScene(s);
+		primaryStage.show();
+	}
+
+	public static void main(String[] args) {
+		Application.launch(args);
+	}
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/bright.css b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/bright.css
new file mode 100644
index 0000000..881d8a4
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/bright.css
@@ -0,0 +1,78 @@
+.root {
+    /* @SuppressWarning */
+    -compensator-default-text: -fx-text-background-color;
+	/* @SuppressWarning */
+    -compensator-extra1: /*#957d47*/ derive(-fx-text-background-color, 110%);
+	-fx-font-size: 1em;
+}
+
+.cell-text-extra {
+	-fx-fill: -compensator-extra1;
+}
+
+.cell-text-default {
+	-fx-fill: -compensator-default-text;
+}
+
+.styled-text-area .list-view {
+	-fx-background-color: white;
+}
+
+.java.styled-text-area .java_string {
+	-styled-text-color: rgb(42, 0, 255);
+}
+
+.java.styled-text-area .java_default {
+	-styled-text-color: rgb(0,0,0);
+}
+
+.java.styled-text-area .java_annotation {
+	-styled-text-color: rgb(200, 200, 200);
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_keyword {
+	-styled-text-color: rgb(127, 0, 85);
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_operator {
+	-styled-text-color: rgb(0,0,0);
+}
+
+.java.styled-text-area .java_bracket {
+	-styled-text-color: rgb(0,0,0);
+}
+
+.java.styled-text-area .java_keyword_return {
+	-styled-text-color: rgb(127, 0, 85);
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_comment_task_tag {
+	-styled-text-color: rgb(127, 159, 191);
+}
+
+.java.styled-text-area .java_doc_link {
+	-styled-text-color: rgb(63, 63, 191);
+}
+
+.java.styled-text-area .java_doc_default {
+	-styled-text-color: rgb(63, 95, 191);
+}
+
+.java.styled-text-area .java_multi_line_comment {
+	-styled-text-color: rgb(63, 127, 95);
+}
+
+.java.styled-text-area .java_single_line_comment {
+	-styled-text-color: rgb(63, 127, 95);
+}
+
+.java.styled-text-area .java_doc_tag {
+	-styled-text-color: rgb(127, 127, 159);
+}
+
+.java.styled-text-area .java_number {
+	-styled-text-color: rgb(42, 0, 255);	
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/dark.css b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/dark.css
new file mode 100644
index 0000000..0eef5bb
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/dark.css
@@ -0,0 +1,100 @@
+.root {
+    -fx-base: #4d5052;
+    -fx-background: #4d5052;
+    -fx-control-inner-background: #4d5052;
+    -fx-text-base-color: #c7c7c7;
+    /* @SuppressWarning */
+    -compensator-default-text: -fx-text-background-color;
+	/* @SuppressWarning */
+    -compensator-extra1: /*#957d47*/ derive(-fx-text-background-color, -30%);
+}
+
+.cell-text-extra {
+	-fx-fill: -compensator-extra1;
+}
+
+.cell-text-default {
+	-fx-fill: -compensator-default-text;
+}
+
+.styled-text-area .list-view {
+	-fx-background-color: #393939;
+}
+
+.styled-text-area .list-cell:filled:focused:selected {
+	-fx-background-color: #414141;
+}
+
+.styled-text-area .line-ruler-text {
+	-fx-text-fill: #c7c7c7;
+}
+
+.styled-text-area .text-caret {
+	-fx-fill: #c7c7c7;
+	-fx-stroke: #c7c7c7;
+}
+
+.java.styled-text-area .selection-marker {
+	-fx-background-color: #2b5696;
+}
+
+.java.styled-text-area .java_string {
+	-styled-text-color: #7c986c;
+}
+
+.java.styled-text-area .java_default {
+	-styled-text-color: #b8c4d1;
+}
+
+.java.styled-text-area .java_annotation {
+	-styled-text-color: rgb(200, 200, 200);
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_keyword {
+	-styled-text-color: #d78b40;
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_operator {
+	-styled-text-color: #b8c4d1;
+}
+
+.java.styled-text-area .java_bracket {
+	-styled-text-color: #b8c4d1;
+}
+
+.java.styled-text-area .java_keyword_return {
+	-styled-text-color: #d78b40;
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_comment_task_tag {
+	-styled-text-color: rgb(127, 159, 191);
+}
+
+.java.styled-text-area .java_doc_link {
+	-styled-text-color: #74a567;
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_doc_default {
+	-styled-text-color: #74a567;
+}
+
+.java.styled-text-area .java_multi_line_comment {
+	-styled-text-color: #929292;
+}
+
+.java.styled-text-area .java_single_line_comment {
+	-styled-text-color: #929292;
+}
+
+.java.styled-text-area .java_doc_tag {
+	-fx-fill: #74a567;
+	-fx-font-weight: bold;
+}
+
+.java.styled-text-area .java_number {
+	-styled-text-color: #7c986c;	
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/AbstractJavaScanner.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/AbstractJavaScanner.java
new file mode 100644
index 0000000..f56cb2a
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/AbstractJavaScanner.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+import java.util.List;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.Token;
+
+public abstract class AbstractJavaScanner extends BufferedRuleBasedScanner {
+	
+	public AbstractJavaScanner() {
+	}
+	
+	public final void initialize() {
+		initializeRules();
+	}
+	
+	abstract protected List<IRule> createRules();
+	
+	private void initializeRules() {
+		List<IRule> rules= createRules();
+		if (rules != null) {
+			IRule[] result= new IRule[rules.size()];
+			rules.toArray(result);
+			setRules(result);
+		}
+	}
+	
+	protected Token getToken(String key) {
+		switch (key) {
+		case IJavaColorConstants.JAVA_STRING:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_STRING));
+		case IJavaColorConstants.JAVA_DEFAULT:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_DEFAULT));
+		case IJavaColorConstants.ANNOTATION:
+			return new Token(new TextAttribute(IJavaColorConstants.ANNOTATION));
+		case IJavaColorConstants.JAVA_KEYWORD:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_KEYWORD));
+		case IJavaColorConstants.JAVA_OPERATOR:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_OPERATOR));
+		case IJavaColorConstants.JAVA_BRACKET:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_BRACKET));
+		case IJavaColorConstants.JAVA_KEYWORD_RETURN:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_KEYWORD_RETURN));
+		case IJavaColorConstants.TASK_TAG:
+			return new Token(new TextAttribute(IJavaColorConstants.TASK_TAG));
+		case IJavaColorConstants.JAVADOC_LINK:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVADOC_LINK));
+		case IJavaColorConstants.JAVADOC_DEFAULT:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVADOC_DEFAULT));
+		case IJavaColorConstants.JAVA_MULTI_LINE_COMMENT:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_MULTI_LINE_COMMENT));
+		case IJavaColorConstants.JAVA_SINGLE_LINE_COMMENT:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_SINGLE_LINE_COMMENT));
+		case IJavaColorConstants.JAVADOC_TAG:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVADOC_TAG));
+		case IJavaColorConstants.JAVA_NUMBER:
+			return new Token(new TextAttribute(IJavaColorConstants.JAVA_NUMBER));
+		default:
+			throw new IllegalStateException("Unknown key '"+ key+"'");
+		}
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/FastJavaPartitionScanner.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/FastJavaPartitionScanner.java
new file mode 100644
index 0000000..203352b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/FastJavaPartitionScanner.java
@@ -0,0 +1,534 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.BufferedDocumentScanner;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+
+/**
+ * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments,
+ * Java strings and Java characters.
+ */
+public class FastJavaPartitionScanner implements IPartitionTokenScanner, IJavaPartitions {
+
+	// states
+	private static final int JAVA= 0;
+	private static final int SINGLE_LINE_COMMENT= 1;
+	private static final int MULTI_LINE_COMMENT= 2;
+	private static final int JAVADOC= 3;
+	private static final int CHARACTER= 4;
+	private static final int STRING= 5;
+
+	// beginning of prefixes and postfixes
+	private static final int NONE= 0;
+	private static final int BACKSLASH= 1; // postfix for STRING and CHARACTER
+	private static final int SLASH= 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC
+	private static final int SLASH_STAR= 3; // prefix for MULTI_LINE_COMMENT or JAVADOC
+	private static final int SLASH_STAR_STAR= 4; // prefix for MULTI_LINE_COMMENT or JAVADOC
+	private static final int STAR= 5; // postfix for MULTI_LINE_COMMENT or JAVADOC
+	private static final int CARRIAGE_RETURN=6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT
+
+	/** The scanner. */
+	private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000);	// faster implementation
+
+	/** The offset of the last returned token. */
+	private int fTokenOffset;
+	/** The length of the last returned token. */
+	private int fTokenLength;
+
+	/** The state of the scanner. */
+	private int fState;
+	/** The last significant characters read. */
+	private int fLast;
+	/** The amount of characters already read on first call to nextToken(). */
+	private int fPrefixLength;
+
+	// emulate JavaPartitionScanner
+	private boolean fEmulate= false;
+	private int fJavaOffset;
+	private int fJavaLength;
+
+	private final IToken[] fTokens= new IToken[] {
+		new Token(null),
+		new Token(JAVA_SINGLE_LINE_COMMENT),
+		new Token(JAVA_MULTI_LINE_COMMENT),
+		new Token(JAVA_DOC),
+		new Token(JAVA_CHARACTER),
+		new Token(JAVA_STRING)
+	};
+
+	public FastJavaPartitionScanner(boolean emulate) {
+	    fEmulate= emulate;
+	}
+
+	public FastJavaPartitionScanner() {
+	    this(false);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
+	 */
+	public IToken nextToken() {
+
+		// emulate JavaPartitionScanner
+		if (fEmulate) {
+			if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
+				fTokenOffset += fTokenLength;
+				return fTokens[JAVA];
+			} else {
+				fJavaOffset= -1;
+				fJavaLength= 0;
+			}
+		}
+
+		fTokenOffset += fTokenLength;
+		fTokenLength= fPrefixLength;
+
+		while (true) {
+			final int ch= fScanner.read();
+
+			// characters
+	 		switch (ch) {
+	 		case ICharacterScanner.EOF:
+		 		if (fTokenLength > 0) {
+		 			fLast= NONE; // ignore last
+		 			return preFix(fState, JAVA, NONE, 0);
+
+		 		} else {
+		 			fLast= NONE;
+		 			fPrefixLength= 0;
+					return Token.EOF;
+		 		}
+
+	 		case '\r':
+	 			// emulate JavaPartitionScanner
+	 			if (!fEmulate && fLast != CARRIAGE_RETURN) {
+						fLast= CARRIAGE_RETURN;
+						fTokenLength++;
+	 					continue;
+
+	 			} else {
+
+					switch (fState) {
+					case SINGLE_LINE_COMMENT:
+					case CHARACTER:
+					case STRING:
+						if (fTokenLength > 0) {
+							IToken token= fTokens[fState];
+
+				 			// emulate JavaPartitionScanner
+							if (fEmulate) {
+								fTokenLength++;
+								fLast= NONE;
+								fPrefixLength= 0;
+							} else {
+								fLast= CARRIAGE_RETURN;
+								fPrefixLength= 1;
+							}
+
+							fState= JAVA;
+							return token;
+
+						} else {
+							consume();
+							continue;
+						}
+
+					default:
+						consume();
+						continue;
+					}
+	 			}
+
+	 		case '\n':
+				switch (fState) {
+				case SINGLE_LINE_COMMENT:
+				case CHARACTER:
+				case STRING:
+					// assert(fTokenLength > 0);
+					return postFix(fState);
+
+				default:
+					consume();
+					continue;
+				}
+
+			default:
+				if (!fEmulate && fLast == CARRIAGE_RETURN) {
+					switch (fState) {
+					case SINGLE_LINE_COMMENT:
+					case CHARACTER:
+					case STRING:
+
+						int last;
+						int newState;
+						switch (ch) {
+						case '/':
+							last= SLASH;
+							newState= JAVA;
+							break;
+
+						case '*':
+							last= STAR;
+							newState= JAVA;
+							break;
+
+						case '\'':
+							last= NONE;
+							newState= CHARACTER;
+							break;
+
+						case '"':
+							last= NONE;
+							newState= STRING;
+							break;
+
+						case '\r':
+							last= CARRIAGE_RETURN;
+							newState= JAVA;
+							break;
+
+						case '\\':
+							last= BACKSLASH;
+							newState= JAVA;
+							break;
+
+						default:
+							last= NONE;
+							newState= JAVA;
+							break;
+						}
+
+						fLast= NONE; // ignore fLast
+						return preFix(fState, newState, last, 1);
+
+					default:
+						break;
+					}
+				}
+			}
+
+			// states
+	 		switch (fState) {
+	 		case JAVA:
+				switch (ch) {
+				case '/':
+					if (fLast == SLASH) {
+						if (fTokenLength - getLastLength(fLast) > 0) {
+							return preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2);
+						} else {
+							preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2);
+							fTokenOffset += fTokenLength;
+							fTokenLength= fPrefixLength;
+							break;
+						}
+
+					} else {
+						fTokenLength++;
+						fLast= SLASH;
+						break;
+					}
+
+				case '*':
+					if (fLast == SLASH) {
+						if (fTokenLength - getLastLength(fLast) > 0)
+							return preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2);
+						else {
+							preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2);
+							fTokenOffset += fTokenLength;
+							fTokenLength= fPrefixLength;
+							break;
+						}
+
+					} else {
+						consume();
+						break;
+					}
+
+				case '\'':
+					fLast= NONE; // ignore fLast
+					if (fTokenLength > 0)
+						return preFix(JAVA, CHARACTER, NONE, 1);
+					else {
+						preFix(JAVA, CHARACTER, NONE, 1);
+						fTokenOffset += fTokenLength;
+						fTokenLength= fPrefixLength;
+						break;
+					}
+
+				case '"':
+					fLast= NONE; // ignore fLast
+					if (fTokenLength > 0)
+						return preFix(JAVA, STRING, NONE, 1);
+					else {
+						preFix(JAVA, STRING, NONE, 1);
+						fTokenOffset += fTokenLength;
+						fTokenLength= fPrefixLength;
+						break;
+					}
+
+				default:
+					consume();
+					break;
+				}
+				break;
+
+	 		case SINGLE_LINE_COMMENT:
+				consume();
+				break;
+
+	 		case JAVADOC:
+				switch (ch) {
+				case '/':
+					switch (fLast) {
+					case SLASH_STAR_STAR:
+						return postFix(MULTI_LINE_COMMENT);
+
+					case STAR:
+						return postFix(JAVADOC);
+
+					default:
+						consume();
+						break;
+					}
+					break;
+
+				case '*':
+					fTokenLength++;
+					fLast= STAR;
+					break;
+
+				default:
+					consume();
+					break;
+				}
+				break;
+
+	 		case MULTI_LINE_COMMENT:
+				switch (ch) {
+				case '*':
+					if (fLast == SLASH_STAR) {
+						fLast= SLASH_STAR_STAR;
+						fTokenLength++;
+						fState= JAVADOC;
+					} else {
+						fTokenLength++;
+						fLast= STAR;
+					}
+					break;
+
+				case '/':
+					if (fLast == STAR) {
+						return postFix(MULTI_LINE_COMMENT);
+					} else {
+						consume();
+						break;
+					}
+
+				default:
+					consume();
+					break;
+				}
+				break;
+
+	 		case STRING:
+	 			switch (ch) {
+	 			case '\\':
+					fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
+					fTokenLength++;
+					break;
+
+				case '\"':
+	 				if (fLast != BACKSLASH) {
+	 					return postFix(STRING);
+
+		 			} else {
+						consume();
+						break;
+	 				}
+
+		 		default:
+					consume();
+	 				break;
+	 			}
+	 			break;
+
+	 		case CHARACTER:
+	 			switch (ch) {
+				case '\\':
+					fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
+					fTokenLength++;
+					break;
+
+	 			case '\'':
+	 				if (fLast != BACKSLASH) {
+	 					return postFix(CHARACTER);
+
+	 				} else {
+						consume();
+		 				break;
+	 				}
+
+	 			default:
+					consume();
+	 				break;
+	 			}
+	 			break;
+	 		}
+		}
+ 	}
+
+	private static final int getLastLength(int last) {
+		switch (last) {
+		default:
+			return -1;
+
+		case NONE:
+			return 0;
+
+		case CARRIAGE_RETURN:
+		case BACKSLASH:
+		case SLASH:
+		case STAR:
+			return 1;
+
+		case SLASH_STAR:
+			return 2;
+
+		case SLASH_STAR_STAR:
+			return 3;
+		}
+	}
+
+	private final void consume() {
+		fTokenLength++;
+		fLast= NONE;
+	}
+
+	private final IToken postFix(int state) {
+		fTokenLength++;
+		fLast= NONE;
+		fState= JAVA;
+		fPrefixLength= 0;
+		return fTokens[state];
+	}
+
+	private final IToken preFix(int state, int newState, int last, int prefixLength) {
+		// emulate JavaPartitionScanner
+		if (fEmulate && state == JAVA && (fTokenLength - getLastLength(fLast) > 0)) {
+			fTokenLength -= getLastLength(fLast);
+			fJavaOffset= fTokenOffset;
+			fJavaLength= fTokenLength;
+			fTokenLength= 1;
+			fState= newState;
+			fPrefixLength= prefixLength;
+			fLast= last;
+			return fTokens[state];
+
+		} else {
+			fTokenLength -= getLastLength(fLast);
+			fLast= last;
+			fPrefixLength= prefixLength;
+			IToken token= fTokens[state];
+			fState= newState;
+			return token;
+		}
+	}
+
+	private static int getState(String contentType) {
+
+		if (contentType == null)
+			return JAVA;
+
+		else if (contentType.equals(JAVA_SINGLE_LINE_COMMENT))
+			return SINGLE_LINE_COMMENT;
+
+		else if (contentType.equals(JAVA_MULTI_LINE_COMMENT))
+			return MULTI_LINE_COMMENT;
+
+		else if (contentType.equals(JAVA_DOC))
+			return JAVADOC;
+
+		else if (contentType.equals(JAVA_STRING))
+			return STRING;
+
+		else if (contentType.equals(JAVA_CHARACTER))
+			return CHARACTER;
+
+		else
+			return JAVA;
+	}
+
+	/*
+	 * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
+	 */
+	public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
+
+		fScanner.setRange(document, offset, length);
+		fTokenOffset= partitionOffset;
+		fTokenLength= 0;
+		fPrefixLength= offset - partitionOffset;
+		fLast= NONE;
+
+		if (offset == partitionOffset) {
+			// restart at beginning of partition
+			fState= JAVA;
+		} else {
+			fState= getState(contentType);
+		}
+
+		// emulate JavaPartitionScanner
+		if (fEmulate) {
+			fJavaOffset= -1;
+			fJavaLength= 0;
+		}
+	}
+
+	/*
+	 * @see ITokenScanner#setRange(IDocument, int, int)
+	 */
+	public void setRange(IDocument document, int offset, int length) {
+
+		fScanner.setRange(document, offset, length);
+		fTokenOffset= offset;
+		fTokenLength= 0;
+		fPrefixLength= 0;
+		fLast= NONE;
+		fState= JAVA;
+
+		// emulate JavaPartitionScanner
+		if (fEmulate) {
+			fJavaOffset= -1;
+			fJavaLength= 0;
+		}
+	}
+
+	/*
+	 * @see ITokenScanner#getTokenLength()
+	 */
+	public int getTokenLength() {
+		return fTokenLength;
+	}
+
+	/*
+	 * @see ITokenScanner#getTokenOffset()
+	 */
+	public int getTokenOffset() {
+		return fTokenOffset;
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaColorConstants.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaColorConstants.java
new file mode 100644
index 0000000..c16bf61
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaColorConstants.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+/**
+ * Color keys used for syntax highlighting Java
+ * code and Javadoc compliant comments.
+ * A <code>IColorManager</code> is responsible for mapping
+ * concrete colors to these keys.
+ * <p>
+ * This interface declares static final fields only; it is not intended to be
+ * implemented.
+ * </p>
+ *
+ * @see org.eclipse.jdt.ui.text.IColorManager
+ * @see org.eclipse.jdt.ui.text.IColorManagerExtension
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface IJavaColorConstants {
+
+	/**
+	 * Note: This constant is for internal use only. Clients should not use this constant. The
+	 * prefix all color constants start with (value <code>"java_"</code>).
+	 */
+	String PREFIX= "java_"; //$NON-NLS-1$
+
+	/** The color key for multi-line comments in Java code
+	 * (value <code>"java_multi_line_comment"</code>).
+	 */
+	String JAVA_MULTI_LINE_COMMENT= "java_multi_line_comment"; //$NON-NLS-1$
+
+	/** The color key for single-line comments in Java code
+	 * (value <code>"java_single_line_comment"</code>).
+	 */
+	String JAVA_SINGLE_LINE_COMMENT= "java_single_line_comment"; //$NON-NLS-1$
+
+	/** The color key for Java keywords in Java code
+	 * (value <code>"java_keyword"</code>).
+	 */
+	String JAVA_KEYWORD= "java_keyword"; //$NON-NLS-1$
+
+	/** The color key for string and character literals in Java code
+	 * (value <code>"java_string"</code>).
+	 */
+	String JAVA_STRING= "java_string"; //$NON-NLS-1$
+
+	/** The color key for method names in Java code
+	 * (value <code>"java_method_name"</code>).
+	 *
+	 * @since 3.0
+	 * @deprecated replaced as of 3.1 by an equivalent semantic highlighting, see {@link org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightings#METHOD}
+	 */
+	String JAVA_METHOD_NAME= "java_method_name"; //$NON-NLS-1$
+
+	/** The color key for keyword 'return' in Java code
+	 * (value <code>"java_keyword_return"</code>).
+	 *
+	 * @since 3.0
+	 */
+	String JAVA_KEYWORD_RETURN= "java_keyword_return"; //$NON-NLS-1$
+
+	/** The color key for operators in Java code
+	 * (value <code>"java_operator"</code>).
+	 *
+	 * @since 3.0
+	 */
+	String JAVA_OPERATOR= "java_operator"; //$NON-NLS-1$
+
+	/** The color key for brackets in Java code
+	 * (value <code>"java_bracket"</code>).
+	 *
+	 * @since 3.3
+	 */
+	String JAVA_BRACKET= "java_bracket"; //$NON-NLS-1$
+
+	/**
+	 * The color key for everything in Java code for which no other color is specified
+	 * (value <code>"java_default"</code>).
+	 */
+	String JAVA_DEFAULT= "java_default"; //$NON-NLS-1$
+
+	/**
+	 * The color key for the Java built-in types such as <code>int</code> and <code>char</code> in Java code
+	 * (value <code>"java_type"</code>).
+	 *
+	 * @deprecated no longer used, replaced by <code>JAVA_KEYWORD</code>
+	 */
+	String JAVA_TYPE= "java_type"; //$NON-NLS-1$
+
+	/**
+	 * The color key for annotations
+	 * (value <code>"java_annotation"</code>).
+	 *
+	 * @since 3.1
+	 * @deprecated replaced as of 3.2 by an equivalent semantic highlighting, see {@link org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightings#ANNOTATION}
+	 */
+	String JAVA_ANNOTATION= "java_annotation"; //$NON-NLS-1$
+
+	/**
+	 * The color key for task tags in java comments
+	 * (value <code>"java_comment_task_tag"</code>).
+	 *
+	 * @since 2.1
+	 */
+	String TASK_TAG= "java_comment_task_tag"; //$NON-NLS-1$
+
+	/**
+	 * The color key for JavaDoc keywords (<code>@foo</code>) in JavaDoc comments
+	 * (value <code>"java_doc_keyword"</code>).
+	 */
+	String JAVADOC_KEYWORD= "java_doc_keyword"; //$NON-NLS-1$
+
+	/**
+	 * The color key for HTML tags (<code>&lt;foo&gt;</code>) in JavaDoc comments
+	 * (value <code>"java_doc_tag"</code>).
+	 */
+	String JAVADOC_TAG= "java_doc_tag"; //$NON-NLS-1$
+
+	/**
+	 * The color key for JavaDoc links (<code>{foo}</code>) in JavaDoc comments
+	 * (value <code>"java_doc_link"</code>).
+	 */
+	String JAVADOC_LINK= "java_doc_link"; //$NON-NLS-1$
+
+	/**
+	 * The color key for everything in JavaDoc comments for which no other color is specified
+	 * (value <code>"java_doc_default"</code>).
+	 */
+	String JAVADOC_DEFAULT= "java_doc_default"; //$NON-NLS-1$
+	
+
+	String JAVA_NUMBER = "java_number";
+
+	//---------- Properties File Editor ----------
+
+	/**
+	 * The color key for keys in a properties file
+	 * (value <code>"pf_coloring_key"</code>).
+	 *
+	 * @since 3.1
+	 */
+	String PROPERTIES_FILE_COLORING_KEY= "pf_coloring_key"; //$NON-NLS-1$
+
+	/**
+	 * The color key for comments in a properties file
+	 * (value <code>"pf_coloring_comment"</code>).
+	 *
+	 * @since 3.1
+	 */
+
+	String PROPERTIES_FILE_COLORING_COMMENT= "pf_coloring_comment"; //$NON-NLS-1$
+
+	/**
+	 * The color key for values in a properties file
+	 * (value <code>"pf_coloring_value"</code>).
+	 *
+	 * @since 3.1
+	 */
+	String PROPERTIES_FILE_COLORING_VALUE= "pf_coloring_value"; //$NON-NLS-1$
+
+	/**
+	 * The color key for assignment in a properties file.
+	 * (value <code>"pf_coloring_assignment"</code>).
+	 *
+	 * @since 3.1
+	 */
+	String PROPERTIES_FILE_COLORING_ASSIGNMENT= "pf_coloring_assignment"; //$NON-NLS-1$
+
+	/**
+	 * The color key for arguments in values in a properties file.
+	 * (value <code>"pf_coloring_argument"</code>).
+	 *
+	 * @since 3.1
+	 */
+	String PROPERTIES_FILE_COLORING_ARGUMENT= "pf_coloring_argument"; //$NON-NLS-1$
+
+	
+	public static final String ANNOTATION="java_annotation"; //$NON-NLS-1$
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaPartitions.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaPartitions.java
new file mode 100644
index 0000000..d82ff30
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaPartitions.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+/**
+ * Definition of Java partitioning and its partitions.
+ *
+ * @since 3.1
+ */
+public interface IJavaPartitions {
+
+	/**
+	 * The identifier of the Java partitioning.
+	 */
+	String JAVA_PARTITIONING= "___java_partitioning";  //$NON-NLS-1$
+
+	/**
+	 * The identifier of the single-line (JLS2: EndOfLineComment) end comment partition content type.
+	 */
+	String JAVA_SINGLE_LINE_COMMENT= "__java_singleline_comment"; //$NON-NLS-1$
+
+	/**
+	 * The identifier multi-line (JLS2: TraditionalComment) comment partition content type.
+	 */
+	String JAVA_MULTI_LINE_COMMENT= "__java_multiline_comment"; //$NON-NLS-1$
+
+	/**
+	 * The identifier of the Javadoc (JLS2: DocumentationComment) partition content type.
+	 */
+	String JAVA_DOC= "__java_javadoc"; //$NON-NLS-1$
+
+	/**
+	 * The identifier of the Java string partition content type.
+	 */
+	String JAVA_STRING= "__java_string"; //$NON-NLS-1$
+
+	/**
+	 * The identifier of the Java character partition content type.
+	 */
+	String JAVA_CHARACTER= "__java_character";  //$NON-NLS-1$
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCodeScanner.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCodeScanner.java
new file mode 100644
index 0000000..94f519c
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCodeScanner.java
@@ -0,0 +1,406 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.rules.CombinedWordRule;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+
+public class JavaCodeScanner extends AbstractJavaScanner {
+	private static final String INTERFACE= "interface";  //$NON-NLS-1$
+	private static final String RETURN= "return"; //$NON-NLS-1$
+	
+	private static String[] fgJava14Keywords= { "assert" }; //$NON-NLS-1$
+	private static String[] fgJava15Keywords= { "enum" }; //$NON-NLS-1$
+	
+	static String[] fgKeywords= {
+		"abstract", //$NON-NLS-1$
+		"break", //$NON-NLS-1$
+		"case", "catch", "class", "const", "continue", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+		"default", "do", //$NON-NLS-2$ //$NON-NLS-1$
+		"else", "extends", //$NON-NLS-2$ //$NON-NLS-1$
+		"final", "finally", "for", //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+		"goto", //$NON-NLS-1$
+		"if", "implements", "import", "instanceof", "interface", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+		"native", "new", //$NON-NLS-2$ //$NON-NLS-1$
+		"package", "private", "protected", "public", //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+		"static", "super", "switch", "synchronized", //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+		"this", "throw", "throws", "transient", "try", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+		"volatile", //$NON-NLS-1$
+		"while" //$NON-NLS-1$
+	};
+
+	private static String[] fgTypes= { "void", "boolean", "char", "byte", "short", "strictfp", "int", "long", "float", "double" }; //$NON-NLS-1$ //$NON-NLS-5$ //$NON-NLS-7$ //$NON-NLS-6$ //$NON-NLS-8$ //$NON-NLS-9$  //$NON-NLS-10$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-2$
+	private static String[] fgConstants= { "false", "null", "true" }; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
+	
+	public JavaCodeScanner() {
+		initialize();
+	}
+	
+//	@Override
+//	public IToken nextToken() {
+//		IToken nextToken = super.nextToken();
+//		System.err.println("FIND TOKEN: " + nextToken.getData());
+//		return nextToken;
+//	}
+	
+	@Override
+	protected List<IRule> createRules() {
+		List<IRule> rules= new ArrayList<IRule>();
+	
+		Token token= getToken(IJavaColorConstants.JAVA_STRING);
+		rules.add(new SingleLineRule("'", "'", token, '\\')); //$NON-NLS-2$ //$NON-NLS-1$
+		
+		Token defaultToken= getToken(IJavaColorConstants.JAVA_DEFAULT);
+		
+		// Add generic whitespace rule.
+		rules.add(new WhitespaceRule(new JavaWhitespaceDetector(), defaultToken));
+
+		token= getToken(IJavaColorConstants.ANNOTATION);
+		AnnotationRule atInterfaceRule= new AnnotationRule(getToken(IJavaColorConstants.JAVA_KEYWORD), token);
+		rules.add(atInterfaceRule);
+
+		// Add word rule for new keywords, see bug 4077
+		JavaWordDetector wordDetector= new JavaWordDetector();
+		CombinedWordRule combinedWordRule= new CombinedWordRule(wordDetector, defaultToken);
+
+		// Add rule for operators
+		token= getToken(IJavaColorConstants.JAVA_OPERATOR);
+		rules.add(new OperatorRule(token));
+
+		// Add rule for brackets
+		token= getToken(IJavaColorConstants.JAVA_BRACKET);
+		rules.add(new BracketRule(token));
+
+		// Add word rule for keyword 'return'.
+		CombinedWordRule.WordMatcher returnWordRule= new CombinedWordRule.WordMatcher();
+		token= getToken(IJavaColorConstants.JAVA_KEYWORD_RETURN);
+		returnWordRule.addWord(RETURN, token);
+		combinedWordRule.addWordMatcher(returnWordRule);
+
+		// Add word rule for keywords, types, and constants.
+		CombinedWordRule.WordMatcher wordRule= new CombinedWordRule.WordMatcher();
+		token= getToken(IJavaColorConstants.JAVA_KEYWORD);
+		
+		for (int i=0; i<fgJava14Keywords.length; i++)
+			wordRule.addWord(fgJava14Keywords[i], token);
+		for (int i=0; i<fgJava15Keywords.length; i++)
+			wordRule.addWord(fgJava15Keywords[i], token);
+		for (int i=0; i<fgKeywords.length; i++)
+			wordRule.addWord(fgKeywords[i], token);
+		for (int i=0; i<fgTypes.length; i++)
+			wordRule.addWord(fgTypes[i], token);
+		for (int i=0; i<fgConstants.length; i++)
+			wordRule.addWord(fgConstants[i], token);
+
+		combinedWordRule.addWordMatcher(wordRule);
+
+		rules.add(combinedWordRule);
+		
+		token = getToken(IJavaColorConstants.JAVA_NUMBER);
+		rules.add(new NumberRule(token));
+
+		setDefaultReturnToken(defaultToken);
+		return rules;
+	}
+	
+	/**
+	 * An annotation rule matches the '@' symbol, any following whitespace and
+	 * optionally a following <code>interface</code> keyword.
+	 *
+	 * It does not match if there is a comment between the '@' symbol and
+	 * the identifier. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=82452
+	 *
+	 * @since 3.1
+	 */
+	private static class AnnotationRule implements IRule {
+		/**
+		 * A resettable scanner supports marking a position in a scanner and
+		 * unreading back to the marked position.
+		 */
+		private static final class ResettableScanner implements ICharacterScanner {
+			private final ICharacterScanner fDelegate;
+			private int fReadCount;
+
+			/**
+			 * Creates a new resettable scanner that will forward calls
+			 * to <code>scanner</code>, but store a marked position.
+			 *
+			 * @param scanner the delegate scanner
+			 */
+			public ResettableScanner(final ICharacterScanner scanner) {
+				fDelegate= scanner;
+				mark();
+			}
+
+			/*
+			 * @see org.eclipse.jface.text.rules.ICharacterScanner#getColumn()
+			 */
+			public int getColumn() {
+				return fDelegate.getColumn();
+			}
+
+			/*
+			 * @see org.eclipse.jface.text.rules.ICharacterScanner#getLegalLineDelimiters()
+			 */
+			public char[][] getLegalLineDelimiters() {
+				return fDelegate.getLegalLineDelimiters();
+			}
+
+			/*
+			 * @see org.eclipse.jface.text.rules.ICharacterScanner#read()
+			 */
+			public int read() {
+				int ch= fDelegate.read();
+				if (ch != ICharacterScanner.EOF)
+					fReadCount++;
+				return ch;
+			}
+
+			/*
+			 * @see org.eclipse.jface.text.rules.ICharacterScanner#unread()
+			 */
+			public void unread() {
+				if (fReadCount > 0)
+					fReadCount--;
+				fDelegate.unread();
+			}
+
+			/**
+			 * Marks an offset in the scanned content.
+			 */
+			public void mark() {
+				fReadCount= 0;
+			}
+
+			/**
+			 * Resets the scanner to the marked position.
+			 */
+			public void reset() {
+				while (fReadCount > 0)
+					unread();
+
+				while (fReadCount < 0)
+					read();
+			}
+		}
+		
+		private final IWhitespaceDetector fWhitespaceDetector= new JavaWhitespaceDetector();
+		private final IWordDetector fWordDetector= new JavaWordDetector();
+		private final IToken fInterfaceToken;
+		private final IToken fAtToken;
+
+		/**
+		 * Creates a new rule.
+		 *
+		 * @param interfaceToken the token to return if
+		 *        <code>'@\s*interface'</code> is matched
+		 * @param atToken the token to return if <code>'@'</code>
+		 *        is matched, but not <code>'@\s*interface'</code>
+		 * @param version the lowest <code>JavaCore.COMPILER_SOURCE</code>
+		 *        version that this rule is enabled
+		 * @param currentVersion the current
+		 *        <code>JavaCore.COMPILER_SOURCE</code> version
+		 */
+		public AnnotationRule(IToken interfaceToken, Token atToken) {
+			fInterfaceToken= interfaceToken;
+			fAtToken= atToken;
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner)
+		 */
+		public IToken evaluate(ICharacterScanner scanner) {
+			ResettableScanner resettable= new ResettableScanner(scanner);
+			if (resettable.read() == '@')
+				return readAnnotation(resettable);
+
+			resettable.reset();
+			return Token.UNDEFINED;
+		}
+
+		private IToken readAnnotation(ResettableScanner scanner) {
+			scanner.mark();
+			skipWhitespace(scanner);
+			if (readInterface(scanner)) {
+				return fInterfaceToken;
+			} else {
+				while( Character.isJavaIdentifierPart(scanner.read()) ) {
+				}
+				scanner.unread();
+//				scanner.reset();
+				return fAtToken;
+			}
+		}
+		
+		private boolean readInterface(ICharacterScanner scanner) {
+			int ch= scanner.read();
+			int i= 0;
+			while (i < INTERFACE.length() && INTERFACE.charAt(i) == ch) {
+				i++;
+				ch= scanner.read();
+			}
+			if (i < INTERFACE.length())
+				return false;
+
+			if (fWordDetector.isWordPart((char) ch))
+				return false;
+
+			if (ch != ICharacterScanner.EOF)
+				scanner.unread();
+
+			return true;
+		}
+
+		private boolean skipWhitespace(ICharacterScanner scanner) {
+			while (fWhitespaceDetector.isWhitespace((char) scanner.read())) {
+				// do nothing
+			}
+
+			scanner.unread();
+			return true;
+		}
+
+	}
+	
+	private static final class NumberRule implements IRule {
+		private final IToken fToken;
+		
+		public NumberRule(IToken fToken) {
+			this.fToken = fToken;
+		}
+
+		@Override
+		public IToken evaluate(ICharacterScanner scanner) {
+			int v = scanner.read();
+			
+			if( Character.isDigit(v) ) {
+				while( (v = scanner.read()) != ICharacterScanner.EOF ) {
+					if( ! Character.isDigit(v) & v != '.' && v != '_' ) {
+						scanner.unread();
+						break;
+					}
+				}
+				return fToken;
+			} else {
+				return Token.UNDEFINED;
+			}
+		}
+		
+	}
+	
+	private static final class OperatorRule implements IRule {
+
+		/** Java operators */
+		private final char[] JAVA_OPERATORS= { ';', '.', '=', '/', '\\', '+', '-', '*', '<', '>', ':', '?', '!', ',', '|', '&', '^', '%', '~'};
+		/** Token to return for this rule */
+		private final IToken fToken;
+
+		/**
+		 * Creates a new operator rule.
+		 *
+		 * @param token Token to use for this rule
+		 */
+		public OperatorRule(IToken token) {
+			fToken= token;
+		}
+
+		/**
+		 * Is this character an operator character?
+		 *
+		 * @param character Character to determine whether it is an operator character
+		 * @return <code>true</code> iff the character is an operator, <code>false</code> otherwise.
+		 */
+		public boolean isOperator(char character) {
+			for (int index= 0; index < JAVA_OPERATORS.length; index++) {
+				if (JAVA_OPERATORS[index] == character)
+					return true;
+			}
+			return false;
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner)
+		 */
+		public IToken evaluate(ICharacterScanner scanner) {
+
+			int character= scanner.read();
+			if (isOperator((char) character)) {
+				do {
+					character= scanner.read();
+				} while (isOperator((char) character));
+				scanner.unread();
+				return fToken;
+			} else {
+				scanner.unread();
+				return Token.UNDEFINED;
+			}
+		}
+	}
+	
+	private static final class BracketRule implements IRule {
+
+		/** Java brackets */
+		private final char[] JAVA_BRACKETS= { '(', ')', '{', '}', '[', ']' };
+		/** Token to return for this rule */
+		private final IToken fToken;
+
+		/**
+		 * Creates a new bracket rule.
+		 *
+		 * @param token Token to use for this rule
+		 */
+		public BracketRule(IToken token) {
+			fToken= token;
+		}
+
+		/**
+		 * Is this character a bracket character?
+		 *
+		 * @param character Character to determine whether it is a bracket character
+		 * @return <code>true</code> iff the character is a bracket, <code>false</code> otherwise.
+		 */
+		public boolean isBracket(char character) {
+			for (int index= 0; index < JAVA_BRACKETS.length; index++) {
+				if (JAVA_BRACKETS[index] == character)
+					return true;
+			}
+			return false;
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner)
+		 */
+		public IToken evaluate(ICharacterScanner scanner) {
+
+			int character= scanner.read();
+			if (isBracket((char) character)) {
+				do {
+					character= scanner.read();
+				} while (isBracket((char) character));
+				scanner.unread();
+				return fToken;
+			} else {
+				scanner.unread();
+				return Token.UNDEFINED;
+			}
+		}
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCommentScanner.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCommentScanner.java
new file mode 100644
index 0000000..6bb280f
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCommentScanner.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.jface.text.rules.CombinedWordRule;
+import org.eclipse.jface.text.rules.CombinedWordRule.CharacterBuffer;
+import org.eclipse.jface.text.rules.CombinedWordRule.WordMatcher;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.Token;
+
+public class JavaCommentScanner extends AbstractJavaScanner {
+	protected static final String TASK_TAG= IJavaColorConstants.TASK_TAG;
+	private TaskTagMatcher fTaskTagMatcher;
+	private String fDefaultTokenProperty;
+//	private String[] fTokenProperties;
+	
+	public JavaCommentScanner(String defaultTokenProperty) {
+		this(defaultTokenProperty, new String[] { defaultTokenProperty, TASK_TAG });
+	}
+	
+	public JavaCommentScanner(String defaultTokenProperty, String[] tokenProperties) {
+		fDefaultTokenProperty= defaultTokenProperty;
+//		fTokenProperties= tokenProperties;
+		initialize();
+	}
+
+	@Override
+	protected List<IRule> createRules() {
+		List<IRule> list= new ArrayList<IRule>();
+		Token defaultToken= getToken(fDefaultTokenProperty);
+
+		List<WordMatcher> matchers= createMatchers();
+		if (matchers.size() > 0) {
+			CombinedWordRule combinedWordRule= new CombinedWordRule(new AtJavaIdentifierDetector(), defaultToken);
+			for (int i= 0, n= matchers.size(); i < n; i++)
+				combinedWordRule.addWordMatcher(matchers.get(i));
+			list.add(combinedWordRule);
+		}
+
+		setDefaultReturnToken(defaultToken);
+
+		return list;
+	}
+	
+	protected List<WordMatcher> createMatchers() {
+		List<WordMatcher> list= new ArrayList<WordMatcher>();
+
+		// Add rule for Task Tags.
+		boolean isCaseSensitive= true;
+		String tasks= "TODO";
+//		if (getPreferenceStore().contains(COMPILER_TASK_TAGS)) {
+//			tasks= getPreferenceStore().getString(COMPILER_TASK_TAGS);
+//			isCaseSensitive= ENABLED.equals(getPreferenceStore().getString(COMPILER_TASK_CASE_SENSITIVE));
+//		} else if (fCorePreferenceStore != null) {
+//			tasks= fCorePreferenceStore.getString(COMPILER_TASK_TAGS);
+//			isCaseSensitive= ENABLED.equals(fCorePreferenceStore.getString(COMPILER_TASK_CASE_SENSITIVE));
+//		}
+		if (tasks != null) {
+			fTaskTagMatcher= new TaskTagMatcher(getToken(TASK_TAG));
+			fTaskTagMatcher.addTaskTags(tasks);
+			fTaskTagMatcher.setCaseSensitive(isCaseSensitive);
+			list.add(fTaskTagMatcher);
+		}
+
+		return list;
+	}
+	
+	private class TaskTagMatcher extends CombinedWordRule.WordMatcher {
+
+		private IToken fToken;
+		/**
+		 * Uppercase words
+		 * @since 3.0
+		 */
+		private Map<CharacterBuffer, IToken> fUppercaseWords= new HashMap<CharacterBuffer, IToken>();
+		/**
+		 * <code>true</code> if task tag detection is case-sensitive.
+		 * @since 3.0
+		 */
+		private boolean fCaseSensitive= true;
+		/**
+		 * Buffer for uppercase word
+		 * @since 3.0
+		 */
+		private CombinedWordRule.CharacterBuffer fBuffer= new CombinedWordRule.CharacterBuffer(16);
+
+		public TaskTagMatcher(IToken token) {
+			fToken= token;
+		}
+
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher#clearWords()
+		 * @since 3.0
+		 */
+		@Override
+		public synchronized void clearWords() {
+			super.clearWords();
+			fUppercaseWords.clear();
+		}
+
+		public synchronized void addTaskTags(String value) {
+			String[] tasks= split(value, ","); //$NON-NLS-1$
+			for (int i= 0; i < tasks.length; i++) {
+				if (tasks[i].length() > 0) {
+					addWord(tasks[i], fToken);
+				}
+			}
+		}
+
+		private String[] split(String value, String delimiters) {
+			StringTokenizer tokenizer= new StringTokenizer(value, delimiters);
+			int size= tokenizer.countTokens();
+			String[] tokens= new String[size];
+			int i= 0;
+			while (i < size)
+				tokens[i++]= tokenizer.nextToken();
+			return tokens;
+		}
+
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher#addWord(java.lang.String, org.eclipse.jface.text.rules.IToken)
+		 * @since 3.0
+		 */
+		@Override
+		public synchronized void addWord(String word, IToken token) {
+			super.addWord(word, token);
+			fUppercaseWords.put(new CombinedWordRule.CharacterBuffer(word.toUpperCase()), token);
+		}
+
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher#evaluate(org.eclipse.jface.text.rules.ICharacterScanner, org.eclipse.jdt.internal.ui.text.CombinedWordRule.CharacterBuffer)
+		 * @since 3.0
+		 */
+		@Override
+		public synchronized IToken evaluate(ICharacterScanner scanner, CombinedWordRule.CharacterBuffer word) {
+			if (fCaseSensitive)
+				return super.evaluate(scanner, word);
+
+			fBuffer.clear();
+			for (int i= 0, n= word.length(); i < n; i++)
+				fBuffer.append(Character.toUpperCase(word.charAt(i)));
+
+			IToken token= fUppercaseWords.get(fBuffer);
+			if (token != null)
+				return token;
+			return Token.UNDEFINED;
+		}
+
+		/**
+		 * Enables/disables the case-sensitivity of the task tag detection.
+		 *
+		 * @param caseSensitive <code>true</code> iff case-sensitivity should be enabled
+		 * @since 3.0
+		 */
+		public void setCaseSensitive(boolean caseSensitive) {
+			fCaseSensitive= caseSensitive;
+		}
+	}
+	
+	private static class AtJavaIdentifierDetector implements IWordDetector {
+
+		public boolean isWordStart(char c) {
+			return c == '@' || Character.isJavaIdentifierStart(c);
+		}
+
+		public boolean isWordPart(char c) {
+			return c == '.' || Character.isJavaIdentifierPart(c);
+		}
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaDocScanner.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaDocScanner.java
new file mode 100644
index 0000000..a323eb3
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaDocScanner.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+
+public class JavaDocScanner extends JavaCommentScanner {
+	private static String[] fgTokenProperties= {
+		IJavaColorConstants.JAVADOC_KEYWORD,
+		IJavaColorConstants.JAVADOC_TAG,
+		IJavaColorConstants.JAVADOC_LINK,
+		IJavaColorConstants.JAVADOC_DEFAULT,
+		TASK_TAG
+	};
+
+
+	public JavaDocScanner() {
+		super(IJavaColorConstants.JAVADOC_DEFAULT, fgTokenProperties);
+	}
+	
+	public IDocument getDocument() {
+		return fDocument;
+	}
+
+	@Override
+	protected List<IRule> createRules() {
+
+		List<IRule> list= new ArrayList<IRule>();
+
+		// Add rule for tags
+		Token token= getToken(IJavaColorConstants.JAVADOC_TAG);
+		list.add(new TagRule(token));
+
+
+		// Add rule for HTML comments
+		WordRule wordRule= new WordRule(new HTMLCommentDetector(), token);
+		wordRule.addWord("<!--", token); //$NON-NLS-1$
+		wordRule.addWord("--!>", token); //$NON-NLS-1$
+		list.add(wordRule);
+
+
+		// Add rules for links
+		token= getToken(IJavaColorConstants.JAVADOC_LINK);
+		list.add(new MultiLineRule("{@link", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
+		list.add(new MultiLineRule("{@value", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
+		list.add(new MultiLineRule("{@inheritDoc", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
+
+		// Add rules for @code and @literals
+		token= getToken(IJavaColorConstants.JAVADOC_DEFAULT);
+		list.add(new MultiLineRule("{@code", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
+		list.add(new MultiLineRule("{@literal", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
+
+		// Add generic whitespace rule
+		token= getToken(IJavaColorConstants.JAVADOC_DEFAULT);
+		list.add(new WhitespaceRule(new JavaWhitespaceDetector(), token));
+
+
+		list.addAll(super.createRules());
+		return list;
+	}
+	
+	class TagRule extends SingleLineRule {
+
+		/*
+		 * @see SingleLineRule
+		 */
+		public TagRule(IToken token) {
+			super("<", ">", token, (char) 0); //$NON-NLS-2$ //$NON-NLS-1$
+		}
+
+		/*
+		 * @see SingleLineRule
+		 */
+		public TagRule(IToken token, char escapeCharacter) {
+			super("<", ">", token, escapeCharacter); //$NON-NLS-2$ //$NON-NLS-1$
+		}
+
+		private IToken evaluateToken() {
+			try {
+				final String token= getDocument().get(getTokenOffset(), getTokenLength()) + "."; //$NON-NLS-1$
+
+				int offset= 0;
+				char character= token.charAt(++offset);
+
+				if (character == '/')
+					character= token.charAt(++offset);
+
+				while (Character.isWhitespace(character))
+					character= token.charAt(++offset);
+
+				while (Character.isLetterOrDigit(character))
+					character= token.charAt(++offset);
+
+				while (Character.isWhitespace(character))
+					character= token.charAt(++offset);
+
+				if (offset >= 2 && token.charAt(offset) == fEndSequence[0])
+					return fToken;
+
+			} catch (BadLocationException exception) {
+				// Do nothing
+			}
+			return getToken(IJavaColorConstants.JAVADOC_DEFAULT);
+		}
+
+		/*
+		 * @see PatternRule#evaluate(ICharacterScanner)
+		 */
+		@Override
+		public IToken evaluate(ICharacterScanner scanner) {
+			IToken result= super.evaluate(scanner);
+			if (result == fToken)
+				return evaluateToken();
+			return result;
+		}
+	}
+	
+	static class HTMLCommentDetector implements IWordDetector {
+
+		/**
+		 * @see IWordDetector#isWordStart(char)
+		 */
+		public boolean isWordStart(char c) {
+			return (c == '<' || c == '-');
+		}
+
+		/**
+		 * @see IWordDetector#isWordPart(char)
+		 */
+		public boolean isWordPart(char c) {
+			return (c == '-' || c == '!' || c == '>');
+		}
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaSourceConfiguration.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaSourceConfiguration.java
new file mode 100644
index 0000000..6da169b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaSourceConfiguration.java
@@ -0,0 +1,237 @@
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.eclipse.fx.ui.controls.styledtext.StyleRange;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.ITokenScanner;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationPainter;
+import org.eclipse.jface.text.source.AnnotationPainter.ITextStyleStrategy;
+import org.eclipse.jface.text.source.AnnotationPresenter;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+
+public class JavaSourceConfiguration extends SourceViewerConfiguration {
+
+	private JavaCodeScanner fCodeScanner;
+	private JavaDocScanner fJavaDocScanner;
+	private JavaCommentScanner fMultilineCommentScanner;
+	private JavaCommentScanner fSinglelineCommentScanner;
+	private SingleTokenJavaScanner fStringScanner;
+//	private final Optional<ProposalComputer> computer;
+//	private Input<?> input;
+	private IAnnotationModel annotationModel;
+	private List<AnnotationPresenter> annotationPresenters;
+
+	public JavaSourceConfiguration() {
+		this(null,null);
+	}
+			
+	
+	public JavaSourceConfiguration(
+//			Input<?> input,
+//			ProposalComputer computer,
+			IAnnotationModel annotationModel,
+			List<AnnotationPresenter> annotationPresenters) {
+//		this.computer = Optional.ofNullable(computer);
+		this.annotationModel = annotationModel;
+//		this.input = input;
+		this.annotationPresenters = annotationPresenters;
+		initializeScanners();
+	}
+
+	@Override
+	public IAnnotationModel getAnnotationModel() {
+		return annotationModel;
+	}
+
+	private void initializeScanners() {
+		fCodeScanner= new JavaCodeScanner();
+		fMultilineCommentScanner= new JavaCommentScanner(IJavaColorConstants.JAVA_MULTI_LINE_COMMENT);
+		fSinglelineCommentScanner= new JavaCommentScanner(IJavaColorConstants.JAVA_SINGLE_LINE_COMMENT);
+		fStringScanner= new SingleTokenJavaScanner(IJavaColorConstants.JAVA_STRING);
+		fJavaDocScanner= new JavaDocScanner();
+	}
+
+	@Override
+	public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) {
+		return IJavaPartitions.JAVA_PARTITIONING;
+	}
+
+	@Override
+	public IContentAssistant getContentAssist() {
+//		if( computer.isPresent() ) {
+//			return new ContentAssistant(this::computeProposals);
+//		}
+		return super.getContentAssist();
+	}
+
+//	private List<ICompletionProposal> computeProposals(Integer offset) {
+//		Future<List<ICompletionProposal>> computedProposals = computer.get().compute(new ProposalContext(input, offset));
+//		try {
+//			return computedProposals.get();
+//		} catch (InterruptedException | ExecutionException e) {
+//			// TODO Auto-generated catch block
+//			e.printStackTrace();
+//		}
+//		return Collections.emptyList();
+//	}
+
+	@Override
+	public IPresentationReconciler getPresentationReconciler(
+			ISourceViewer sourceViewer) {
+		PresentationReconciler reconciler= new /*JavaPresentationReconciler*/ PresentationReconciler();
+		reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+		DefaultDamagerRepairer dr= new DefaultDamagerRepairer(getCodeScanner());
+		reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+		reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+		dr= new DefaultDamagerRepairer(getJavaDocScanner());
+		reconciler.setDamager(dr, IJavaPartitions.JAVA_DOC);
+		reconciler.setRepairer(dr, IJavaPartitions.JAVA_DOC);
+
+		dr= new DefaultDamagerRepairer(getMultilineCommentScanner());
+		reconciler.setDamager(dr, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
+		reconciler.setRepairer(dr, IJavaPartitions.JAVA_MULTI_LINE_COMMENT);
+
+		dr= new DefaultDamagerRepairer(getSinglelineCommentScanner());
+		reconciler.setDamager(dr, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
+		reconciler.setRepairer(dr, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT);
+
+		dr= new DefaultDamagerRepairer(getStringScanner());
+		reconciler.setDamager(dr, IJavaPartitions.JAVA_STRING);
+		reconciler.setRepairer(dr, IJavaPartitions.JAVA_STRING);
+
+		dr= new DefaultDamagerRepairer(getStringScanner());
+		reconciler.setDamager(dr, IJavaPartitions.JAVA_CHARACTER);
+		reconciler.setRepairer(dr, IJavaPartitions.JAVA_CHARACTER);
+
+		return reconciler;
+	}
+
+	private ITokenScanner getStringScanner() {
+		return fStringScanner;
+	}
+
+	private ITokenScanner getSinglelineCommentScanner() {
+		return fSinglelineCommentScanner;
+	}
+
+	private ITokenScanner getMultilineCommentScanner() {
+		return fMultilineCommentScanner;
+	}
+
+	private ITokenScanner getJavaDocScanner() {
+		return fJavaDocScanner;
+	}
+
+	private ITokenScanner getCodeScanner() {
+		return fCodeScanner;
+	}
+
+	@Override
+	public String getStyleclassName() {
+		return "java";
+	}
+	
+	@Override
+	public List<AnnotationPresenter> getAnnotationPresenters() {
+		return annotationPresenters;
+	}
+
+	private static final ITextStyleStrategy PROBLEM_UNDERLINE = new ITextStyleStrategy() {
+
+		@Override
+		public void applyTextStyle(StyleRange styleRange, String annotationColor) {
+			System.err.println("=======> Applying on" + annotationColor);
+		}
+	};
+
+	@Override
+	public AnnotationPainter getAnnotationPainter(ISourceViewer sourceViewer) {
+		AnnotationPainter painter = new AnnotationPainter(sourceViewer, new AnnotationAccess());
+		painter.addTextStyleStrategy("PROBLEM_UNDERLINE", PROBLEM_UNDERLINE);
+		painter.addAnnotationType("PROBLEM_UNDERLINE", "PROBLEM_UNDERLINE");
+		painter.setAnnotationTypeColor("jdt.annotation.WARNING", "jdt_warning");
+		painter.setAnnotationTypeColor("jdt.annotation.TASK", "jdt_task");
+		painter.setAnnotationTypeColor("jdt.annotation.ERROR", "jdt_error");
+
+//		painter.addTextStyleStrategy(AnnotationPreference.STYLE_SQUIGGLES, fgSquigglesStrategy);
+//		painter.addTextStyleStrategy(AnnotationPreference.STYLE_PROBLEM_UNDERLINE, fgProblemUnderlineStrategy);
+//		painter.addTextStyleStrategy(AnnotationPreference.STYLE_BOX, fgBoxStrategy);
+//		painter.addTextStyleStrategy(AnnotationPreference.STYLE_DASHED_BOX, fgDashedBoxStrategy);
+//		painter.addTextStyleStrategy(AnnotationPreference.STYLE_UNDERLINE, fgUnderlineStrategy);
+
+//		return painter;
+		return null;
+	}
+
+	static class AnnotationAccess implements IAnnotationAccess, IAnnotationAccessExtension {
+
+		@Override
+		public String getTypeLabel(Annotation annotation) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public int getLayer(Annotation annotation) {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public boolean isPaintable(Annotation annotation) {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public boolean isSubtype(Object annotationType,
+				Object potentialSupertype) {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public Object[] getSupertypes(Object annotationType) {
+			System.err.println("THE ANNOTATION TYPE: " + annotationType);
+			return new Object[] { "PROBLEM_UNDERLINE" };
+		}
+
+		@Override
+		public Object getType(Annotation annotation) {
+			System.err.println("Extrac type: " + annotation);
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public boolean isMultiLine(Annotation annotation) {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public boolean isTemporary(Annotation annotation) {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWhitespaceDetector.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWhitespaceDetector.java
new file mode 100644
index 0000000..65c8bdb
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWhitespaceDetector.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+
+
+/**
+ * A java aware white space detector.
+ */
+public class JavaWhitespaceDetector implements IWhitespaceDetector {
+
+	public boolean isWhitespace(char c) {
+		return Character.isWhitespace(c);
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWordDetector.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWordDetector.java
new file mode 100644
index 0000000..54e63f6
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWordDetector.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+
+import org.eclipse.jface.text.rules.IWordDetector;
+
+/**
+ * A Java aware word detector.
+ */
+public class JavaWordDetector implements IWordDetector {
+
+	/*
+	 * @see IWordDetector#isWordStart
+	 */
+	public boolean isWordStart(char c) {
+		return Character.isJavaIdentifierStart(c);
+	}
+
+	/*
+	 * @see IWordDetector#isWordPart
+	 */
+	public boolean isWordPart(char c) {
+		return Character.isJavaIdentifierPart(c);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/SingleTokenJavaScanner.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/SingleTokenJavaScanner.java
new file mode 100644
index 0000000..87ca700
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/SingleTokenJavaScanner.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.xtext.sample.editor.java.text;
+
+import java.util.List;
+
+import org.eclipse.jface.text.rules.IRule;
+
+public class SingleTokenJavaScanner extends AbstractJavaScanner{
+	private String[] fProperty;
+
+	public SingleTokenJavaScanner(String property) {
+		super();
+		fProperty= new String[] { property };
+		initialize();
+	}
+	
+	@Override
+	protected List<IRule> createRules() {
+		setDefaultReturnToken(getToken(fProperty[0]));
+		return null;
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/SampleStatemachineCode.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/SampleStatemachineCode.java
new file mode 100644
index 0000000..1888b0d
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/SampleStatemachineCode.java
@@ -0,0 +1,73 @@
+package org.eclipse.fx.xtext.sample.editor.statemachine;
+
+import java.io.File;
+
+import org.eclipse.fx.xtext.sample.editor.Util;
+import org.eclipse.fx.xtext.statemachine.fx.text.IStatemachinePartitions;
+import org.eclipse.fx.xtext.statemachine.fx.text.StatemachinePartitionScanner;
+import org.eclipse.fx.xtext.statemachine.fx.text.StatemachineSourceConfiguration;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.jface.text.source.SourceViewer;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.HBox;
+import javafx.stage.Stage;
+
+public class SampleStatemachineCode extends Application {
+	private final static String[] LEGAL_CONTENT_TYPES = new String[] {
+		IStatemachinePartitions.MULTI_LINE_COMMENT
+	};
+	
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane container = new BorderPane();
+		
+		HBox b = new HBox(10);
+		
+		{
+			Button bright = new Button("Bright");
+			b.getChildren().add(bright);
+			bright.setOnAction(e -> bright.getScene().getStylesheets()
+					.setAll(getClass().getResource("bright.css").toExternalForm()));
+		}
+
+		{
+			Button dark = new Button("Dark");
+			b.getChildren().add(dark);
+			dark.setOnAction(
+					e -> dark.getScene().getStylesheets().setAll(getClass().getResource("dark.css").toExternalForm()));
+		}
+
+		container.setTop(b);
+		
+		Document document = new Document();
+		document.set(Util.getFileContent(getClass().getClassLoader().getResource("StateSample.state").toURI()));
+
+		StatemachineSourceConfiguration configuration = new StatemachineSourceConfiguration(document, new File("/Users/tomschindl/Documents/e-workspaces/efxclipse_xtext/org.eclipse.fx.xtext.sample.editor/src/StateSample.state"));
+
+		SourceViewer viewer = new SourceViewer();
+		
+		FastPartitioner partitioner = new FastPartitioner(new StatemachinePartitionScanner(), LEGAL_CONTENT_TYPES);
+		document.setDocumentPartitioner(configuration.getConfiguredDocumentPartitioning(viewer), partitioner);
+//		document.setDocumentPartitioner(partitioner);
+		partitioner.connect(document);
+		
+		viewer.configure(configuration);
+		viewer.setDocument(document);
+		container.setCenter(viewer.getTextWidget());
+		Scene s = new Scene(container);
+		s.getStylesheets().add(getClass().getResource("bright.css").toExternalForm());
+		primaryStage.setScene(s);
+		primaryStage.show();
+		System.err.println(viewer.getTextWidget().getStyleRanges(0, document.getLength(), true).length);
+	}
+
+	public static void main(String[] args) {
+		launch(args);
+		System.exit(0);
+	}
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/bright.css b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/bright.css
new file mode 100644
index 0000000..a4130dc
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/bright.css
@@ -0,0 +1,42 @@
+.root {
+    /* @SuppressWarning */
+    -compensator-default-text: -fx-text-background-color;
+	/* @SuppressWarning */
+    -compensator-extra1: /*#957d47*/ derive(-fx-text-background-color, 110%);
+	-fx-font-size: 1em;
+}
+
+.cell-text-extra {
+	-fx-fill: -compensator-extra1;
+}
+
+.cell-text-default {
+	-fx-fill: -compensator-default-text;
+}
+
+.styled-text-area .list-view {
+	-fx-background-color: white;
+}
+
+.state.styled-text-area .state_default {
+	-styled-text-color: rgb(0,0,0);
+}
+
+.state.styled-text-area .state_keyword {
+	-styled-text-color: rgb(127, 0, 85);
+	-fx-font-weight: bold;
+}
+
+.state.styled-text-area .state_doc_default {
+	-styled-text-color: rgb(63, 127, 95);
+}
+
+
+
+.state-default-string {
+	-fx-fill: -compensator-default-text;
+}
+
+.state-type-info {
+	-fx-fill: -compensator-extra1;
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/dark.css b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/dark.css
new file mode 100644
index 0000000..1213027
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/dark.css
@@ -0,0 +1,66 @@
+.root {
+    -fx-base: #4d5052;
+    -fx-background: #4d5052;
+    -fx-control-inner-background: #4d5052;
+    -fx-text-base-color: #c7c7c7;
+    /* @SuppressWarning */
+    -compensator-default-text: -fx-text-background-color;
+	/* @SuppressWarning */
+    -compensator-extra1: /*#957d47*/ derive(-fx-text-background-color, -30%);
+}
+
+.cell-text-extra {
+	-fx-fill: -compensator-extra1;
+}
+
+.cell-text-default {
+	-fx-fill: -compensator-default-text;
+}
+
+.styled-text-area .list-view {
+	-fx-background-color: #393939;
+}
+
+.styled-text-area .list-cell:filled:focused:selected {
+	-fx-background-color: #414141;
+}
+
+.styled-text-area .line-ruler-text {
+	-fx-text-fill: #c7c7c7;
+}
+
+.styled-text-area .text-caret {
+	-fx-fill: #c7c7c7;
+	-fx-stroke: #c7c7c7;
+}
+
+.state.styled-text-area .selection-marker {
+	-fx-background-color: #2b5696;
+}
+
+
+
+
+
+
+.state.styled-text-area .state_default {
+	-styled-text-color: #b8c4d1;
+}
+
+.state.styled-text-area .state_keyword {
+	-styled-text-color: #d78b40;
+	-fx-font-weight: bold;
+}
+
+.state.styled-text-area .state_doc_default {
+	-styled-text-color: #929292;
+}
+
+
+.state-default-string {
+	-fx-fill: -compensator-default-text;
+}
+
+.state-type-info {
+	-fx-fill: -compensator-extra1;
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/MySample.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/MySample.java
new file mode 100644
index 0000000..2ebd726
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/MySample.java
@@ -0,0 +1,10 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+/*
+ * This is a multiline comment
+ */
+public class MySample {
+	public void main(String[] args) {
+		System.err.println("Hello World!");
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleLabel.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleLabel.java
new file mode 100644
index 0000000..b21a1ce
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleLabel.java
@@ -0,0 +1,26 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.control.Label;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.text.Font;
+import javafx.stage.Stage;
+
+public class SampleLabel extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		
+		Label l = new Label("I'm a Label with 20pt");
+		l.setFont(Font.font(20));
+		p.setCenter(l);
+		primaryStage.setScene(new Scene(p));
+		primaryStage.show();
+	}
+
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledLabel.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledLabel.java
new file mode 100644
index 0000000..90a0bc9
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledLabel.java
@@ -0,0 +1,34 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import org.eclipse.fx.ui.controls.styledtext.StyledLabel;
+import org.eclipse.fx.ui.controls.styledtext.StyledString;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.stage.Stage;
+
+public class SampleStyledLabel extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		
+		StyledString ss = new StyledString();
+		ss.appendSegment("Styled", "h1");
+		ss.appendSegment("Label", "h1","colorful");
+		
+		StyledLabel l = new StyledLabel(ss);
+		p.setCenter(l);
+		
+		Scene s = new Scene(p);
+		s.getStylesheets().add(getClass().getResource("styled-string.css").toExternalForm());
+		
+		primaryStage.setScene(s);
+		primaryStage.show();
+	}
+
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledString.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledString.java
new file mode 100644
index 0000000..7f0e5f1
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledString.java
@@ -0,0 +1,33 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import org.eclipse.fx.ui.controls.Util;
+import org.eclipse.fx.ui.controls.styledtext.StyledString;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.stage.Stage;
+
+public class SampleStyledString extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		
+		StyledString ss = new StyledString();
+		ss.appendSegment("Styled", "h1");
+		ss.appendSegment("String", "h1","colorful");
+		
+		p.setCenter(Util.toNode(ss));
+		
+		Scene s = new Scene(p);
+		s.getStylesheets().add(getClass().getResource("styled-string.css").toExternalForm());
+		
+		primaryStage.setScene(s);
+		primaryStage.show();
+	}
+	
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledTextArea.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledTextArea.java
new file mode 100644
index 0000000..bfecfb5
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledTextArea.java
@@ -0,0 +1,36 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import org.eclipse.fx.ui.controls.styledtext.StyleRange;
+import org.eclipse.fx.ui.controls.styledtext.StyledTextArea;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.stage.Stage;
+
+public class SampleStyledTextArea extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		
+		StyledTextArea a = new StyledTextArea();
+		a.getContent().setText("public class Sample {\n\n}");
+		a.setStyleRanges(
+				new StyleRange("keyword", 0, "public".length(), null, null),
+				new StyleRange("keyword", "public".length()+1, "class".length(), null, null)
+				);
+		a.setLineRulerVisible(true);
+		p.setCenter(a);
+		
+		Scene s = new Scene(p);
+		s.getStylesheets().add(getClass().getResource("styled-text.css").toExternalForm());
+		
+		primaryStage.setScene(s);
+		primaryStage.show();
+	}
+
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextArea.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextArea.java
new file mode 100644
index 0000000..6c1b355
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextArea.java
@@ -0,0 +1,30 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.BorderPane;
+import javafx.stage.Stage;
+
+public class SampleTextArea extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		
+		TextArea t = new TextArea();
+		StringBuilder b = new StringBuilder();
+		b.append("This is a multiline text\n");
+		b.append("This is a multiline text\n");
+		b.append("This is a multiline text\n");
+		t.setText(b.toString());
+		p.setCenter(t);
+		
+		primaryStage.setScene(new Scene(p));
+		primaryStage.show();
+	}
+
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextField.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextField.java
new file mode 100644
index 0000000..3b22d09
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextField.java
@@ -0,0 +1,25 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.BorderPane;
+import javafx.stage.Stage;
+
+public class SampleTextField extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		
+		TextField f = new TextField("I'm a text field");
+		p.setCenter(f);
+		
+		primaryStage.setScene(new Scene(p));
+		primaryStage.show();
+	}
+
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextFlow.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextFlow.java
new file mode 100644
index 0000000..3dae506
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextFlow.java
@@ -0,0 +1,37 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import javafx.scene.text.Text;
+import javafx.scene.text.TextFlow;
+import javafx.stage.Stage;
+
+public class SampleTextFlow extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		
+		TextFlow f = new TextFlow();
+		
+		Text t1 = new Text("I'm black 12pt");
+		t1.setFont(Font.font(12));
+		f.getChildren().add(t1);
+		
+		Text t2 = new Text("I'm red 20pt");
+		t2.setFont(Font.font(20));
+		t2.setFill(Color.RED);
+		f.getChildren().add(t2);
+		
+		p.setCenter(f);
+		primaryStage.setScene(new Scene(p));
+		primaryStage.show();
+	}
+
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextNode.java b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextNode.java
new file mode 100644
index 0000000..c69f06a
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextNode.java
@@ -0,0 +1,25 @@
+package org.eclipse.fx.xtext.sample.editor.text;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.text.Font;
+import javafx.scene.text.Text;
+import javafx.stage.Stage;
+
+public class SampleTextNode extends Application {
+
+	@Override
+	public void start(Stage primaryStage) throws Exception {
+		BorderPane p = new BorderPane();
+		Text t = new Text("I'm a text with font-size 20");
+		t.setFont(Font.font(20));
+		p.setCenter(t);
+		primaryStage.setScene(new Scene(p));
+		primaryStage.show();
+	}
+	
+	public static void main(String[] args) {
+		launch(args);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-string.css b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-string.css
new file mode 100644
index 0000000..2c38ecb
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-string.css
@@ -0,0 +1,8 @@
+.h1 {
+	-fx-font-size: 20pt;
+}
+
+.colorful {
+	-fx-font-weight: bold;
+	-fx-fill: linear-gradient( from 0.0% 0.0% to 100.0% 100.0%, rgb(128,179,128) 0.0, rgb(255,179,102) 100.0);
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-text.css b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-text.css
new file mode 100644
index 0000000..cb8036e
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-text.css
@@ -0,0 +1,4 @@
+.keyword {
+	-styled-text-color: rgb(127, 0, 85);
+	-fx-font-weight: bold;
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/.classpath b/demos/org.eclipse.fx.xtext.statemachine.fx/.classpath
new file mode 100644
index 0000000..0805795
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="xtend-gen"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/.gitignore b/demos/org.eclipse.fx.xtext.statemachine.fx/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/.project b/demos/org.eclipse.fx.xtext.statemachine.fx/.project
new file mode 100644
index 0000000..a73c6d0
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.fx.xtext.statemachine.fx</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<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>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+	</natures>
+</projectDescription>
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/.settings/org.eclipse.jdt.core.prefs b/demos/org.eclipse.fx.xtext.statemachine.fx/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/META-INF/MANIFEST.MF b/demos/org.eclipse.fx.xtext.statemachine.fx/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..00f51ab
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0

+Bundle-ManifestVersion: 2

+Bundle-Name: Fx

+Bundle-SymbolicName: org.eclipse.fx.xtext.statemachine.fx

+Bundle-Version: 1.0.0.qualifier

+Bundle-RequiredExecutionEnvironment: JavaSE-1.8

+Require-Bundle: org.eclipse.text,

+ org.eclipse.fx.text;bundle-version="1.0.0",

+ org.eclipse.fx.text.ui;bundle-version="1.0.0",

+ org.eclipse.xtext,

+ com.google.guava,

+ org.eclipse.xtext.xbase.lib,

+ org.eclipse.xtend.lib,

+ org.eclipse.xtend.lib.macro,

+ org.eclipse.xtext.ide;bundle-version="2.9.0",

+ org.eclipse.fx.xtext.statemachine.ide;bundle-version="1.0.0",

+ org.eclipse.fx.xtext.statemachine,

+ org.eclipse.fx.ui.controls

+Export-Package: org.eclipse.fx.xtext.statemachine.fx.text

+

diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/build.properties b/demos/org.eclipse.fx.xtext.statemachine.fx/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/ContentAssistProvider.java b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/ContentAssistProvider.java
new file mode 100644
index 0000000..3741663
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/ContentAssistProvider.java
@@ -0,0 +1,143 @@
+package org.eclipse.fx.xtext.statemachine.fx.contentassist;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.fx.ui.controls.styledtext.StyledString;
+import org.eclipse.jface.text.contentassist.CompletetionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.xtext.AbstractElement;
+import org.eclipse.xtext.Assignment;
+import org.eclipse.xtext.CrossReference;
+import org.eclipse.xtext.GrammarUtil;
+import org.eclipse.xtext.Keyword;
+import org.eclipse.xtext.RuleCall;
+import org.eclipse.xtext.TerminalRule;
+import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.ContentAssistContextFactory;
+import org.eclipse.xtext.resource.IEObjectDescription;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.resource.XtextResourceSet;
+import org.eclipse.xtext.scoping.IScope;
+import org.eclipse.xtext.scoping.IScopeProvider;
+import org.eclipse.xtext.util.TextRegion;
+import org.eclipse.xtext.xtext.CurrentTypeFinder;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import javafx.scene.Node;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+
+@Singleton
+public class ContentAssistProvider {
+	@Inject
+	Provider<ContentAssistContextFactory> contextFactoryProvider;
+	@Inject
+	Provider<XtextResourceSet> resourceSetProvider;
+	@Inject
+	ExecutorService pool;
+	@Inject
+	IScopeProvider scopeProvider;
+	@Inject
+	CurrentTypeFinder typeFinder;
+	
+	private Image referenceImage;
+	
+	public ContentAssistProvider() {
+		referenceImage = new Image(getClass().getResource("field_public_obj.png").toExternalForm());
+	}
+
+	@SuppressWarnings("restriction")
+	public List<ICompletionProposal> doContentAssist(String content, String uri, Integer offset) {
+		ContentAssistContextFactory contextFactory = contextFactoryProvider.get();
+		XtextResourceSet xtextResourceSet = resourceSetProvider.get();
+
+		XtextResource resource = (XtextResource) xtextResourceSet.getResource(URI.createURI(uri), true);
+		contextFactory.setPool(pool);
+		ContentAssistContext[] contexts = contextFactory.create(content, new TextRegion(0, 0), offset, resource);
+
+		List<ICompletionProposal> proposal = new ArrayList<>();
+		for (int i = 0; i < contexts.length; i++) {
+			for (AbstractElement abstractElement : contexts[i].getFirstSetGrammarElements()) {
+				createProposals(contexts[i], abstractElement, offset, proposal);
+			}
+		}
+
+		return proposal;
+	}
+
+	private void createProposals(ContentAssistContext context, AbstractElement abstractElement, int offset,
+			List<ICompletionProposal> proposal) {
+		if (abstractElement instanceof Assignment) {
+			Assignment assignment = (Assignment) abstractElement;
+			if (assignment.getTerminal() instanceof CrossReference) {
+				createProposals(context, assignment.getTerminal(), offset, proposal);
+			}
+		} else if (abstractElement instanceof RuleCall) {
+			RuleCall ruleCall = (RuleCall) abstractElement;
+			if (ruleCall.getRule() instanceof TerminalRule && context.getPrefix().isEmpty()) {
+				if (ruleCall.getRule().getName().equals("STRING")) {
+					// val container = ruleCall.eContainer
+					// if (container instanceof Assignment) {
+					// proposal = '"' + container.feature + '"'
+					// description = ruleCall.rule.name
+					// } else {
+					// proposal = '"' + ruleCall.rule.name + '"'
+					// }
+					// editPositions += new
+					// ContentAssistResult.EditPosition(context.offset + 1,
+					// proposal.length - 2)
+				} else {
+					EObject container = ruleCall.eContainer();
+					if (container instanceof Assignment) {
+						proposal.add(new CompletetionProposal(((Assignment) container).getFeature(), offset, 0,
+								ruleCall.getRule().getName(), () -> null));
+					} else {
+						proposal.add(new CompletetionProposal(ruleCall.getRule().getName(), offset, 0,
+								ruleCall.getRule().getName(), () -> null));
+					}
+					// editPositions += new
+					// ContentAssistResult.EditPosition(context.offset,
+					// proposal.length)
+				}
+			}
+		} else if (abstractElement instanceof Keyword) {
+			Keyword w = (Keyword) abstractElement;
+			proposal.add(new CompletetionProposal(w.getValue(), offset, 0, w.getValue(), () -> null));
+		} else if (abstractElement instanceof CrossReference) {
+			CrossReference reference = (CrossReference) abstractElement;
+			EClassifier type = typeFinder.findCurrentTypeAfter(reference);
+			if (type instanceof EClass) {
+				EReference ereference = GrammarUtil.getReference(reference, (EClass) type);
+				if (ereference != null) {
+					IScope scope = scopeProvider.getScope(context.getCurrentModel(), ereference);
+					try {
+						for (IEObjectDescription description : scope.getAllElements()) {
+							String elementName = description.getName().toString();
+							if (elementName.startsWith(context.getPrefix())) {
+								StyledString s = new StyledString();
+								s.appendSegment(elementName + " - ", "state-default-string");
+								s.appendSegment(description.getEClass().getName(), "state-type-info");
+								proposal.add(new CompletetionProposal(elementName, offset,
+										0, s, () -> new ImageView(referenceImage)));
+							}
+						}
+					} catch (UnsupportedOperationException uoe) {
+						// LOG.error('Failed to create content assist proposals
+						// for cross-reference.', uoe)
+					}
+				}
+			}
+		}
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/field_public_obj.png b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/field_public_obj.png
new file mode 100644
index 0000000..56b3e59
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/field_public_obj.png
Binary files differ
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/internal/StatemachineFXModule.xtend b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/internal/StatemachineFXModule.xtend
new file mode 100644
index 0000000..da7d9cc
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/internal/StatemachineFXModule.xtend
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2015 itemis AG (http://www.itemis.eu) 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
+ *******************************************************************************/
+package org.eclipse.fx.xtext.statemachine.fx.internal
+
+import com.google.inject.Binder
+import com.google.inject.name.Names
+import org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.StatemachineParser
+import org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal.InternalStatemachineLexer
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.xtext.ide.LexerIdeBindings
+import org.eclipse.xtext.ide.editor.contentassist.antlr.IContentAssistParser
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.Lexer
+import org.eclipse.xtext.service.AbstractGenericModule
+import java.util.concurrent.ExecutorService
+import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
+
+@Accessors
+@FinalFieldsConstructor
+class StatemachineFXModule extends AbstractGenericModule {
+	
+	val ExecutorService executorService
+	
+	def configureExecutorService(Binder binder) {
+		binder.bind(ExecutorService).toInstance(executorService)
+	}
+	
+	def configureContentAssistLexer(Binder binder) {
+		binder.bind(Lexer).annotatedWith(Names.named(LexerIdeBindings.CONTENT_ASSIST)).to(InternalStatemachineLexer)
+	}
+	
+	def Class<? extends IContentAssistParser> bindIContentAssistParser() {
+		StatemachineParser
+	}
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/IStatemachinePartitions.java b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/IStatemachinePartitions.java
new file mode 100644
index 0000000..565a626
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/IStatemachinePartitions.java
@@ -0,0 +1,5 @@
+package org.eclipse.fx.xtext.statemachine.fx.text;
+
+public interface IStatemachinePartitions {
+	public static String MULTI_LINE_COMMENT = "__statemachine_multiline_comment";
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineCodeScanner.java b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineCodeScanner.java
new file mode 100644
index 0000000..892bbb0
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineCodeScanner.java
@@ -0,0 +1,49 @@
+package org.eclipse.fx.xtext.statemachine.fx.text;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.CombinedWordRule;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.source.JavaLikeWordDetector;
+
+public class StatemachineCodeScanner extends RuleBasedScanner {
+	public StatemachineCodeScanner() {
+		Token keywordToken = new Token(new TextAttribute("state_keyword"));
+		Token defaultToken = new Token(new TextAttribute("state_default"));
+		
+		setDefaultReturnToken(defaultToken);
+		
+		IRule[] rules = new IRule[1];
+		
+		// Keyword rules
+		JavaLikeWordDetector wordDetector= new JavaLikeWordDetector();
+		CombinedWordRule combinedWordRule= new CombinedWordRule(wordDetector, defaultToken) {
+			@Override
+			public IToken evaluate(ICharacterScanner scanner) {
+				IToken evaluate = super.evaluate(scanner);
+				return evaluate;
+			}
+		};
+		
+		CombinedWordRule.WordMatcher wordRule= new CombinedWordRule.WordMatcher();
+		wordRule.addWord("signal", keywordToken);
+		wordRule.addWord("input", keywordToken);
+		wordRule.addWord("output", keywordToken);
+		wordRule.addWord("state", keywordToken);
+		wordRule.addWord("end", keywordToken);
+		wordRule.addWord("if", keywordToken);
+		wordRule.addWord("goto", keywordToken);
+		wordRule.addWord("and", keywordToken);
+		wordRule.addWord("set", keywordToken);
+		wordRule.addWord("true", keywordToken);
+		wordRule.addWord("false", keywordToken);
+		
+		combinedWordRule.addWordMatcher(wordRule);
+		rules[0] = combinedWordRule;
+		setRules(rules);
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineDocScanner.java b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineDocScanner.java
new file mode 100644
index 0000000..95850a5
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineDocScanner.java
@@ -0,0 +1,11 @@
+package org.eclipse.fx.xtext.statemachine.fx.text;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.Token;
+
+public class StatemachineDocScanner extends RuleBasedScanner {
+	public StatemachineDocScanner() {
+		setDefaultReturnToken(new Token(new TextAttribute("state_doc_default")));
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachinePartitionScanner.java b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachinePartitionScanner.java
new file mode 100644
index 0000000..73a3dd2
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachinePartitionScanner.java
@@ -0,0 +1,15 @@
+package org.eclipse.fx.xtext.statemachine.fx.text;
+
+import org.eclipse.jface.text.rules.IPredicateRule;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
+import org.eclipse.jface.text.rules.Token;
+
+public class StatemachinePartitionScanner extends RuleBasedPartitionScanner {
+	public StatemachinePartitionScanner() {
+		IPredicateRule[] pr = new IPredicateRule[1];
+		pr[0] = new MultiLineRule("/*", "*/", new Token(IStatemachinePartitions.MULTI_LINE_COMMENT), (char)0, false);
+		
+		setPredicateRules(pr);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineSourceConfiguration.java b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineSourceConfiguration.java
new file mode 100644
index 0000000..a3d08cf
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineSourceConfiguration.java
@@ -0,0 +1,83 @@
+package org.eclipse.fx.xtext.statemachine.fx.text;
+
+import java.io.File;
+import java.util.List;
+import java.util.concurrent.Executors;
+
+import org.eclipse.fx.xtext.statemachine.StatemachineRuntimeModule;
+import org.eclipse.fx.xtext.statemachine.StatemachineStandaloneSetup;
+import org.eclipse.fx.xtext.statemachine.fx.contentassist.ContentAssistProvider;
+import org.eclipse.fx.xtext.statemachine.fx.internal.StatemachineFXModule;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+
+public class StatemachineSourceConfiguration extends SourceViewerConfiguration {
+	static Injector injector;
+	private ContentAssistProvider contentAssistProvider;
+	
+	static {
+		injector = new StatemachineStandaloneSetup() {
+			public Injector createInjector() {
+				StatemachineRuntimeModule runtimeModule = new StatemachineRuntimeModule();
+				StatemachineFXModule webModule = new StatemachineFXModule(Executors.newFixedThreadPool(3));
+//				webModule.resourceBaseProvider = resourceBaseProvider
+				return Guice.createInjector((Module)runtimeModule, webModule);
+				
+			}
+		}.createInjectorAndDoEMFRegistration();
+	}
+	
+	private Document doc;
+	private File f;
+	
+	public StatemachineSourceConfiguration(Document doc, File f) {
+		this.doc = doc;
+		this.f = f;
+		contentAssistProvider = injector.getInstance(ContentAssistProvider.class);
+	}
+	
+	@Override
+	public String getStyleclassName() {
+		return "state";
+	}
+
+	@Override
+	public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+		PresentationReconciler reconciler = new PresentationReconciler();
+
+		{
+			DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new StatemachineCodeScanner());
+			reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+			reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);			
+		}
+		
+		{
+			DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new StatemachineDocScanner());
+			reconciler.setDamager(dr, IStatemachinePartitions.MULTI_LINE_COMMENT);
+			reconciler.setRepairer(dr, IStatemachinePartitions.MULTI_LINE_COMMENT);
+		}
+				
+		return reconciler;
+	}
+	
+	@Override
+	public IContentAssistant getContentAssist() {
+		return new ContentAssistant(this::computeProposals);
+	}
+
+	private List<ICompletionProposal> computeProposals(Integer offset) {
+		return contentAssistProvider.doContentAssist(doc.get(),f.toURI().toString(), offset);
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine.fx/xtend-gen/org/eclipse/fx/xtext/statemachine/fx/internal/.gitignore b/demos/org.eclipse.fx.xtext.statemachine.fx/xtend-gen/org/eclipse/fx/xtext/statemachine/fx/internal/.gitignore
new file mode 100644
index 0000000..eb2eb70
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.fx/xtend-gen/org/eclipse/fx/xtext/statemachine/fx/internal/.gitignore
@@ -0,0 +1,4 @@
+/.StatemachineFXModule.java._trace
+/.StatemachineFXModule.xtendbin
+/.StatemachineWebModule.java._trace
+/StatemachineFXModule.java
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/.classpath b/demos/org.eclipse.fx.xtext.statemachine.ide/.classpath
new file mode 100644
index 0000000..2534a14
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-gen"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/.gitignore b/demos/org.eclipse.fx.xtext.statemachine.ide/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/.project b/demos/org.eclipse.fx.xtext.statemachine.ide/.project
new file mode 100644
index 0000000..38e13d8
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.fx.xtext.statemachine.ide</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>
+		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+	</natures>
+</projectDescription>
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.core.resources.prefs b/demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.jdt.core.prefs b/demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/META-INF/MANIFEST.MF b/demos/org.eclipse.fx.xtext.statemachine.ide/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8129130
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0

+Bundle-ManifestVersion: 2

+Bundle-Name: org.eclipse.fx.xtext.statemachine.ide

+Bundle-Vendor: My Company

+Bundle-Version: 1.0.0.qualifier

+Bundle-SymbolicName: org.eclipse.fx.xtext.statemachine.ide; singleton:=true

+Bundle-ActivationPolicy: lazy

+Require-Bundle: org.eclipse.fx.xtext.statemachine,

+ org.eclipse.xtext.ide;visibility:=reexport

+Import-Package: org.apache.log4j

+Bundle-RequiredExecutionEnvironment: JavaSE-1.8

+Export-Package: org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr,

+ org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal

diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/build.properties b/demos/org.eclipse.fx.xtext.statemachine.ide/build.properties
new file mode 100644
index 0000000..43a9292
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/build.properties
@@ -0,0 +1,5 @@
+source.. = src/,\
+           src-gen/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/StatemachineParser.java b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/StatemachineParser.java
new file mode 100644
index 0000000..eed6a62
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/StatemachineParser.java
@@ -0,0 +1,94 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.HashMap;
+
+import org.antlr.runtime.RecognitionException;
+import org.eclipse.xtext.AbstractElement;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.AbstractContentAssistParser;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.FollowElement;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.AbstractInternalContentAssistParser;
+
+import com.google.inject.Inject;
+
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+
+public class StatemachineParser extends AbstractContentAssistParser {
+	
+	@Inject
+	private StatemachineGrammarAccess grammarAccess;
+	
+	private Map<AbstractElement, String> nameMappings;
+	
+	@Override
+	protected org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal.InternalStatemachineParser createParser() {
+		org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal.InternalStatemachineParser result = new org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal.InternalStatemachineParser(null);
+		result.setGrammarAccess(grammarAccess);
+		return result;
+	}
+	
+	@Override
+	protected String getRuleName(AbstractElement element) {
+		if (nameMappings == null) {
+			nameMappings = new HashMap<AbstractElement, String>() {
+				private static final long serialVersionUID = 1L;
+				{
+					put(grammarAccess.getSignalAccess().getAlternatives_0(), "rule__Signal__Alternatives_0");
+					put(grammarAccess.getStatemachineAccess().getGroup(), "rule__Statemachine__Group__0");
+					put(grammarAccess.getSignalAccess().getGroup(), "rule__Signal__Group__0");
+					put(grammarAccess.getInputSignalAccess().getGroup(), "rule__InputSignal__Group__0");
+					put(grammarAccess.getOutputSignalAccess().getGroup(), "rule__OutputSignal__Group__0");
+					put(grammarAccess.getStateAccess().getGroup(), "rule__State__Group__0");
+					put(grammarAccess.getTransitionAccess().getGroup(), "rule__Transition__Group__0");
+					put(grammarAccess.getConditionAccess().getGroup(), "rule__Condition__Group__0");
+					put(grammarAccess.getConditionAccess().getGroup_1(), "rule__Condition__Group_1__0");
+					put(grammarAccess.getEventAccess().getGroup(), "rule__Event__Group__0");
+					put(grammarAccess.getCommandAccess().getGroup(), "rule__Command__Group__0");
+					put(grammarAccess.getStatemachineAccess().getSignalsAssignment_1(), "rule__Statemachine__SignalsAssignment_1");
+					put(grammarAccess.getStatemachineAccess().getStatesAssignment_2(), "rule__Statemachine__StatesAssignment_2");
+					put(grammarAccess.getSignalAccess().getNameAssignment_2(), "rule__Signal__NameAssignment_2");
+					put(grammarAccess.getStateAccess().getNameAssignment_1(), "rule__State__NameAssignment_1");
+					put(grammarAccess.getStateAccess().getCommandsAssignment_2(), "rule__State__CommandsAssignment_2");
+					put(grammarAccess.getStateAccess().getTransitionsAssignment_3(), "rule__State__TransitionsAssignment_3");
+					put(grammarAccess.getTransitionAccess().getConditionAssignment_1(), "rule__Transition__ConditionAssignment_1");
+					put(grammarAccess.getTransitionAccess().getStateAssignment_3(), "rule__Transition__StateAssignment_3");
+					put(grammarAccess.getConditionAccess().getEventsAssignment_0(), "rule__Condition__EventsAssignment_0");
+					put(grammarAccess.getConditionAccess().getEventsAssignment_1_1(), "rule__Condition__EventsAssignment_1_1");
+					put(grammarAccess.getEventAccess().getSignalAssignment_0(), "rule__Event__SignalAssignment_0");
+					put(grammarAccess.getEventAccess().getValueAssignment_2(), "rule__Event__ValueAssignment_2");
+					put(grammarAccess.getCommandAccess().getSignalAssignment_1(), "rule__Command__SignalAssignment_1");
+					put(grammarAccess.getCommandAccess().getNewValueAssignment_3(), "rule__Command__NewValueAssignment_3");
+				}
+			};
+		}
+		return nameMappings.get(element);
+	}
+	
+	@Override
+	protected Collection<FollowElement> getFollowElements(AbstractInternalContentAssistParser parser) {
+		try {
+			org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal.InternalStatemachineParser typedParser = (org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal.InternalStatemachineParser) parser;
+			typedParser.entryRuleStatemachine();
+			return typedParser.getFollowElements();
+		} catch(RecognitionException ex) {
+			throw new RuntimeException(ex);
+		}		
+	}
+	
+	@Override
+	protected String[] getInitialHiddenTokens() {
+		return new String[] { "RULE_WS", "RULE_ML_COMMENT", "RULE_SL_COMMENT" };
+	}
+	
+	public StatemachineGrammarAccess getGrammarAccess() {
+		return this.grammarAccess;
+	}
+	
+	public void setGrammarAccess(StatemachineGrammarAccess grammarAccess) {
+		this.grammarAccess = grammarAccess;
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g
new file mode 100644
index 0000000..58b680b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g
@@ -0,0 +1,1524 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+grammar InternalStatemachine;
+
+options {
+	superClass=AbstractInternalContentAssistParser;
+	
+}
+
+@lexer::header {
+package org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal;
+
+// Hack: Use our own Lexer superclass by means of import. 
+// Currently there is no other way to specify the superclass for the lexer.
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.Lexer;
+}
+
+@parser::header {
+package org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal; 
+
+import java.io.InputStream;
+import org.eclipse.xtext.*;
+import org.eclipse.xtext.parser.*;
+import org.eclipse.xtext.parser.impl.*;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream.HiddenTokens;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.AbstractInternalContentAssistParser;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.DFA;
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+
+}
+
+@parser::members {
+ 
+ 	private StatemachineGrammarAccess grammarAccess;
+ 	
+    public void setGrammarAccess(StatemachineGrammarAccess grammarAccess) {
+    	this.grammarAccess = grammarAccess;
+    }
+    
+    @Override
+    protected Grammar getGrammar() {
+    	return grammarAccess.getGrammar();
+    }
+    
+    @Override
+    protected String getValueForTokenName(String tokenName) {
+    	return tokenName;
+    }
+
+}
+
+
+
+
+// Entry rule entryRuleStatemachine
+entryRuleStatemachine 
+:
+{ before(grammarAccess.getStatemachineRule()); }
+	 ruleStatemachine
+{ after(grammarAccess.getStatemachineRule()); } 
+	 EOF 
+;
+
+// Rule Statemachine
+ruleStatemachine
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getStatemachineAccess().getGroup()); }
+(rule__Statemachine__Group__0)
+{ after(grammarAccess.getStatemachineAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleSignal
+entryRuleSignal 
+:
+{ before(grammarAccess.getSignalRule()); }
+	 ruleSignal
+{ after(grammarAccess.getSignalRule()); } 
+	 EOF 
+;
+
+// Rule Signal
+ruleSignal
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getSignalAccess().getGroup()); }
+(rule__Signal__Group__0)
+{ after(grammarAccess.getSignalAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleInputSignal
+entryRuleInputSignal 
+:
+{ before(grammarAccess.getInputSignalRule()); }
+	 ruleInputSignal
+{ after(grammarAccess.getInputSignalRule()); } 
+	 EOF 
+;
+
+// Rule InputSignal
+ruleInputSignal
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getInputSignalAccess().getGroup()); }
+(rule__InputSignal__Group__0)
+{ after(grammarAccess.getInputSignalAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleOutputSignal
+entryRuleOutputSignal 
+:
+{ before(grammarAccess.getOutputSignalRule()); }
+	 ruleOutputSignal
+{ after(grammarAccess.getOutputSignalRule()); } 
+	 EOF 
+;
+
+// Rule OutputSignal
+ruleOutputSignal
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getOutputSignalAccess().getGroup()); }
+(rule__OutputSignal__Group__0)
+{ after(grammarAccess.getOutputSignalAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleState
+entryRuleState 
+:
+{ before(grammarAccess.getStateRule()); }
+	 ruleState
+{ after(grammarAccess.getStateRule()); } 
+	 EOF 
+;
+
+// Rule State
+ruleState
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getStateAccess().getGroup()); }
+(rule__State__Group__0)
+{ after(grammarAccess.getStateAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleTransition
+entryRuleTransition 
+:
+{ before(grammarAccess.getTransitionRule()); }
+	 ruleTransition
+{ after(grammarAccess.getTransitionRule()); } 
+	 EOF 
+;
+
+// Rule Transition
+ruleTransition
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getTransitionAccess().getGroup()); }
+(rule__Transition__Group__0)
+{ after(grammarAccess.getTransitionAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleCondition
+entryRuleCondition 
+:
+{ before(grammarAccess.getConditionRule()); }
+	 ruleCondition
+{ after(grammarAccess.getConditionRule()); } 
+	 EOF 
+;
+
+// Rule Condition
+ruleCondition
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getConditionAccess().getGroup()); }
+(rule__Condition__Group__0)
+{ after(grammarAccess.getConditionAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleEvent
+entryRuleEvent 
+:
+{ before(grammarAccess.getEventRule()); }
+	 ruleEvent
+{ after(grammarAccess.getEventRule()); } 
+	 EOF 
+;
+
+// Rule Event
+ruleEvent
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getEventAccess().getGroup()); }
+(rule__Event__Group__0)
+{ after(grammarAccess.getEventAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+// Entry rule entryRuleCommand
+entryRuleCommand 
+:
+{ before(grammarAccess.getCommandRule()); }
+	 ruleCommand
+{ after(grammarAccess.getCommandRule()); } 
+	 EOF 
+;
+
+// Rule Command
+ruleCommand
+    @init {
+		int stackSize = keepStackSize();
+    }
+	:
+(
+{ before(grammarAccess.getCommandAccess().getGroup()); }
+(rule__Command__Group__0)
+{ after(grammarAccess.getCommandAccess().getGroup()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+rule__Signal__Alternatives_0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getSignalAccess().getInputSignalParserRuleCall_0_0()); }
+	ruleInputSignal
+{ after(grammarAccess.getSignalAccess().getInputSignalParserRuleCall_0_0()); }
+)
+
+    |(
+{ before(grammarAccess.getSignalAccess().getOutputSignalParserRuleCall_0_1()); }
+	ruleOutputSignal
+{ after(grammarAccess.getSignalAccess().getOutputSignalParserRuleCall_0_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+rule__Statemachine__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Statemachine__Group__0__Impl
+	rule__Statemachine__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Statemachine__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStatemachineAccess().getStatemachineAction_0()); }
+(
+
+)
+{ after(grammarAccess.getStatemachineAccess().getStatemachineAction_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Statemachine__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Statemachine__Group__1__Impl
+	rule__Statemachine__Group__2
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Statemachine__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStatemachineAccess().getSignalsAssignment_1()); }
+(rule__Statemachine__SignalsAssignment_1)*
+{ after(grammarAccess.getStatemachineAccess().getSignalsAssignment_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Statemachine__Group__2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Statemachine__Group__2__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Statemachine__Group__2__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStatemachineAccess().getStatesAssignment_2()); }
+(rule__Statemachine__StatesAssignment_2)*
+{ after(grammarAccess.getStatemachineAccess().getStatesAssignment_2()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+
+
+rule__Signal__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Signal__Group__0__Impl
+	rule__Signal__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Signal__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getSignalAccess().getAlternatives_0()); }
+(rule__Signal__Alternatives_0)
+{ after(grammarAccess.getSignalAccess().getAlternatives_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Signal__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Signal__Group__1__Impl
+	rule__Signal__Group__2
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Signal__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getSignalAccess().getSignalKeyword_1()); }
+
+	'signal' 
+
+{ after(grammarAccess.getSignalAccess().getSignalKeyword_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Signal__Group__2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Signal__Group__2__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Signal__Group__2__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getSignalAccess().getNameAssignment_2()); }
+(rule__Signal__NameAssignment_2)
+{ after(grammarAccess.getSignalAccess().getNameAssignment_2()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+
+
+rule__InputSignal__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__InputSignal__Group__0__Impl
+	rule__InputSignal__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__InputSignal__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getInputSignalAccess().getInputSignalAction_0()); }
+(
+
+)
+{ after(grammarAccess.getInputSignalAccess().getInputSignalAction_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__InputSignal__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__InputSignal__Group__1__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__InputSignal__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getInputSignalAccess().getInputKeyword_1()); }
+
+	'input' 
+
+{ after(grammarAccess.getInputSignalAccess().getInputKeyword_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+rule__OutputSignal__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__OutputSignal__Group__0__Impl
+	rule__OutputSignal__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__OutputSignal__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getOutputSignalAccess().getOutputSignalAction_0()); }
+(
+
+)
+{ after(grammarAccess.getOutputSignalAccess().getOutputSignalAction_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__OutputSignal__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__OutputSignal__Group__1__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__OutputSignal__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getOutputSignalAccess().getOutputKeyword_1()); }
+
+	'output' 
+
+{ after(grammarAccess.getOutputSignalAccess().getOutputKeyword_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+rule__State__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__State__Group__0__Impl
+	rule__State__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getStateKeyword_0()); }
+
+	'state' 
+
+{ after(grammarAccess.getStateAccess().getStateKeyword_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__State__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__State__Group__1__Impl
+	rule__State__Group__2
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getNameAssignment_1()); }
+(rule__State__NameAssignment_1)
+{ after(grammarAccess.getStateAccess().getNameAssignment_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__State__Group__2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__State__Group__2__Impl
+	rule__State__Group__3
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__Group__2__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getCommandsAssignment_2()); }
+(rule__State__CommandsAssignment_2)*
+{ after(grammarAccess.getStateAccess().getCommandsAssignment_2()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__State__Group__3
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__State__Group__3__Impl
+	rule__State__Group__4
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__Group__3__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getTransitionsAssignment_3()); }
+(rule__State__TransitionsAssignment_3)*
+{ after(grammarAccess.getStateAccess().getTransitionsAssignment_3()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__State__Group__4
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__State__Group__4__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__Group__4__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getEndKeyword_4()); }
+
+	'end' 
+
+{ after(grammarAccess.getStateAccess().getEndKeyword_4()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+rule__Transition__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Transition__Group__0__Impl
+	rule__Transition__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Transition__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getTransitionAccess().getIfKeyword_0()); }
+
+	'if' 
+
+{ after(grammarAccess.getTransitionAccess().getIfKeyword_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Transition__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Transition__Group__1__Impl
+	rule__Transition__Group__2
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Transition__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getTransitionAccess().getConditionAssignment_1()); }
+(rule__Transition__ConditionAssignment_1)
+{ after(grammarAccess.getTransitionAccess().getConditionAssignment_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Transition__Group__2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Transition__Group__2__Impl
+	rule__Transition__Group__3
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Transition__Group__2__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getTransitionAccess().getGotoKeyword_2()); }
+
+	'goto' 
+
+{ after(grammarAccess.getTransitionAccess().getGotoKeyword_2()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Transition__Group__3
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Transition__Group__3__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Transition__Group__3__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getTransitionAccess().getStateAssignment_3()); }
+(rule__Transition__StateAssignment_3)
+{ after(grammarAccess.getTransitionAccess().getStateAssignment_3()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+
+
+
+
+rule__Condition__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Condition__Group__0__Impl
+	rule__Condition__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Condition__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getConditionAccess().getEventsAssignment_0()); }
+(rule__Condition__EventsAssignment_0)
+{ after(grammarAccess.getConditionAccess().getEventsAssignment_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Condition__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Condition__Group__1__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Condition__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getConditionAccess().getGroup_1()); }
+(rule__Condition__Group_1__0)*
+{ after(grammarAccess.getConditionAccess().getGroup_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+rule__Condition__Group_1__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Condition__Group_1__0__Impl
+	rule__Condition__Group_1__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Condition__Group_1__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getConditionAccess().getAndKeyword_1_0()); }
+
+	'and' 
+
+{ after(grammarAccess.getConditionAccess().getAndKeyword_1_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Condition__Group_1__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Condition__Group_1__1__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Condition__Group_1__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getConditionAccess().getEventsAssignment_1_1()); }
+(rule__Condition__EventsAssignment_1_1)
+{ after(grammarAccess.getConditionAccess().getEventsAssignment_1_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+rule__Event__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Event__Group__0__Impl
+	rule__Event__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Event__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getEventAccess().getSignalAssignment_0()); }
+(rule__Event__SignalAssignment_0)
+{ after(grammarAccess.getEventAccess().getSignalAssignment_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Event__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Event__Group__1__Impl
+	rule__Event__Group__2
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Event__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getEventAccess().getEqualsSignEqualsSignKeyword_1()); }
+
+	'==' 
+
+{ after(grammarAccess.getEventAccess().getEqualsSignEqualsSignKeyword_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Event__Group__2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Event__Group__2__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Event__Group__2__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getEventAccess().getValueAssignment_2()); }
+(rule__Event__ValueAssignment_2)
+{ after(grammarAccess.getEventAccess().getValueAssignment_2()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+
+
+rule__Command__Group__0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Command__Group__0__Impl
+	rule__Command__Group__1
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Command__Group__0__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getCommandAccess().getSetKeyword_0()); }
+
+	'set' 
+
+{ after(grammarAccess.getCommandAccess().getSetKeyword_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Command__Group__1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Command__Group__1__Impl
+	rule__Command__Group__2
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Command__Group__1__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getCommandAccess().getSignalAssignment_1()); }
+(rule__Command__SignalAssignment_1)
+{ after(grammarAccess.getCommandAccess().getSignalAssignment_1()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Command__Group__2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Command__Group__2__Impl
+	rule__Command__Group__3
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Command__Group__2__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getCommandAccess().getEqualsSignKeyword_2()); }
+
+	'=' 
+
+{ after(grammarAccess.getCommandAccess().getEqualsSignKeyword_2()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+rule__Command__Group__3
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+	rule__Command__Group__3__Impl
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Command__Group__3__Impl
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getCommandAccess().getNewValueAssignment_3()); }
+(rule__Command__NewValueAssignment_3)
+{ after(grammarAccess.getCommandAccess().getNewValueAssignment_3()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+
+
+
+
+
+
+
+
+
+rule__Statemachine__SignalsAssignment_1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStatemachineAccess().getSignalsSignalParserRuleCall_1_0()); }
+	ruleSignal{ after(grammarAccess.getStatemachineAccess().getSignalsSignalParserRuleCall_1_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Statemachine__StatesAssignment_2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStatemachineAccess().getStatesStateParserRuleCall_2_0()); }
+	ruleState{ after(grammarAccess.getStatemachineAccess().getStatesStateParserRuleCall_2_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Signal__NameAssignment_2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0()); }
+	RULE_ID{ after(grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__NameAssignment_1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getNameIDTerminalRuleCall_1_0()); }
+	RULE_ID{ after(grammarAccess.getStateAccess().getNameIDTerminalRuleCall_1_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__CommandsAssignment_2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getCommandsCommandParserRuleCall_2_0()); }
+	ruleCommand{ after(grammarAccess.getStateAccess().getCommandsCommandParserRuleCall_2_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__State__TransitionsAssignment_3
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getStateAccess().getTransitionsTransitionParserRuleCall_3_0()); }
+	ruleTransition{ after(grammarAccess.getStateAccess().getTransitionsTransitionParserRuleCall_3_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Transition__ConditionAssignment_1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getTransitionAccess().getConditionConditionParserRuleCall_1_0()); }
+	ruleCondition{ after(grammarAccess.getTransitionAccess().getConditionConditionParserRuleCall_1_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Transition__StateAssignment_3
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getTransitionAccess().getStateStateCrossReference_3_0()); }
+(
+{ before(grammarAccess.getTransitionAccess().getStateStateIDTerminalRuleCall_3_0_1()); }
+	RULE_ID{ after(grammarAccess.getTransitionAccess().getStateStateIDTerminalRuleCall_3_0_1()); }
+)
+{ after(grammarAccess.getTransitionAccess().getStateStateCrossReference_3_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Condition__EventsAssignment_0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_0_0()); }
+	ruleEvent{ after(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_0_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Condition__EventsAssignment_1_1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_1_1_0()); }
+	ruleEvent{ after(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_1_1_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Event__SignalAssignment_0
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getEventAccess().getSignalSignalCrossReference_0_0()); }
+(
+{ before(grammarAccess.getEventAccess().getSignalSignalIDTerminalRuleCall_0_0_1()); }
+	RULE_ID{ after(grammarAccess.getEventAccess().getSignalSignalIDTerminalRuleCall_0_0_1()); }
+)
+{ after(grammarAccess.getEventAccess().getSignalSignalCrossReference_0_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Event__ValueAssignment_2
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getEventAccess().getValueBOOLEANTerminalRuleCall_2_0()); }
+	RULE_BOOLEAN{ after(grammarAccess.getEventAccess().getValueBOOLEANTerminalRuleCall_2_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Command__SignalAssignment_1
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getCommandAccess().getSignalSignalCrossReference_1_0()); }
+(
+{ before(grammarAccess.getCommandAccess().getSignalSignalIDTerminalRuleCall_1_0_1()); }
+	RULE_ID{ after(grammarAccess.getCommandAccess().getSignalSignalIDTerminalRuleCall_1_0_1()); }
+)
+{ after(grammarAccess.getCommandAccess().getSignalSignalCrossReference_1_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+rule__Command__NewValueAssignment_3
+    @init {
+		int stackSize = keepStackSize();
+    }
+:
+(
+{ before(grammarAccess.getCommandAccess().getNewValueBOOLEANTerminalRuleCall_3_0()); }
+	RULE_BOOLEAN{ after(grammarAccess.getCommandAccess().getNewValueBOOLEANTerminalRuleCall_3_0()); }
+)
+
+;
+finally {
+	restoreStackSize(stackSize);
+}
+
+
+RULE_BOOLEAN : ('true'|'false');
+
+RULE_ID : '^'? ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
+
+RULE_INT : ('0'..'9')+;
+
+RULE_STRING : ('"' ('\\' .|~(('\\'|'"')))* '"'|'\'' ('\\' .|~(('\\'|'\'')))* '\'');
+
+RULE_ML_COMMENT : '/*' ( options {greedy=false;} : . )*'*/';
+
+RULE_SL_COMMENT : '//' ~(('\n'|'\r'))* ('\r'? '\n')?;
+
+RULE_WS : (' '|'\t'|'\r'|'\n')+;
+
+RULE_ANY_OTHER : .;
+
+
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.tokens b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.tokens
new file mode 100644
index 0000000..4cf4071
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.tokens
@@ -0,0 +1,30 @@
+'='=22
+'=='=20
+'and'=19
+'end'=16
+'goto'=18
+'if'=17
+'input'=13
+'output'=14
+'set'=21
+'signal'=12
+'state'=15
+RULE_ANY_OTHER=11
+RULE_BOOLEAN=5
+RULE_ID=4
+RULE_INT=6
+RULE_ML_COMMENT=8
+RULE_SL_COMMENT=9
+RULE_STRING=7
+RULE_WS=10
+T__12=12
+T__13=13
+T__14=14
+T__15=15
+T__16=16
+T__17=17
+T__18=18
+T__19=19
+T__20=20
+T__21=21
+T__22=22
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineLexer.java b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineLexer.java
new file mode 100644
index 0000000..304c9bc
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineLexer.java
@@ -0,0 +1,1168 @@
+package org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal;
+
+// Hack: Use our own Lexer superclass by means of import. 
+// Currently there is no other way to specify the superclass for the lexer.
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.Lexer;
+
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+@SuppressWarnings("all")
+public class InternalStatemachineLexer extends Lexer {
+    public static final int RULE_BOOLEAN=5;
+    public static final int RULE_STRING=7;
+    public static final int RULE_SL_COMMENT=9;
+    public static final int T__19=19;
+    public static final int T__15=15;
+    public static final int T__16=16;
+    public static final int T__17=17;
+    public static final int T__18=18;
+    public static final int T__12=12;
+    public static final int T__13=13;
+    public static final int T__14=14;
+    public static final int EOF=-1;
+    public static final int RULE_ID=4;
+    public static final int RULE_WS=10;
+    public static final int RULE_ANY_OTHER=11;
+    public static final int RULE_INT=6;
+    public static final int T__22=22;
+    public static final int RULE_ML_COMMENT=8;
+    public static final int T__20=20;
+    public static final int T__21=21;
+
+    // delegates
+    // delegators
+
+    public InternalStatemachineLexer() {;} 
+    public InternalStatemachineLexer(CharStream input) {
+        this(input, new RecognizerSharedState());
+    }
+    public InternalStatemachineLexer(CharStream input, RecognizerSharedState state) {
+        super(input,state);
+
+    }
+    public String getGrammarFileName() { return "../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g"; }
+
+    // $ANTLR start "T__12"
+    public final void mT__12() throws RecognitionException {
+        try {
+            int _type = T__12;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:11:7: ( 'signal' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:11:9: 'signal'
+            {
+            match("signal"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__12"
+
+    // $ANTLR start "T__13"
+    public final void mT__13() throws RecognitionException {
+        try {
+            int _type = T__13;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:12:7: ( 'input' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:12:9: 'input'
+            {
+            match("input"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__13"
+
+    // $ANTLR start "T__14"
+    public final void mT__14() throws RecognitionException {
+        try {
+            int _type = T__14;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:13:7: ( 'output' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:13:9: 'output'
+            {
+            match("output"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__14"
+
+    // $ANTLR start "T__15"
+    public final void mT__15() throws RecognitionException {
+        try {
+            int _type = T__15;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:14:7: ( 'state' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:14:9: 'state'
+            {
+            match("state"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__15"
+
+    // $ANTLR start "T__16"
+    public final void mT__16() throws RecognitionException {
+        try {
+            int _type = T__16;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:15:7: ( 'end' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:15:9: 'end'
+            {
+            match("end"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__16"
+
+    // $ANTLR start "T__17"
+    public final void mT__17() throws RecognitionException {
+        try {
+            int _type = T__17;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:16:7: ( 'if' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:16:9: 'if'
+            {
+            match("if"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__17"
+
+    // $ANTLR start "T__18"
+    public final void mT__18() throws RecognitionException {
+        try {
+            int _type = T__18;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:17:7: ( 'goto' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:17:9: 'goto'
+            {
+            match("goto"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__18"
+
+    // $ANTLR start "T__19"
+    public final void mT__19() throws RecognitionException {
+        try {
+            int _type = T__19;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:18:7: ( 'and' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:18:9: 'and'
+            {
+            match("and"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__19"
+
+    // $ANTLR start "T__20"
+    public final void mT__20() throws RecognitionException {
+        try {
+            int _type = T__20;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:19:7: ( '==' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:19:9: '=='
+            {
+            match("=="); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__20"
+
+    // $ANTLR start "T__21"
+    public final void mT__21() throws RecognitionException {
+        try {
+            int _type = T__21;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:20:7: ( 'set' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:20:9: 'set'
+            {
+            match("set"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__21"
+
+    // $ANTLR start "T__22"
+    public final void mT__22() throws RecognitionException {
+        try {
+            int _type = T__22;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:21:7: ( '=' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:21:9: '='
+            {
+            match('='); 
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__22"
+
+    // $ANTLR start "RULE_BOOLEAN"
+    public final void mRULE_BOOLEAN() throws RecognitionException {
+        try {
+            int _type = RULE_BOOLEAN;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1508:14: ( ( 'true' | 'false' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1508:16: ( 'true' | 'false' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1508:16: ( 'true' | 'false' )
+            int alt1=2;
+            int LA1_0 = input.LA(1);
+
+            if ( (LA1_0=='t') ) {
+                alt1=1;
+            }
+            else if ( (LA1_0=='f') ) {
+                alt1=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 1, 0, input);
+
+                throw nvae;
+            }
+            switch (alt1) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1508:17: 'true'
+                    {
+                    match("true"); 
+
+
+                    }
+                    break;
+                case 2 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1508:24: 'false'
+                    {
+                    match("false"); 
+
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_BOOLEAN"
+
+    // $ANTLR start "RULE_ID"
+    public final void mRULE_ID() throws RecognitionException {
+        try {
+            int _type = RULE_ID;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1510:9: ( ( '^' )? ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )* )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1510:11: ( '^' )? ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )*
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1510:11: ( '^' )?
+            int alt2=2;
+            int LA2_0 = input.LA(1);
+
+            if ( (LA2_0=='^') ) {
+                alt2=1;
+            }
+            switch (alt2) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1510:11: '^'
+                    {
+                    match('^'); 
+
+                    }
+                    break;
+
+            }
+
+            if ( (input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse = new MismatchedSetException(null,input);
+                recover(mse);
+                throw mse;}
+
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1510:40: ( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )*
+            loop3:
+            do {
+                int alt3=2;
+                int LA3_0 = input.LA(1);
+
+                if ( ((LA3_0>='0' && LA3_0<='9')||(LA3_0>='A' && LA3_0<='Z')||LA3_0=='_'||(LA3_0>='a' && LA3_0<='z')) ) {
+                    alt3=1;
+                }
+
+
+                switch (alt3) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:
+            	    {
+            	    if ( (input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        recover(mse);
+            	        throw mse;}
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop3;
+                }
+            } while (true);
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_ID"
+
+    // $ANTLR start "RULE_INT"
+    public final void mRULE_INT() throws RecognitionException {
+        try {
+            int _type = RULE_INT;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1512:10: ( ( '0' .. '9' )+ )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1512:12: ( '0' .. '9' )+
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1512:12: ( '0' .. '9' )+
+            int cnt4=0;
+            loop4:
+            do {
+                int alt4=2;
+                int LA4_0 = input.LA(1);
+
+                if ( ((LA4_0>='0' && LA4_0<='9')) ) {
+                    alt4=1;
+                }
+
+
+                switch (alt4) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1512:13: '0' .. '9'
+            	    {
+            	    matchRange('0','9'); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt4 >= 1 ) break loop4;
+                        EarlyExitException eee =
+                            new EarlyExitException(4, input);
+                        throw eee;
+                }
+                cnt4++;
+            } while (true);
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_INT"
+
+    // $ANTLR start "RULE_STRING"
+    public final void mRULE_STRING() throws RecognitionException {
+        try {
+            int _type = RULE_STRING;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:13: ( ( '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"' | '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\'' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:15: ( '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"' | '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\'' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:15: ( '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"' | '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\'' )
+            int alt7=2;
+            int LA7_0 = input.LA(1);
+
+            if ( (LA7_0=='\"') ) {
+                alt7=1;
+            }
+            else if ( (LA7_0=='\'') ) {
+                alt7=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 7, 0, input);
+
+                throw nvae;
+            }
+            switch (alt7) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:16: '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"'
+                    {
+                    match('\"'); 
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:20: ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )*
+                    loop5:
+                    do {
+                        int alt5=3;
+                        int LA5_0 = input.LA(1);
+
+                        if ( (LA5_0=='\\') ) {
+                            alt5=1;
+                        }
+                        else if ( ((LA5_0>='\u0000' && LA5_0<='!')||(LA5_0>='#' && LA5_0<='[')||(LA5_0>=']' && LA5_0<='\uFFFF')) ) {
+                            alt5=2;
+                        }
+
+
+                        switch (alt5) {
+                    	case 1 :
+                    	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:21: '\\\\' .
+                    	    {
+                    	    match('\\'); 
+                    	    matchAny(); 
+
+                    	    }
+                    	    break;
+                    	case 2 :
+                    	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:28: ~ ( ( '\\\\' | '\"' ) )
+                    	    {
+                    	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='!')||(input.LA(1)>='#' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFF') ) {
+                    	        input.consume();
+
+                    	    }
+                    	    else {
+                    	        MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        recover(mse);
+                    	        throw mse;}
+
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop5;
+                        }
+                    } while (true);
+
+                    match('\"'); 
+
+                    }
+                    break;
+                case 2 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:48: '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\''
+                    {
+                    match('\''); 
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:53: ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )*
+                    loop6:
+                    do {
+                        int alt6=3;
+                        int LA6_0 = input.LA(1);
+
+                        if ( (LA6_0=='\\') ) {
+                            alt6=1;
+                        }
+                        else if ( ((LA6_0>='\u0000' && LA6_0<='&')||(LA6_0>='(' && LA6_0<='[')||(LA6_0>=']' && LA6_0<='\uFFFF')) ) {
+                            alt6=2;
+                        }
+
+
+                        switch (alt6) {
+                    	case 1 :
+                    	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:54: '\\\\' .
+                    	    {
+                    	    match('\\'); 
+                    	    matchAny(); 
+
+                    	    }
+                    	    break;
+                    	case 2 :
+                    	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1514:61: ~ ( ( '\\\\' | '\\'' ) )
+                    	    {
+                    	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFF') ) {
+                    	        input.consume();
+
+                    	    }
+                    	    else {
+                    	        MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        recover(mse);
+                    	        throw mse;}
+
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop6;
+                        }
+                    } while (true);
+
+                    match('\''); 
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_STRING"
+
+    // $ANTLR start "RULE_ML_COMMENT"
+    public final void mRULE_ML_COMMENT() throws RecognitionException {
+        try {
+            int _type = RULE_ML_COMMENT;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1516:17: ( '/*' ( options {greedy=false; } : . )* '*/' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1516:19: '/*' ( options {greedy=false; } : . )* '*/'
+            {
+            match("/*"); 
+
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1516:24: ( options {greedy=false; } : . )*
+            loop8:
+            do {
+                int alt8=2;
+                int LA8_0 = input.LA(1);
+
+                if ( (LA8_0=='*') ) {
+                    int LA8_1 = input.LA(2);
+
+                    if ( (LA8_1=='/') ) {
+                        alt8=2;
+                    }
+                    else if ( ((LA8_1>='\u0000' && LA8_1<='.')||(LA8_1>='0' && LA8_1<='\uFFFF')) ) {
+                        alt8=1;
+                    }
+
+
+                }
+                else if ( ((LA8_0>='\u0000' && LA8_0<=')')||(LA8_0>='+' && LA8_0<='\uFFFF')) ) {
+                    alt8=1;
+                }
+
+
+                switch (alt8) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1516:52: .
+            	    {
+            	    matchAny(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop8;
+                }
+            } while (true);
+
+            match("*/"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_ML_COMMENT"
+
+    // $ANTLR start "RULE_SL_COMMENT"
+    public final void mRULE_SL_COMMENT() throws RecognitionException {
+        try {
+            int _type = RULE_SL_COMMENT;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:17: ( '//' (~ ( ( '\\n' | '\\r' ) ) )* ( ( '\\r' )? '\\n' )? )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:19: '//' (~ ( ( '\\n' | '\\r' ) ) )* ( ( '\\r' )? '\\n' )?
+            {
+            match("//"); 
+
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:24: (~ ( ( '\\n' | '\\r' ) ) )*
+            loop9:
+            do {
+                int alt9=2;
+                int LA9_0 = input.LA(1);
+
+                if ( ((LA9_0>='\u0000' && LA9_0<='\t')||(LA9_0>='\u000B' && LA9_0<='\f')||(LA9_0>='\u000E' && LA9_0<='\uFFFF')) ) {
+                    alt9=1;
+                }
+
+
+                switch (alt9) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:24: ~ ( ( '\\n' | '\\r' ) )
+            	    {
+            	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='\t')||(input.LA(1)>='\u000B' && input.LA(1)<='\f')||(input.LA(1)>='\u000E' && input.LA(1)<='\uFFFF') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        recover(mse);
+            	        throw mse;}
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop9;
+                }
+            } while (true);
+
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:40: ( ( '\\r' )? '\\n' )?
+            int alt11=2;
+            int LA11_0 = input.LA(1);
+
+            if ( (LA11_0=='\n'||LA11_0=='\r') ) {
+                alt11=1;
+            }
+            switch (alt11) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:41: ( '\\r' )? '\\n'
+                    {
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:41: ( '\\r' )?
+                    int alt10=2;
+                    int LA10_0 = input.LA(1);
+
+                    if ( (LA10_0=='\r') ) {
+                        alt10=1;
+                    }
+                    switch (alt10) {
+                        case 1 :
+                            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1518:41: '\\r'
+                            {
+                            match('\r'); 
+
+                            }
+                            break;
+
+                    }
+
+                    match('\n'); 
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_SL_COMMENT"
+
+    // $ANTLR start "RULE_WS"
+    public final void mRULE_WS() throws RecognitionException {
+        try {
+            int _type = RULE_WS;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1520:9: ( ( ' ' | '\\t' | '\\r' | '\\n' )+ )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1520:11: ( ' ' | '\\t' | '\\r' | '\\n' )+
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1520:11: ( ' ' | '\\t' | '\\r' | '\\n' )+
+            int cnt12=0;
+            loop12:
+            do {
+                int alt12=2;
+                int LA12_0 = input.LA(1);
+
+                if ( ((LA12_0>='\t' && LA12_0<='\n')||LA12_0=='\r'||LA12_0==' ') ) {
+                    alt12=1;
+                }
+
+
+                switch (alt12) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:
+            	    {
+            	    if ( (input.LA(1)>='\t' && input.LA(1)<='\n')||input.LA(1)=='\r'||input.LA(1)==' ' ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        recover(mse);
+            	        throw mse;}
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt12 >= 1 ) break loop12;
+                        EarlyExitException eee =
+                            new EarlyExitException(12, input);
+                        throw eee;
+                }
+                cnt12++;
+            } while (true);
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_WS"
+
+    // $ANTLR start "RULE_ANY_OTHER"
+    public final void mRULE_ANY_OTHER() throws RecognitionException {
+        try {
+            int _type = RULE_ANY_OTHER;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1522:16: ( . )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1522:18: .
+            {
+            matchAny(); 
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_ANY_OTHER"
+
+    public void mTokens() throws RecognitionException {
+        // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:8: ( T__12 | T__13 | T__14 | T__15 | T__16 | T__17 | T__18 | T__19 | T__20 | T__21 | T__22 | RULE_BOOLEAN | RULE_ID | RULE_INT | RULE_STRING | RULE_ML_COMMENT | RULE_SL_COMMENT | RULE_WS | RULE_ANY_OTHER )
+        int alt13=19;
+        alt13 = dfa13.predict(input);
+        switch (alt13) {
+            case 1 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:10: T__12
+                {
+                mT__12(); 
+
+                }
+                break;
+            case 2 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:16: T__13
+                {
+                mT__13(); 
+
+                }
+                break;
+            case 3 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:22: T__14
+                {
+                mT__14(); 
+
+                }
+                break;
+            case 4 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:28: T__15
+                {
+                mT__15(); 
+
+                }
+                break;
+            case 5 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:34: T__16
+                {
+                mT__16(); 
+
+                }
+                break;
+            case 6 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:40: T__17
+                {
+                mT__17(); 
+
+                }
+                break;
+            case 7 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:46: T__18
+                {
+                mT__18(); 
+
+                }
+                break;
+            case 8 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:52: T__19
+                {
+                mT__19(); 
+
+                }
+                break;
+            case 9 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:58: T__20
+                {
+                mT__20(); 
+
+                }
+                break;
+            case 10 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:64: T__21
+                {
+                mT__21(); 
+
+                }
+                break;
+            case 11 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:70: T__22
+                {
+                mT__22(); 
+
+                }
+                break;
+            case 12 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:76: RULE_BOOLEAN
+                {
+                mRULE_BOOLEAN(); 
+
+                }
+                break;
+            case 13 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:89: RULE_ID
+                {
+                mRULE_ID(); 
+
+                }
+                break;
+            case 14 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:97: RULE_INT
+                {
+                mRULE_INT(); 
+
+                }
+                break;
+            case 15 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:106: RULE_STRING
+                {
+                mRULE_STRING(); 
+
+                }
+                break;
+            case 16 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:118: RULE_ML_COMMENT
+                {
+                mRULE_ML_COMMENT(); 
+
+                }
+                break;
+            case 17 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:134: RULE_SL_COMMENT
+                {
+                mRULE_SL_COMMENT(); 
+
+                }
+                break;
+            case 18 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:150: RULE_WS
+                {
+                mRULE_WS(); 
+
+                }
+                break;
+            case 19 :
+                // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1:158: RULE_ANY_OTHER
+                {
+                mRULE_ANY_OTHER(); 
+
+                }
+                break;
+
+        }
+
+    }
+
+
+    protected DFA13 dfa13 = new DFA13(this);
+    static final String DFA13_eotS =
+        "\1\uffff\6\25\1\35\2\25\1\21\2\uffff\3\21\2\uffff\3\25\1\uffff\1\25\1\51\4\25\2\uffff\2\25\5\uffff\2\25\1\62\1\25\1\uffff\1\25\1\65\1\25\1\67\4\25\1\uffff\2\25\1\uffff\1\76\1\uffff\1\77\2\25\1\102\1\103\1\25\2\uffff\1\77\1\105\2\uffff\1\106\2\uffff";
+    static final String DFA13_eofS =
+        "\107\uffff";
+    static final String DFA13_minS =
+        "\1\0\1\145\1\146\1\165\1\156\1\157\1\156\1\75\1\162\1\141\1\101\2\uffff\2\0\1\52\2\uffff\1\147\1\141\1\164\1\uffff\1\160\1\60\1\164\1\144\1\164\1\144\2\uffff\1\165\1\154\5\uffff\1\156\1\164\1\60\1\165\1\uffff\1\160\1\60\1\157\1\60\1\145\1\163\1\141\1\145\1\uffff\1\164\1\165\1\uffff\1\60\1\uffff\1\60\1\145\1\154\2\60\1\164\2\uffff\2\60\2\uffff\1\60\2\uffff";
+    static final String DFA13_maxS =
+        "\1\uffff\1\164\1\156\1\165\1\156\1\157\1\156\1\75\1\162\1\141\1\172\2\uffff\2\uffff\1\57\2\uffff\1\147\1\141\1\164\1\uffff\1\160\1\172\1\164\1\144\1\164\1\144\2\uffff\1\165\1\154\5\uffff\1\156\1\164\1\172\1\165\1\uffff\1\160\1\172\1\157\1\172\1\145\1\163\1\141\1\145\1\uffff\1\164\1\165\1\uffff\1\172\1\uffff\1\172\1\145\1\154\2\172\1\164\2\uffff\2\172\2\uffff\1\172\2\uffff";
+    static final String DFA13_acceptS =
+        "\13\uffff\1\15\1\16\3\uffff\1\22\1\23\3\uffff\1\15\6\uffff\1\11\1\13\2\uffff\1\16\1\17\1\20\1\21\1\22\4\uffff\1\6\10\uffff\1\12\2\uffff\1\5\1\uffff\1\10\6\uffff\1\7\1\14\2\uffff\1\4\1\2\1\uffff\1\1\1\3";
+    static final String DFA13_specialS =
+        "\1\1\14\uffff\1\0\1\2\70\uffff}>";
+    static final String[] DFA13_transitionS = {
+            "\11\21\2\20\2\21\1\20\22\21\1\20\1\21\1\15\4\21\1\16\7\21\1\17\12\14\3\21\1\7\3\21\32\13\3\21\1\12\1\13\1\21\1\6\3\13\1\4\1\11\1\5\1\13\1\2\5\13\1\3\3\13\1\1\1\10\6\13\uff85\21",
+            "\1\24\3\uffff\1\22\12\uffff\1\23",
+            "\1\27\7\uffff\1\26",
+            "\1\30",
+            "\1\31",
+            "\1\32",
+            "\1\33",
+            "\1\34",
+            "\1\36",
+            "\1\37",
+            "\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            "",
+            "\0\41",
+            "\0\41",
+            "\1\42\4\uffff\1\43",
+            "",
+            "",
+            "\1\45",
+            "\1\46",
+            "\1\47",
+            "",
+            "\1\50",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\52",
+            "\1\53",
+            "\1\54",
+            "\1\55",
+            "",
+            "",
+            "\1\56",
+            "\1\57",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\1\60",
+            "\1\61",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\63",
+            "",
+            "\1\64",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\66",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\70",
+            "\1\71",
+            "\1\72",
+            "\1\73",
+            "",
+            "\1\74",
+            "\1\75",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\100",
+            "\1\101",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\104",
+            "",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            ""
+    };
+
+    static final short[] DFA13_eot = DFA.unpackEncodedString(DFA13_eotS);
+    static final short[] DFA13_eof = DFA.unpackEncodedString(DFA13_eofS);
+    static final char[] DFA13_min = DFA.unpackEncodedStringToUnsignedChars(DFA13_minS);
+    static final char[] DFA13_max = DFA.unpackEncodedStringToUnsignedChars(DFA13_maxS);
+    static final short[] DFA13_accept = DFA.unpackEncodedString(DFA13_acceptS);
+    static final short[] DFA13_special = DFA.unpackEncodedString(DFA13_specialS);
+    static final short[][] DFA13_transition;
+
+    static {
+        int numStates = DFA13_transitionS.length;
+        DFA13_transition = new short[numStates][];
+        for (int i=0; i<numStates; i++) {
+            DFA13_transition[i] = DFA.unpackEncodedString(DFA13_transitionS[i]);
+        }
+    }
+
+    class DFA13 extends DFA {
+
+        public DFA13(BaseRecognizer recognizer) {
+            this.recognizer = recognizer;
+            this.decisionNumber = 13;
+            this.eot = DFA13_eot;
+            this.eof = DFA13_eof;
+            this.min = DFA13_min;
+            this.max = DFA13_max;
+            this.accept = DFA13_accept;
+            this.special = DFA13_special;
+            this.transition = DFA13_transition;
+        }
+        public String getDescription() {
+            return "1:1: Tokens : ( T__12 | T__13 | T__14 | T__15 | T__16 | T__17 | T__18 | T__19 | T__20 | T__21 | T__22 | RULE_BOOLEAN | RULE_ID | RULE_INT | RULE_STRING | RULE_ML_COMMENT | RULE_SL_COMMENT | RULE_WS | RULE_ANY_OTHER );";
+        }
+        public int specialStateTransition(int s, IntStream _input) throws NoViableAltException {
+            IntStream input = _input;
+        	int _s = s;
+            switch ( s ) {
+                    case 0 : 
+                        int LA13_13 = input.LA(1);
+
+                        s = -1;
+                        if ( ((LA13_13>='\u0000' && LA13_13<='\uFFFF')) ) {s = 33;}
+
+                        else s = 17;
+
+                        if ( s>=0 ) return s;
+                        break;
+                    case 1 : 
+                        int LA13_0 = input.LA(1);
+
+                        s = -1;
+                        if ( (LA13_0=='s') ) {s = 1;}
+
+                        else if ( (LA13_0=='i') ) {s = 2;}
+
+                        else if ( (LA13_0=='o') ) {s = 3;}
+
+                        else if ( (LA13_0=='e') ) {s = 4;}
+
+                        else if ( (LA13_0=='g') ) {s = 5;}
+
+                        else if ( (LA13_0=='a') ) {s = 6;}
+
+                        else if ( (LA13_0=='=') ) {s = 7;}
+
+                        else if ( (LA13_0=='t') ) {s = 8;}
+
+                        else if ( (LA13_0=='f') ) {s = 9;}
+
+                        else if ( (LA13_0=='^') ) {s = 10;}
+
+                        else if ( ((LA13_0>='A' && LA13_0<='Z')||LA13_0=='_'||(LA13_0>='b' && LA13_0<='d')||LA13_0=='h'||(LA13_0>='j' && LA13_0<='n')||(LA13_0>='p' && LA13_0<='r')||(LA13_0>='u' && LA13_0<='z')) ) {s = 11;}
+
+                        else if ( ((LA13_0>='0' && LA13_0<='9')) ) {s = 12;}
+
+                        else if ( (LA13_0=='\"') ) {s = 13;}
+
+                        else if ( (LA13_0=='\'') ) {s = 14;}
+
+                        else if ( (LA13_0=='/') ) {s = 15;}
+
+                        else if ( ((LA13_0>='\t' && LA13_0<='\n')||LA13_0=='\r'||LA13_0==' ') ) {s = 16;}
+
+                        else if ( ((LA13_0>='\u0000' && LA13_0<='\b')||(LA13_0>='\u000B' && LA13_0<='\f')||(LA13_0>='\u000E' && LA13_0<='\u001F')||LA13_0=='!'||(LA13_0>='#' && LA13_0<='&')||(LA13_0>='(' && LA13_0<='.')||(LA13_0>=':' && LA13_0<='<')||(LA13_0>='>' && LA13_0<='@')||(LA13_0>='[' && LA13_0<=']')||LA13_0=='`'||(LA13_0>='{' && LA13_0<='\uFFFF')) ) {s = 17;}
+
+                        if ( s>=0 ) return s;
+                        break;
+                    case 2 : 
+                        int LA13_14 = input.LA(1);
+
+                        s = -1;
+                        if ( ((LA13_14>='\u0000' && LA13_14<='\uFFFF')) ) {s = 33;}
+
+                        else s = 17;
+
+                        if ( s>=0 ) return s;
+                        break;
+            }
+            NoViableAltException nvae =
+                new NoViableAltException(getDescription(), 13, _s, input);
+            error(nvae);
+            throw nvae;
+        }
+    }
+ 
+
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineParser.java b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineParser.java
new file mode 100644
index 0000000..62a51fd
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineParser.java
@@ -0,0 +1,4002 @@
+package org.eclipse.fx.xtext.statemachine.ide.contentassist.antlr.internal; 
+
+import java.io.InputStream;
+import org.eclipse.xtext.*;
+import org.eclipse.xtext.parser.*;
+import org.eclipse.xtext.parser.impl.*;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream.HiddenTokens;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.AbstractInternalContentAssistParser;
+import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.DFA;
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+
+
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+@SuppressWarnings("all")
+public class InternalStatemachineParser extends AbstractInternalContentAssistParser {
+    public static final String[] tokenNames = new String[] {
+        "<invalid>", "<EOR>", "<DOWN>", "<UP>", "RULE_ID", "RULE_BOOLEAN", "RULE_INT", "RULE_STRING", "RULE_ML_COMMENT", "RULE_SL_COMMENT", "RULE_WS", "RULE_ANY_OTHER", "'signal'", "'input'", "'output'", "'state'", "'end'", "'if'", "'goto'", "'and'", "'=='", "'set'", "'='"
+    };
+    public static final int RULE_BOOLEAN=5;
+    public static final int RULE_STRING=7;
+    public static final int RULE_SL_COMMENT=9;
+    public static final int T__19=19;
+    public static final int T__15=15;
+    public static final int T__16=16;
+    public static final int T__17=17;
+    public static final int T__18=18;
+    public static final int T__12=12;
+    public static final int T__13=13;
+    public static final int T__14=14;
+    public static final int EOF=-1;
+    public static final int RULE_ID=4;
+    public static final int RULE_WS=10;
+    public static final int RULE_ANY_OTHER=11;
+    public static final int RULE_INT=6;
+    public static final int T__22=22;
+    public static final int RULE_ML_COMMENT=8;
+    public static final int T__20=20;
+    public static final int T__21=21;
+
+    // delegates
+    // delegators
+
+
+        public InternalStatemachineParser(TokenStream input) {
+            this(input, new RecognizerSharedState());
+        }
+        public InternalStatemachineParser(TokenStream input, RecognizerSharedState state) {
+            super(input, state);
+             
+        }
+        
+
+    public String[] getTokenNames() { return InternalStatemachineParser.tokenNames; }
+    public String getGrammarFileName() { return "../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g"; }
+
+
+     
+     	private StatemachineGrammarAccess grammarAccess;
+     	
+        public void setGrammarAccess(StatemachineGrammarAccess grammarAccess) {
+        	this.grammarAccess = grammarAccess;
+        }
+        
+        @Override
+        protected Grammar getGrammar() {
+        	return grammarAccess.getGrammar();
+        }
+        
+        @Override
+        protected String getValueForTokenName(String tokenName) {
+        	return tokenName;
+        }
+
+
+
+
+    // $ANTLR start "entryRuleStatemachine"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:60:1: entryRuleStatemachine : ruleStatemachine EOF ;
+    public final void entryRuleStatemachine() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:61:1: ( ruleStatemachine EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:62:1: ruleStatemachine EOF
+            {
+             before(grammarAccess.getStatemachineRule()); 
+            pushFollow(FOLLOW_ruleStatemachine_in_entryRuleStatemachine61);
+            ruleStatemachine();
+
+            state._fsp--;
+
+             after(grammarAccess.getStatemachineRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleStatemachine68); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleStatemachine"
+
+
+    // $ANTLR start "ruleStatemachine"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:69:1: ruleStatemachine : ( ( rule__Statemachine__Group__0 ) ) ;
+    public final void ruleStatemachine() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:73:2: ( ( ( rule__Statemachine__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:74:1: ( ( rule__Statemachine__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:74:1: ( ( rule__Statemachine__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:75:1: ( rule__Statemachine__Group__0 )
+            {
+             before(grammarAccess.getStatemachineAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:76:1: ( rule__Statemachine__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:76:2: rule__Statemachine__Group__0
+            {
+            pushFollow(FOLLOW_rule__Statemachine__Group__0_in_ruleStatemachine94);
+            rule__Statemachine__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getStatemachineAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleStatemachine"
+
+
+    // $ANTLR start "entryRuleSignal"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:88:1: entryRuleSignal : ruleSignal EOF ;
+    public final void entryRuleSignal() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:89:1: ( ruleSignal EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:90:1: ruleSignal EOF
+            {
+             before(grammarAccess.getSignalRule()); 
+            pushFollow(FOLLOW_ruleSignal_in_entryRuleSignal121);
+            ruleSignal();
+
+            state._fsp--;
+
+             after(grammarAccess.getSignalRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleSignal128); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleSignal"
+
+
+    // $ANTLR start "ruleSignal"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:97:1: ruleSignal : ( ( rule__Signal__Group__0 ) ) ;
+    public final void ruleSignal() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:101:2: ( ( ( rule__Signal__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:102:1: ( ( rule__Signal__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:102:1: ( ( rule__Signal__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:103:1: ( rule__Signal__Group__0 )
+            {
+             before(grammarAccess.getSignalAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:104:1: ( rule__Signal__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:104:2: rule__Signal__Group__0
+            {
+            pushFollow(FOLLOW_rule__Signal__Group__0_in_ruleSignal154);
+            rule__Signal__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getSignalAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleSignal"
+
+
+    // $ANTLR start "entryRuleInputSignal"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:116:1: entryRuleInputSignal : ruleInputSignal EOF ;
+    public final void entryRuleInputSignal() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:117:1: ( ruleInputSignal EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:118:1: ruleInputSignal EOF
+            {
+             before(grammarAccess.getInputSignalRule()); 
+            pushFollow(FOLLOW_ruleInputSignal_in_entryRuleInputSignal181);
+            ruleInputSignal();
+
+            state._fsp--;
+
+             after(grammarAccess.getInputSignalRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleInputSignal188); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleInputSignal"
+
+
+    // $ANTLR start "ruleInputSignal"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:125:1: ruleInputSignal : ( ( rule__InputSignal__Group__0 ) ) ;
+    public final void ruleInputSignal() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:129:2: ( ( ( rule__InputSignal__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:130:1: ( ( rule__InputSignal__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:130:1: ( ( rule__InputSignal__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:131:1: ( rule__InputSignal__Group__0 )
+            {
+             before(grammarAccess.getInputSignalAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:132:1: ( rule__InputSignal__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:132:2: rule__InputSignal__Group__0
+            {
+            pushFollow(FOLLOW_rule__InputSignal__Group__0_in_ruleInputSignal214);
+            rule__InputSignal__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getInputSignalAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleInputSignal"
+
+
+    // $ANTLR start "entryRuleOutputSignal"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:144:1: entryRuleOutputSignal : ruleOutputSignal EOF ;
+    public final void entryRuleOutputSignal() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:145:1: ( ruleOutputSignal EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:146:1: ruleOutputSignal EOF
+            {
+             before(grammarAccess.getOutputSignalRule()); 
+            pushFollow(FOLLOW_ruleOutputSignal_in_entryRuleOutputSignal241);
+            ruleOutputSignal();
+
+            state._fsp--;
+
+             after(grammarAccess.getOutputSignalRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleOutputSignal248); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleOutputSignal"
+
+
+    // $ANTLR start "ruleOutputSignal"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:153:1: ruleOutputSignal : ( ( rule__OutputSignal__Group__0 ) ) ;
+    public final void ruleOutputSignal() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:157:2: ( ( ( rule__OutputSignal__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:158:1: ( ( rule__OutputSignal__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:158:1: ( ( rule__OutputSignal__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:159:1: ( rule__OutputSignal__Group__0 )
+            {
+             before(grammarAccess.getOutputSignalAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:160:1: ( rule__OutputSignal__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:160:2: rule__OutputSignal__Group__0
+            {
+            pushFollow(FOLLOW_rule__OutputSignal__Group__0_in_ruleOutputSignal274);
+            rule__OutputSignal__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getOutputSignalAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleOutputSignal"
+
+
+    // $ANTLR start "entryRuleState"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:172:1: entryRuleState : ruleState EOF ;
+    public final void entryRuleState() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:173:1: ( ruleState EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:174:1: ruleState EOF
+            {
+             before(grammarAccess.getStateRule()); 
+            pushFollow(FOLLOW_ruleState_in_entryRuleState301);
+            ruleState();
+
+            state._fsp--;
+
+             after(grammarAccess.getStateRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleState308); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleState"
+
+
+    // $ANTLR start "ruleState"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:181:1: ruleState : ( ( rule__State__Group__0 ) ) ;
+    public final void ruleState() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:185:2: ( ( ( rule__State__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:186:1: ( ( rule__State__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:186:1: ( ( rule__State__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:187:1: ( rule__State__Group__0 )
+            {
+             before(grammarAccess.getStateAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:188:1: ( rule__State__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:188:2: rule__State__Group__0
+            {
+            pushFollow(FOLLOW_rule__State__Group__0_in_ruleState334);
+            rule__State__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getStateAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleState"
+
+
+    // $ANTLR start "entryRuleTransition"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:200:1: entryRuleTransition : ruleTransition EOF ;
+    public final void entryRuleTransition() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:201:1: ( ruleTransition EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:202:1: ruleTransition EOF
+            {
+             before(grammarAccess.getTransitionRule()); 
+            pushFollow(FOLLOW_ruleTransition_in_entryRuleTransition361);
+            ruleTransition();
+
+            state._fsp--;
+
+             after(grammarAccess.getTransitionRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleTransition368); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleTransition"
+
+
+    // $ANTLR start "ruleTransition"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:209:1: ruleTransition : ( ( rule__Transition__Group__0 ) ) ;
+    public final void ruleTransition() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:213:2: ( ( ( rule__Transition__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:214:1: ( ( rule__Transition__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:214:1: ( ( rule__Transition__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:215:1: ( rule__Transition__Group__0 )
+            {
+             before(grammarAccess.getTransitionAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:216:1: ( rule__Transition__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:216:2: rule__Transition__Group__0
+            {
+            pushFollow(FOLLOW_rule__Transition__Group__0_in_ruleTransition394);
+            rule__Transition__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getTransitionAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleTransition"
+
+
+    // $ANTLR start "entryRuleCondition"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:228:1: entryRuleCondition : ruleCondition EOF ;
+    public final void entryRuleCondition() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:229:1: ( ruleCondition EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:230:1: ruleCondition EOF
+            {
+             before(grammarAccess.getConditionRule()); 
+            pushFollow(FOLLOW_ruleCondition_in_entryRuleCondition421);
+            ruleCondition();
+
+            state._fsp--;
+
+             after(grammarAccess.getConditionRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleCondition428); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleCondition"
+
+
+    // $ANTLR start "ruleCondition"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:237:1: ruleCondition : ( ( rule__Condition__Group__0 ) ) ;
+    public final void ruleCondition() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:241:2: ( ( ( rule__Condition__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:242:1: ( ( rule__Condition__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:242:1: ( ( rule__Condition__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:243:1: ( rule__Condition__Group__0 )
+            {
+             before(grammarAccess.getConditionAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:244:1: ( rule__Condition__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:244:2: rule__Condition__Group__0
+            {
+            pushFollow(FOLLOW_rule__Condition__Group__0_in_ruleCondition454);
+            rule__Condition__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getConditionAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleCondition"
+
+
+    // $ANTLR start "entryRuleEvent"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:256:1: entryRuleEvent : ruleEvent EOF ;
+    public final void entryRuleEvent() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:257:1: ( ruleEvent EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:258:1: ruleEvent EOF
+            {
+             before(grammarAccess.getEventRule()); 
+            pushFollow(FOLLOW_ruleEvent_in_entryRuleEvent481);
+            ruleEvent();
+
+            state._fsp--;
+
+             after(grammarAccess.getEventRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleEvent488); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleEvent"
+
+
+    // $ANTLR start "ruleEvent"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:265:1: ruleEvent : ( ( rule__Event__Group__0 ) ) ;
+    public final void ruleEvent() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:269:2: ( ( ( rule__Event__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:270:1: ( ( rule__Event__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:270:1: ( ( rule__Event__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:271:1: ( rule__Event__Group__0 )
+            {
+             before(grammarAccess.getEventAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:272:1: ( rule__Event__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:272:2: rule__Event__Group__0
+            {
+            pushFollow(FOLLOW_rule__Event__Group__0_in_ruleEvent514);
+            rule__Event__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getEventAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleEvent"
+
+
+    // $ANTLR start "entryRuleCommand"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:284:1: entryRuleCommand : ruleCommand EOF ;
+    public final void entryRuleCommand() throws RecognitionException {
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:285:1: ( ruleCommand EOF )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:286:1: ruleCommand EOF
+            {
+             before(grammarAccess.getCommandRule()); 
+            pushFollow(FOLLOW_ruleCommand_in_entryRuleCommand541);
+            ruleCommand();
+
+            state._fsp--;
+
+             after(grammarAccess.getCommandRule()); 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleCommand548); 
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return ;
+    }
+    // $ANTLR end "entryRuleCommand"
+
+
+    // $ANTLR start "ruleCommand"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:293:1: ruleCommand : ( ( rule__Command__Group__0 ) ) ;
+    public final void ruleCommand() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:297:2: ( ( ( rule__Command__Group__0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:298:1: ( ( rule__Command__Group__0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:298:1: ( ( rule__Command__Group__0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:299:1: ( rule__Command__Group__0 )
+            {
+             before(grammarAccess.getCommandAccess().getGroup()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:300:1: ( rule__Command__Group__0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:300:2: rule__Command__Group__0
+            {
+            pushFollow(FOLLOW_rule__Command__Group__0_in_ruleCommand574);
+            rule__Command__Group__0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getCommandAccess().getGroup()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "ruleCommand"
+
+
+    // $ANTLR start "rule__Signal__Alternatives_0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:312:1: rule__Signal__Alternatives_0 : ( ( ruleInputSignal ) | ( ruleOutputSignal ) );
+    public final void rule__Signal__Alternatives_0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:316:1: ( ( ruleInputSignal ) | ( ruleOutputSignal ) )
+            int alt1=2;
+            int LA1_0 = input.LA(1);
+
+            if ( (LA1_0==13) ) {
+                alt1=1;
+            }
+            else if ( (LA1_0==14) ) {
+                alt1=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 1, 0, input);
+
+                throw nvae;
+            }
+            switch (alt1) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:317:1: ( ruleInputSignal )
+                    {
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:317:1: ( ruleInputSignal )
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:318:1: ruleInputSignal
+                    {
+                     before(grammarAccess.getSignalAccess().getInputSignalParserRuleCall_0_0()); 
+                    pushFollow(FOLLOW_ruleInputSignal_in_rule__Signal__Alternatives_0610);
+                    ruleInputSignal();
+
+                    state._fsp--;
+
+                     after(grammarAccess.getSignalAccess().getInputSignalParserRuleCall_0_0()); 
+
+                    }
+
+
+                    }
+                    break;
+                case 2 :
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:323:6: ( ruleOutputSignal )
+                    {
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:323:6: ( ruleOutputSignal )
+                    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:324:1: ruleOutputSignal
+                    {
+                     before(grammarAccess.getSignalAccess().getOutputSignalParserRuleCall_0_1()); 
+                    pushFollow(FOLLOW_ruleOutputSignal_in_rule__Signal__Alternatives_0627);
+                    ruleOutputSignal();
+
+                    state._fsp--;
+
+                     after(grammarAccess.getSignalAccess().getOutputSignalParserRuleCall_0_1()); 
+
+                    }
+
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__Alternatives_0"
+
+
+    // $ANTLR start "rule__Statemachine__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:336:1: rule__Statemachine__Group__0 : rule__Statemachine__Group__0__Impl rule__Statemachine__Group__1 ;
+    public final void rule__Statemachine__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:340:1: ( rule__Statemachine__Group__0__Impl rule__Statemachine__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:341:2: rule__Statemachine__Group__0__Impl rule__Statemachine__Group__1
+            {
+            pushFollow(FOLLOW_rule__Statemachine__Group__0__Impl_in_rule__Statemachine__Group__0657);
+            rule__Statemachine__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Statemachine__Group__1_in_rule__Statemachine__Group__0660);
+            rule__Statemachine__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__Group__0"
+
+
+    // $ANTLR start "rule__Statemachine__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:348:1: rule__Statemachine__Group__0__Impl : ( () ) ;
+    public final void rule__Statemachine__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:352:1: ( ( () ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:353:1: ( () )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:353:1: ( () )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:354:1: ()
+            {
+             before(grammarAccess.getStatemachineAccess().getStatemachineAction_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:355:1: ()
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:357:1: 
+            {
+            }
+
+             after(grammarAccess.getStatemachineAccess().getStatemachineAction_0()); 
+
+            }
+
+
+            }
+
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__Group__0__Impl"
+
+
+    // $ANTLR start "rule__Statemachine__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:367:1: rule__Statemachine__Group__1 : rule__Statemachine__Group__1__Impl rule__Statemachine__Group__2 ;
+    public final void rule__Statemachine__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:371:1: ( rule__Statemachine__Group__1__Impl rule__Statemachine__Group__2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:372:2: rule__Statemachine__Group__1__Impl rule__Statemachine__Group__2
+            {
+            pushFollow(FOLLOW_rule__Statemachine__Group__1__Impl_in_rule__Statemachine__Group__1718);
+            rule__Statemachine__Group__1__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Statemachine__Group__2_in_rule__Statemachine__Group__1721);
+            rule__Statemachine__Group__2();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__Group__1"
+
+
+    // $ANTLR start "rule__Statemachine__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:379:1: rule__Statemachine__Group__1__Impl : ( ( rule__Statemachine__SignalsAssignment_1 )* ) ;
+    public final void rule__Statemachine__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:383:1: ( ( ( rule__Statemachine__SignalsAssignment_1 )* ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:384:1: ( ( rule__Statemachine__SignalsAssignment_1 )* )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:384:1: ( ( rule__Statemachine__SignalsAssignment_1 )* )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:385:1: ( rule__Statemachine__SignalsAssignment_1 )*
+            {
+             before(grammarAccess.getStatemachineAccess().getSignalsAssignment_1()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:386:1: ( rule__Statemachine__SignalsAssignment_1 )*
+            loop2:
+            do {
+                int alt2=2;
+                int LA2_0 = input.LA(1);
+
+                if ( ((LA2_0>=13 && LA2_0<=14)) ) {
+                    alt2=1;
+                }
+
+
+                switch (alt2) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:386:2: rule__Statemachine__SignalsAssignment_1
+            	    {
+            	    pushFollow(FOLLOW_rule__Statemachine__SignalsAssignment_1_in_rule__Statemachine__Group__1__Impl748);
+            	    rule__Statemachine__SignalsAssignment_1();
+
+            	    state._fsp--;
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop2;
+                }
+            } while (true);
+
+             after(grammarAccess.getStatemachineAccess().getSignalsAssignment_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__Group__1__Impl"
+
+
+    // $ANTLR start "rule__Statemachine__Group__2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:396:1: rule__Statemachine__Group__2 : rule__Statemachine__Group__2__Impl ;
+    public final void rule__Statemachine__Group__2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:400:1: ( rule__Statemachine__Group__2__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:401:2: rule__Statemachine__Group__2__Impl
+            {
+            pushFollow(FOLLOW_rule__Statemachine__Group__2__Impl_in_rule__Statemachine__Group__2779);
+            rule__Statemachine__Group__2__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__Group__2"
+
+
+    // $ANTLR start "rule__Statemachine__Group__2__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:407:1: rule__Statemachine__Group__2__Impl : ( ( rule__Statemachine__StatesAssignment_2 )* ) ;
+    public final void rule__Statemachine__Group__2__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:411:1: ( ( ( rule__Statemachine__StatesAssignment_2 )* ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:412:1: ( ( rule__Statemachine__StatesAssignment_2 )* )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:412:1: ( ( rule__Statemachine__StatesAssignment_2 )* )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:413:1: ( rule__Statemachine__StatesAssignment_2 )*
+            {
+             before(grammarAccess.getStatemachineAccess().getStatesAssignment_2()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:414:1: ( rule__Statemachine__StatesAssignment_2 )*
+            loop3:
+            do {
+                int alt3=2;
+                int LA3_0 = input.LA(1);
+
+                if ( (LA3_0==15) ) {
+                    alt3=1;
+                }
+
+
+                switch (alt3) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:414:2: rule__Statemachine__StatesAssignment_2
+            	    {
+            	    pushFollow(FOLLOW_rule__Statemachine__StatesAssignment_2_in_rule__Statemachine__Group__2__Impl806);
+            	    rule__Statemachine__StatesAssignment_2();
+
+            	    state._fsp--;
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop3;
+                }
+            } while (true);
+
+             after(grammarAccess.getStatemachineAccess().getStatesAssignment_2()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__Group__2__Impl"
+
+
+    // $ANTLR start "rule__Signal__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:430:1: rule__Signal__Group__0 : rule__Signal__Group__0__Impl rule__Signal__Group__1 ;
+    public final void rule__Signal__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:434:1: ( rule__Signal__Group__0__Impl rule__Signal__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:435:2: rule__Signal__Group__0__Impl rule__Signal__Group__1
+            {
+            pushFollow(FOLLOW_rule__Signal__Group__0__Impl_in_rule__Signal__Group__0843);
+            rule__Signal__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Signal__Group__1_in_rule__Signal__Group__0846);
+            rule__Signal__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__Group__0"
+
+
+    // $ANTLR start "rule__Signal__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:442:1: rule__Signal__Group__0__Impl : ( ( rule__Signal__Alternatives_0 ) ) ;
+    public final void rule__Signal__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:446:1: ( ( ( rule__Signal__Alternatives_0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:447:1: ( ( rule__Signal__Alternatives_0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:447:1: ( ( rule__Signal__Alternatives_0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:448:1: ( rule__Signal__Alternatives_0 )
+            {
+             before(grammarAccess.getSignalAccess().getAlternatives_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:449:1: ( rule__Signal__Alternatives_0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:449:2: rule__Signal__Alternatives_0
+            {
+            pushFollow(FOLLOW_rule__Signal__Alternatives_0_in_rule__Signal__Group__0__Impl873);
+            rule__Signal__Alternatives_0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getSignalAccess().getAlternatives_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__Group__0__Impl"
+
+
+    // $ANTLR start "rule__Signal__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:459:1: rule__Signal__Group__1 : rule__Signal__Group__1__Impl rule__Signal__Group__2 ;
+    public final void rule__Signal__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:463:1: ( rule__Signal__Group__1__Impl rule__Signal__Group__2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:464:2: rule__Signal__Group__1__Impl rule__Signal__Group__2
+            {
+            pushFollow(FOLLOW_rule__Signal__Group__1__Impl_in_rule__Signal__Group__1903);
+            rule__Signal__Group__1__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Signal__Group__2_in_rule__Signal__Group__1906);
+            rule__Signal__Group__2();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__Group__1"
+
+
+    // $ANTLR start "rule__Signal__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:471:1: rule__Signal__Group__1__Impl : ( 'signal' ) ;
+    public final void rule__Signal__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:475:1: ( ( 'signal' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:476:1: ( 'signal' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:476:1: ( 'signal' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:477:1: 'signal'
+            {
+             before(grammarAccess.getSignalAccess().getSignalKeyword_1()); 
+            match(input,12,FOLLOW_12_in_rule__Signal__Group__1__Impl934); 
+             after(grammarAccess.getSignalAccess().getSignalKeyword_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__Group__1__Impl"
+
+
+    // $ANTLR start "rule__Signal__Group__2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:490:1: rule__Signal__Group__2 : rule__Signal__Group__2__Impl ;
+    public final void rule__Signal__Group__2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:494:1: ( rule__Signal__Group__2__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:495:2: rule__Signal__Group__2__Impl
+            {
+            pushFollow(FOLLOW_rule__Signal__Group__2__Impl_in_rule__Signal__Group__2965);
+            rule__Signal__Group__2__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__Group__2"
+
+
+    // $ANTLR start "rule__Signal__Group__2__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:501:1: rule__Signal__Group__2__Impl : ( ( rule__Signal__NameAssignment_2 ) ) ;
+    public final void rule__Signal__Group__2__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:505:1: ( ( ( rule__Signal__NameAssignment_2 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:506:1: ( ( rule__Signal__NameAssignment_2 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:506:1: ( ( rule__Signal__NameAssignment_2 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:507:1: ( rule__Signal__NameAssignment_2 )
+            {
+             before(grammarAccess.getSignalAccess().getNameAssignment_2()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:508:1: ( rule__Signal__NameAssignment_2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:508:2: rule__Signal__NameAssignment_2
+            {
+            pushFollow(FOLLOW_rule__Signal__NameAssignment_2_in_rule__Signal__Group__2__Impl992);
+            rule__Signal__NameAssignment_2();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getSignalAccess().getNameAssignment_2()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__Group__2__Impl"
+
+
+    // $ANTLR start "rule__InputSignal__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:524:1: rule__InputSignal__Group__0 : rule__InputSignal__Group__0__Impl rule__InputSignal__Group__1 ;
+    public final void rule__InputSignal__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:528:1: ( rule__InputSignal__Group__0__Impl rule__InputSignal__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:529:2: rule__InputSignal__Group__0__Impl rule__InputSignal__Group__1
+            {
+            pushFollow(FOLLOW_rule__InputSignal__Group__0__Impl_in_rule__InputSignal__Group__01028);
+            rule__InputSignal__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__InputSignal__Group__1_in_rule__InputSignal__Group__01031);
+            rule__InputSignal__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__InputSignal__Group__0"
+
+
+    // $ANTLR start "rule__InputSignal__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:536:1: rule__InputSignal__Group__0__Impl : ( () ) ;
+    public final void rule__InputSignal__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:540:1: ( ( () ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:541:1: ( () )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:541:1: ( () )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:542:1: ()
+            {
+             before(grammarAccess.getInputSignalAccess().getInputSignalAction_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:543:1: ()
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:545:1: 
+            {
+            }
+
+             after(grammarAccess.getInputSignalAccess().getInputSignalAction_0()); 
+
+            }
+
+
+            }
+
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__InputSignal__Group__0__Impl"
+
+
+    // $ANTLR start "rule__InputSignal__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:555:1: rule__InputSignal__Group__1 : rule__InputSignal__Group__1__Impl ;
+    public final void rule__InputSignal__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:559:1: ( rule__InputSignal__Group__1__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:560:2: rule__InputSignal__Group__1__Impl
+            {
+            pushFollow(FOLLOW_rule__InputSignal__Group__1__Impl_in_rule__InputSignal__Group__11089);
+            rule__InputSignal__Group__1__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__InputSignal__Group__1"
+
+
+    // $ANTLR start "rule__InputSignal__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:566:1: rule__InputSignal__Group__1__Impl : ( 'input' ) ;
+    public final void rule__InputSignal__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:570:1: ( ( 'input' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:571:1: ( 'input' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:571:1: ( 'input' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:572:1: 'input'
+            {
+             before(grammarAccess.getInputSignalAccess().getInputKeyword_1()); 
+            match(input,13,FOLLOW_13_in_rule__InputSignal__Group__1__Impl1117); 
+             after(grammarAccess.getInputSignalAccess().getInputKeyword_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__InputSignal__Group__1__Impl"
+
+
+    // $ANTLR start "rule__OutputSignal__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:589:1: rule__OutputSignal__Group__0 : rule__OutputSignal__Group__0__Impl rule__OutputSignal__Group__1 ;
+    public final void rule__OutputSignal__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:593:1: ( rule__OutputSignal__Group__0__Impl rule__OutputSignal__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:594:2: rule__OutputSignal__Group__0__Impl rule__OutputSignal__Group__1
+            {
+            pushFollow(FOLLOW_rule__OutputSignal__Group__0__Impl_in_rule__OutputSignal__Group__01152);
+            rule__OutputSignal__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__OutputSignal__Group__1_in_rule__OutputSignal__Group__01155);
+            rule__OutputSignal__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__OutputSignal__Group__0"
+
+
+    // $ANTLR start "rule__OutputSignal__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:601:1: rule__OutputSignal__Group__0__Impl : ( () ) ;
+    public final void rule__OutputSignal__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:605:1: ( ( () ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:606:1: ( () )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:606:1: ( () )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:607:1: ()
+            {
+             before(grammarAccess.getOutputSignalAccess().getOutputSignalAction_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:608:1: ()
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:610:1: 
+            {
+            }
+
+             after(grammarAccess.getOutputSignalAccess().getOutputSignalAction_0()); 
+
+            }
+
+
+            }
+
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__OutputSignal__Group__0__Impl"
+
+
+    // $ANTLR start "rule__OutputSignal__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:620:1: rule__OutputSignal__Group__1 : rule__OutputSignal__Group__1__Impl ;
+    public final void rule__OutputSignal__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:624:1: ( rule__OutputSignal__Group__1__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:625:2: rule__OutputSignal__Group__1__Impl
+            {
+            pushFollow(FOLLOW_rule__OutputSignal__Group__1__Impl_in_rule__OutputSignal__Group__11213);
+            rule__OutputSignal__Group__1__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__OutputSignal__Group__1"
+
+
+    // $ANTLR start "rule__OutputSignal__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:631:1: rule__OutputSignal__Group__1__Impl : ( 'output' ) ;
+    public final void rule__OutputSignal__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:635:1: ( ( 'output' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:636:1: ( 'output' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:636:1: ( 'output' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:637:1: 'output'
+            {
+             before(grammarAccess.getOutputSignalAccess().getOutputKeyword_1()); 
+            match(input,14,FOLLOW_14_in_rule__OutputSignal__Group__1__Impl1241); 
+             after(grammarAccess.getOutputSignalAccess().getOutputKeyword_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__OutputSignal__Group__1__Impl"
+
+
+    // $ANTLR start "rule__State__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:654:1: rule__State__Group__0 : rule__State__Group__0__Impl rule__State__Group__1 ;
+    public final void rule__State__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:658:1: ( rule__State__Group__0__Impl rule__State__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:659:2: rule__State__Group__0__Impl rule__State__Group__1
+            {
+            pushFollow(FOLLOW_rule__State__Group__0__Impl_in_rule__State__Group__01276);
+            rule__State__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__State__Group__1_in_rule__State__Group__01279);
+            rule__State__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__0"
+
+
+    // $ANTLR start "rule__State__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:666:1: rule__State__Group__0__Impl : ( 'state' ) ;
+    public final void rule__State__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:670:1: ( ( 'state' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:671:1: ( 'state' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:671:1: ( 'state' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:672:1: 'state'
+            {
+             before(grammarAccess.getStateAccess().getStateKeyword_0()); 
+            match(input,15,FOLLOW_15_in_rule__State__Group__0__Impl1307); 
+             after(grammarAccess.getStateAccess().getStateKeyword_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__0__Impl"
+
+
+    // $ANTLR start "rule__State__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:685:1: rule__State__Group__1 : rule__State__Group__1__Impl rule__State__Group__2 ;
+    public final void rule__State__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:689:1: ( rule__State__Group__1__Impl rule__State__Group__2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:690:2: rule__State__Group__1__Impl rule__State__Group__2
+            {
+            pushFollow(FOLLOW_rule__State__Group__1__Impl_in_rule__State__Group__11338);
+            rule__State__Group__1__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__State__Group__2_in_rule__State__Group__11341);
+            rule__State__Group__2();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__1"
+
+
+    // $ANTLR start "rule__State__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:697:1: rule__State__Group__1__Impl : ( ( rule__State__NameAssignment_1 ) ) ;
+    public final void rule__State__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:701:1: ( ( ( rule__State__NameAssignment_1 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:702:1: ( ( rule__State__NameAssignment_1 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:702:1: ( ( rule__State__NameAssignment_1 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:703:1: ( rule__State__NameAssignment_1 )
+            {
+             before(grammarAccess.getStateAccess().getNameAssignment_1()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:704:1: ( rule__State__NameAssignment_1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:704:2: rule__State__NameAssignment_1
+            {
+            pushFollow(FOLLOW_rule__State__NameAssignment_1_in_rule__State__Group__1__Impl1368);
+            rule__State__NameAssignment_1();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getStateAccess().getNameAssignment_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__1__Impl"
+
+
+    // $ANTLR start "rule__State__Group__2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:714:1: rule__State__Group__2 : rule__State__Group__2__Impl rule__State__Group__3 ;
+    public final void rule__State__Group__2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:718:1: ( rule__State__Group__2__Impl rule__State__Group__3 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:719:2: rule__State__Group__2__Impl rule__State__Group__3
+            {
+            pushFollow(FOLLOW_rule__State__Group__2__Impl_in_rule__State__Group__21398);
+            rule__State__Group__2__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__State__Group__3_in_rule__State__Group__21401);
+            rule__State__Group__3();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__2"
+
+
+    // $ANTLR start "rule__State__Group__2__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:726:1: rule__State__Group__2__Impl : ( ( rule__State__CommandsAssignment_2 )* ) ;
+    public final void rule__State__Group__2__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:730:1: ( ( ( rule__State__CommandsAssignment_2 )* ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:731:1: ( ( rule__State__CommandsAssignment_2 )* )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:731:1: ( ( rule__State__CommandsAssignment_2 )* )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:732:1: ( rule__State__CommandsAssignment_2 )*
+            {
+             before(grammarAccess.getStateAccess().getCommandsAssignment_2()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:733:1: ( rule__State__CommandsAssignment_2 )*
+            loop4:
+            do {
+                int alt4=2;
+                int LA4_0 = input.LA(1);
+
+                if ( (LA4_0==21) ) {
+                    alt4=1;
+                }
+
+
+                switch (alt4) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:733:2: rule__State__CommandsAssignment_2
+            	    {
+            	    pushFollow(FOLLOW_rule__State__CommandsAssignment_2_in_rule__State__Group__2__Impl1428);
+            	    rule__State__CommandsAssignment_2();
+
+            	    state._fsp--;
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop4;
+                }
+            } while (true);
+
+             after(grammarAccess.getStateAccess().getCommandsAssignment_2()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__2__Impl"
+
+
+    // $ANTLR start "rule__State__Group__3"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:743:1: rule__State__Group__3 : rule__State__Group__3__Impl rule__State__Group__4 ;
+    public final void rule__State__Group__3() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:747:1: ( rule__State__Group__3__Impl rule__State__Group__4 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:748:2: rule__State__Group__3__Impl rule__State__Group__4
+            {
+            pushFollow(FOLLOW_rule__State__Group__3__Impl_in_rule__State__Group__31459);
+            rule__State__Group__3__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__State__Group__4_in_rule__State__Group__31462);
+            rule__State__Group__4();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__3"
+
+
+    // $ANTLR start "rule__State__Group__3__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:755:1: rule__State__Group__3__Impl : ( ( rule__State__TransitionsAssignment_3 )* ) ;
+    public final void rule__State__Group__3__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:759:1: ( ( ( rule__State__TransitionsAssignment_3 )* ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:760:1: ( ( rule__State__TransitionsAssignment_3 )* )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:760:1: ( ( rule__State__TransitionsAssignment_3 )* )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:761:1: ( rule__State__TransitionsAssignment_3 )*
+            {
+             before(grammarAccess.getStateAccess().getTransitionsAssignment_3()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:762:1: ( rule__State__TransitionsAssignment_3 )*
+            loop5:
+            do {
+                int alt5=2;
+                int LA5_0 = input.LA(1);
+
+                if ( (LA5_0==17) ) {
+                    alt5=1;
+                }
+
+
+                switch (alt5) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:762:2: rule__State__TransitionsAssignment_3
+            	    {
+            	    pushFollow(FOLLOW_rule__State__TransitionsAssignment_3_in_rule__State__Group__3__Impl1489);
+            	    rule__State__TransitionsAssignment_3();
+
+            	    state._fsp--;
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop5;
+                }
+            } while (true);
+
+             after(grammarAccess.getStateAccess().getTransitionsAssignment_3()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__3__Impl"
+
+
+    // $ANTLR start "rule__State__Group__4"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:772:1: rule__State__Group__4 : rule__State__Group__4__Impl ;
+    public final void rule__State__Group__4() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:776:1: ( rule__State__Group__4__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:777:2: rule__State__Group__4__Impl
+            {
+            pushFollow(FOLLOW_rule__State__Group__4__Impl_in_rule__State__Group__41520);
+            rule__State__Group__4__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__4"
+
+
+    // $ANTLR start "rule__State__Group__4__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:783:1: rule__State__Group__4__Impl : ( 'end' ) ;
+    public final void rule__State__Group__4__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:787:1: ( ( 'end' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:788:1: ( 'end' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:788:1: ( 'end' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:789:1: 'end'
+            {
+             before(grammarAccess.getStateAccess().getEndKeyword_4()); 
+            match(input,16,FOLLOW_16_in_rule__State__Group__4__Impl1548); 
+             after(grammarAccess.getStateAccess().getEndKeyword_4()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__Group__4__Impl"
+
+
+    // $ANTLR start "rule__Transition__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:812:1: rule__Transition__Group__0 : rule__Transition__Group__0__Impl rule__Transition__Group__1 ;
+    public final void rule__Transition__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:816:1: ( rule__Transition__Group__0__Impl rule__Transition__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:817:2: rule__Transition__Group__0__Impl rule__Transition__Group__1
+            {
+            pushFollow(FOLLOW_rule__Transition__Group__0__Impl_in_rule__Transition__Group__01589);
+            rule__Transition__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Transition__Group__1_in_rule__Transition__Group__01592);
+            rule__Transition__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__0"
+
+
+    // $ANTLR start "rule__Transition__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:824:1: rule__Transition__Group__0__Impl : ( 'if' ) ;
+    public final void rule__Transition__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:828:1: ( ( 'if' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:829:1: ( 'if' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:829:1: ( 'if' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:830:1: 'if'
+            {
+             before(grammarAccess.getTransitionAccess().getIfKeyword_0()); 
+            match(input,17,FOLLOW_17_in_rule__Transition__Group__0__Impl1620); 
+             after(grammarAccess.getTransitionAccess().getIfKeyword_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__0__Impl"
+
+
+    // $ANTLR start "rule__Transition__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:843:1: rule__Transition__Group__1 : rule__Transition__Group__1__Impl rule__Transition__Group__2 ;
+    public final void rule__Transition__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:847:1: ( rule__Transition__Group__1__Impl rule__Transition__Group__2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:848:2: rule__Transition__Group__1__Impl rule__Transition__Group__2
+            {
+            pushFollow(FOLLOW_rule__Transition__Group__1__Impl_in_rule__Transition__Group__11651);
+            rule__Transition__Group__1__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Transition__Group__2_in_rule__Transition__Group__11654);
+            rule__Transition__Group__2();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__1"
+
+
+    // $ANTLR start "rule__Transition__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:855:1: rule__Transition__Group__1__Impl : ( ( rule__Transition__ConditionAssignment_1 ) ) ;
+    public final void rule__Transition__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:859:1: ( ( ( rule__Transition__ConditionAssignment_1 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:860:1: ( ( rule__Transition__ConditionAssignment_1 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:860:1: ( ( rule__Transition__ConditionAssignment_1 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:861:1: ( rule__Transition__ConditionAssignment_1 )
+            {
+             before(grammarAccess.getTransitionAccess().getConditionAssignment_1()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:862:1: ( rule__Transition__ConditionAssignment_1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:862:2: rule__Transition__ConditionAssignment_1
+            {
+            pushFollow(FOLLOW_rule__Transition__ConditionAssignment_1_in_rule__Transition__Group__1__Impl1681);
+            rule__Transition__ConditionAssignment_1();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getTransitionAccess().getConditionAssignment_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__1__Impl"
+
+
+    // $ANTLR start "rule__Transition__Group__2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:872:1: rule__Transition__Group__2 : rule__Transition__Group__2__Impl rule__Transition__Group__3 ;
+    public final void rule__Transition__Group__2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:876:1: ( rule__Transition__Group__2__Impl rule__Transition__Group__3 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:877:2: rule__Transition__Group__2__Impl rule__Transition__Group__3
+            {
+            pushFollow(FOLLOW_rule__Transition__Group__2__Impl_in_rule__Transition__Group__21711);
+            rule__Transition__Group__2__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Transition__Group__3_in_rule__Transition__Group__21714);
+            rule__Transition__Group__3();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__2"
+
+
+    // $ANTLR start "rule__Transition__Group__2__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:884:1: rule__Transition__Group__2__Impl : ( 'goto' ) ;
+    public final void rule__Transition__Group__2__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:888:1: ( ( 'goto' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:889:1: ( 'goto' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:889:1: ( 'goto' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:890:1: 'goto'
+            {
+             before(grammarAccess.getTransitionAccess().getGotoKeyword_2()); 
+            match(input,18,FOLLOW_18_in_rule__Transition__Group__2__Impl1742); 
+             after(grammarAccess.getTransitionAccess().getGotoKeyword_2()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__2__Impl"
+
+
+    // $ANTLR start "rule__Transition__Group__3"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:903:1: rule__Transition__Group__3 : rule__Transition__Group__3__Impl ;
+    public final void rule__Transition__Group__3() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:907:1: ( rule__Transition__Group__3__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:908:2: rule__Transition__Group__3__Impl
+            {
+            pushFollow(FOLLOW_rule__Transition__Group__3__Impl_in_rule__Transition__Group__31773);
+            rule__Transition__Group__3__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__3"
+
+
+    // $ANTLR start "rule__Transition__Group__3__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:914:1: rule__Transition__Group__3__Impl : ( ( rule__Transition__StateAssignment_3 ) ) ;
+    public final void rule__Transition__Group__3__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:918:1: ( ( ( rule__Transition__StateAssignment_3 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:919:1: ( ( rule__Transition__StateAssignment_3 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:919:1: ( ( rule__Transition__StateAssignment_3 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:920:1: ( rule__Transition__StateAssignment_3 )
+            {
+             before(grammarAccess.getTransitionAccess().getStateAssignment_3()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:921:1: ( rule__Transition__StateAssignment_3 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:921:2: rule__Transition__StateAssignment_3
+            {
+            pushFollow(FOLLOW_rule__Transition__StateAssignment_3_in_rule__Transition__Group__3__Impl1800);
+            rule__Transition__StateAssignment_3();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getTransitionAccess().getStateAssignment_3()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__Group__3__Impl"
+
+
+    // $ANTLR start "rule__Condition__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:939:1: rule__Condition__Group__0 : rule__Condition__Group__0__Impl rule__Condition__Group__1 ;
+    public final void rule__Condition__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:943:1: ( rule__Condition__Group__0__Impl rule__Condition__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:944:2: rule__Condition__Group__0__Impl rule__Condition__Group__1
+            {
+            pushFollow(FOLLOW_rule__Condition__Group__0__Impl_in_rule__Condition__Group__01838);
+            rule__Condition__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Condition__Group__1_in_rule__Condition__Group__01841);
+            rule__Condition__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group__0"
+
+
+    // $ANTLR start "rule__Condition__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:951:1: rule__Condition__Group__0__Impl : ( ( rule__Condition__EventsAssignment_0 ) ) ;
+    public final void rule__Condition__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:955:1: ( ( ( rule__Condition__EventsAssignment_0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:956:1: ( ( rule__Condition__EventsAssignment_0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:956:1: ( ( rule__Condition__EventsAssignment_0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:957:1: ( rule__Condition__EventsAssignment_0 )
+            {
+             before(grammarAccess.getConditionAccess().getEventsAssignment_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:958:1: ( rule__Condition__EventsAssignment_0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:958:2: rule__Condition__EventsAssignment_0
+            {
+            pushFollow(FOLLOW_rule__Condition__EventsAssignment_0_in_rule__Condition__Group__0__Impl1868);
+            rule__Condition__EventsAssignment_0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getConditionAccess().getEventsAssignment_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group__0__Impl"
+
+
+    // $ANTLR start "rule__Condition__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:968:1: rule__Condition__Group__1 : rule__Condition__Group__1__Impl ;
+    public final void rule__Condition__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:972:1: ( rule__Condition__Group__1__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:973:2: rule__Condition__Group__1__Impl
+            {
+            pushFollow(FOLLOW_rule__Condition__Group__1__Impl_in_rule__Condition__Group__11898);
+            rule__Condition__Group__1__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group__1"
+
+
+    // $ANTLR start "rule__Condition__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:979:1: rule__Condition__Group__1__Impl : ( ( rule__Condition__Group_1__0 )* ) ;
+    public final void rule__Condition__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:983:1: ( ( ( rule__Condition__Group_1__0 )* ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:984:1: ( ( rule__Condition__Group_1__0 )* )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:984:1: ( ( rule__Condition__Group_1__0 )* )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:985:1: ( rule__Condition__Group_1__0 )*
+            {
+             before(grammarAccess.getConditionAccess().getGroup_1()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:986:1: ( rule__Condition__Group_1__0 )*
+            loop6:
+            do {
+                int alt6=2;
+                int LA6_0 = input.LA(1);
+
+                if ( (LA6_0==19) ) {
+                    alt6=1;
+                }
+
+
+                switch (alt6) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:986:2: rule__Condition__Group_1__0
+            	    {
+            	    pushFollow(FOLLOW_rule__Condition__Group_1__0_in_rule__Condition__Group__1__Impl1925);
+            	    rule__Condition__Group_1__0();
+
+            	    state._fsp--;
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop6;
+                }
+            } while (true);
+
+             after(grammarAccess.getConditionAccess().getGroup_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group__1__Impl"
+
+
+    // $ANTLR start "rule__Condition__Group_1__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1000:1: rule__Condition__Group_1__0 : rule__Condition__Group_1__0__Impl rule__Condition__Group_1__1 ;
+    public final void rule__Condition__Group_1__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1004:1: ( rule__Condition__Group_1__0__Impl rule__Condition__Group_1__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1005:2: rule__Condition__Group_1__0__Impl rule__Condition__Group_1__1
+            {
+            pushFollow(FOLLOW_rule__Condition__Group_1__0__Impl_in_rule__Condition__Group_1__01960);
+            rule__Condition__Group_1__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Condition__Group_1__1_in_rule__Condition__Group_1__01963);
+            rule__Condition__Group_1__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group_1__0"
+
+
+    // $ANTLR start "rule__Condition__Group_1__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1012:1: rule__Condition__Group_1__0__Impl : ( 'and' ) ;
+    public final void rule__Condition__Group_1__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1016:1: ( ( 'and' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1017:1: ( 'and' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1017:1: ( 'and' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1018:1: 'and'
+            {
+             before(grammarAccess.getConditionAccess().getAndKeyword_1_0()); 
+            match(input,19,FOLLOW_19_in_rule__Condition__Group_1__0__Impl1991); 
+             after(grammarAccess.getConditionAccess().getAndKeyword_1_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group_1__0__Impl"
+
+
+    // $ANTLR start "rule__Condition__Group_1__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1031:1: rule__Condition__Group_1__1 : rule__Condition__Group_1__1__Impl ;
+    public final void rule__Condition__Group_1__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1035:1: ( rule__Condition__Group_1__1__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1036:2: rule__Condition__Group_1__1__Impl
+            {
+            pushFollow(FOLLOW_rule__Condition__Group_1__1__Impl_in_rule__Condition__Group_1__12022);
+            rule__Condition__Group_1__1__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group_1__1"
+
+
+    // $ANTLR start "rule__Condition__Group_1__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1042:1: rule__Condition__Group_1__1__Impl : ( ( rule__Condition__EventsAssignment_1_1 ) ) ;
+    public final void rule__Condition__Group_1__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1046:1: ( ( ( rule__Condition__EventsAssignment_1_1 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1047:1: ( ( rule__Condition__EventsAssignment_1_1 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1047:1: ( ( rule__Condition__EventsAssignment_1_1 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1048:1: ( rule__Condition__EventsAssignment_1_1 )
+            {
+             before(grammarAccess.getConditionAccess().getEventsAssignment_1_1()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1049:1: ( rule__Condition__EventsAssignment_1_1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1049:2: rule__Condition__EventsAssignment_1_1
+            {
+            pushFollow(FOLLOW_rule__Condition__EventsAssignment_1_1_in_rule__Condition__Group_1__1__Impl2049);
+            rule__Condition__EventsAssignment_1_1();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getConditionAccess().getEventsAssignment_1_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__Group_1__1__Impl"
+
+
+    // $ANTLR start "rule__Event__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1063:1: rule__Event__Group__0 : rule__Event__Group__0__Impl rule__Event__Group__1 ;
+    public final void rule__Event__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1067:1: ( rule__Event__Group__0__Impl rule__Event__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1068:2: rule__Event__Group__0__Impl rule__Event__Group__1
+            {
+            pushFollow(FOLLOW_rule__Event__Group__0__Impl_in_rule__Event__Group__02083);
+            rule__Event__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Event__Group__1_in_rule__Event__Group__02086);
+            rule__Event__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__Group__0"
+
+
+    // $ANTLR start "rule__Event__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1075:1: rule__Event__Group__0__Impl : ( ( rule__Event__SignalAssignment_0 ) ) ;
+    public final void rule__Event__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1079:1: ( ( ( rule__Event__SignalAssignment_0 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1080:1: ( ( rule__Event__SignalAssignment_0 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1080:1: ( ( rule__Event__SignalAssignment_0 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1081:1: ( rule__Event__SignalAssignment_0 )
+            {
+             before(grammarAccess.getEventAccess().getSignalAssignment_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1082:1: ( rule__Event__SignalAssignment_0 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1082:2: rule__Event__SignalAssignment_0
+            {
+            pushFollow(FOLLOW_rule__Event__SignalAssignment_0_in_rule__Event__Group__0__Impl2113);
+            rule__Event__SignalAssignment_0();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getEventAccess().getSignalAssignment_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__Group__0__Impl"
+
+
+    // $ANTLR start "rule__Event__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1092:1: rule__Event__Group__1 : rule__Event__Group__1__Impl rule__Event__Group__2 ;
+    public final void rule__Event__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1096:1: ( rule__Event__Group__1__Impl rule__Event__Group__2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1097:2: rule__Event__Group__1__Impl rule__Event__Group__2
+            {
+            pushFollow(FOLLOW_rule__Event__Group__1__Impl_in_rule__Event__Group__12143);
+            rule__Event__Group__1__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Event__Group__2_in_rule__Event__Group__12146);
+            rule__Event__Group__2();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__Group__1"
+
+
+    // $ANTLR start "rule__Event__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1104:1: rule__Event__Group__1__Impl : ( '==' ) ;
+    public final void rule__Event__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1108:1: ( ( '==' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1109:1: ( '==' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1109:1: ( '==' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1110:1: '=='
+            {
+             before(grammarAccess.getEventAccess().getEqualsSignEqualsSignKeyword_1()); 
+            match(input,20,FOLLOW_20_in_rule__Event__Group__1__Impl2174); 
+             after(grammarAccess.getEventAccess().getEqualsSignEqualsSignKeyword_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__Group__1__Impl"
+
+
+    // $ANTLR start "rule__Event__Group__2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1123:1: rule__Event__Group__2 : rule__Event__Group__2__Impl ;
+    public final void rule__Event__Group__2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1127:1: ( rule__Event__Group__2__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1128:2: rule__Event__Group__2__Impl
+            {
+            pushFollow(FOLLOW_rule__Event__Group__2__Impl_in_rule__Event__Group__22205);
+            rule__Event__Group__2__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__Group__2"
+
+
+    // $ANTLR start "rule__Event__Group__2__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1134:1: rule__Event__Group__2__Impl : ( ( rule__Event__ValueAssignment_2 ) ) ;
+    public final void rule__Event__Group__2__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1138:1: ( ( ( rule__Event__ValueAssignment_2 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1139:1: ( ( rule__Event__ValueAssignment_2 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1139:1: ( ( rule__Event__ValueAssignment_2 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1140:1: ( rule__Event__ValueAssignment_2 )
+            {
+             before(grammarAccess.getEventAccess().getValueAssignment_2()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1141:1: ( rule__Event__ValueAssignment_2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1141:2: rule__Event__ValueAssignment_2
+            {
+            pushFollow(FOLLOW_rule__Event__ValueAssignment_2_in_rule__Event__Group__2__Impl2232);
+            rule__Event__ValueAssignment_2();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getEventAccess().getValueAssignment_2()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__Group__2__Impl"
+
+
+    // $ANTLR start "rule__Command__Group__0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1157:1: rule__Command__Group__0 : rule__Command__Group__0__Impl rule__Command__Group__1 ;
+    public final void rule__Command__Group__0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1161:1: ( rule__Command__Group__0__Impl rule__Command__Group__1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1162:2: rule__Command__Group__0__Impl rule__Command__Group__1
+            {
+            pushFollow(FOLLOW_rule__Command__Group__0__Impl_in_rule__Command__Group__02268);
+            rule__Command__Group__0__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Command__Group__1_in_rule__Command__Group__02271);
+            rule__Command__Group__1();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__0"
+
+
+    // $ANTLR start "rule__Command__Group__0__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1169:1: rule__Command__Group__0__Impl : ( 'set' ) ;
+    public final void rule__Command__Group__0__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1173:1: ( ( 'set' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1174:1: ( 'set' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1174:1: ( 'set' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1175:1: 'set'
+            {
+             before(grammarAccess.getCommandAccess().getSetKeyword_0()); 
+            match(input,21,FOLLOW_21_in_rule__Command__Group__0__Impl2299); 
+             after(grammarAccess.getCommandAccess().getSetKeyword_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__0__Impl"
+
+
+    // $ANTLR start "rule__Command__Group__1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1188:1: rule__Command__Group__1 : rule__Command__Group__1__Impl rule__Command__Group__2 ;
+    public final void rule__Command__Group__1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1192:1: ( rule__Command__Group__1__Impl rule__Command__Group__2 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1193:2: rule__Command__Group__1__Impl rule__Command__Group__2
+            {
+            pushFollow(FOLLOW_rule__Command__Group__1__Impl_in_rule__Command__Group__12330);
+            rule__Command__Group__1__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Command__Group__2_in_rule__Command__Group__12333);
+            rule__Command__Group__2();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__1"
+
+
+    // $ANTLR start "rule__Command__Group__1__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1200:1: rule__Command__Group__1__Impl : ( ( rule__Command__SignalAssignment_1 ) ) ;
+    public final void rule__Command__Group__1__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1204:1: ( ( ( rule__Command__SignalAssignment_1 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1205:1: ( ( rule__Command__SignalAssignment_1 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1205:1: ( ( rule__Command__SignalAssignment_1 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1206:1: ( rule__Command__SignalAssignment_1 )
+            {
+             before(grammarAccess.getCommandAccess().getSignalAssignment_1()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1207:1: ( rule__Command__SignalAssignment_1 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1207:2: rule__Command__SignalAssignment_1
+            {
+            pushFollow(FOLLOW_rule__Command__SignalAssignment_1_in_rule__Command__Group__1__Impl2360);
+            rule__Command__SignalAssignment_1();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getCommandAccess().getSignalAssignment_1()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__1__Impl"
+
+
+    // $ANTLR start "rule__Command__Group__2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1217:1: rule__Command__Group__2 : rule__Command__Group__2__Impl rule__Command__Group__3 ;
+    public final void rule__Command__Group__2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1221:1: ( rule__Command__Group__2__Impl rule__Command__Group__3 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1222:2: rule__Command__Group__2__Impl rule__Command__Group__3
+            {
+            pushFollow(FOLLOW_rule__Command__Group__2__Impl_in_rule__Command__Group__22390);
+            rule__Command__Group__2__Impl();
+
+            state._fsp--;
+
+            pushFollow(FOLLOW_rule__Command__Group__3_in_rule__Command__Group__22393);
+            rule__Command__Group__3();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__2"
+
+
+    // $ANTLR start "rule__Command__Group__2__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1229:1: rule__Command__Group__2__Impl : ( '=' ) ;
+    public final void rule__Command__Group__2__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1233:1: ( ( '=' ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1234:1: ( '=' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1234:1: ( '=' )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1235:1: '='
+            {
+             before(grammarAccess.getCommandAccess().getEqualsSignKeyword_2()); 
+            match(input,22,FOLLOW_22_in_rule__Command__Group__2__Impl2421); 
+             after(grammarAccess.getCommandAccess().getEqualsSignKeyword_2()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__2__Impl"
+
+
+    // $ANTLR start "rule__Command__Group__3"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1248:1: rule__Command__Group__3 : rule__Command__Group__3__Impl ;
+    public final void rule__Command__Group__3() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1252:1: ( rule__Command__Group__3__Impl )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1253:2: rule__Command__Group__3__Impl
+            {
+            pushFollow(FOLLOW_rule__Command__Group__3__Impl_in_rule__Command__Group__32452);
+            rule__Command__Group__3__Impl();
+
+            state._fsp--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__3"
+
+
+    // $ANTLR start "rule__Command__Group__3__Impl"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1259:1: rule__Command__Group__3__Impl : ( ( rule__Command__NewValueAssignment_3 ) ) ;
+    public final void rule__Command__Group__3__Impl() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1263:1: ( ( ( rule__Command__NewValueAssignment_3 ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1264:1: ( ( rule__Command__NewValueAssignment_3 ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1264:1: ( ( rule__Command__NewValueAssignment_3 ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1265:1: ( rule__Command__NewValueAssignment_3 )
+            {
+             before(grammarAccess.getCommandAccess().getNewValueAssignment_3()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1266:1: ( rule__Command__NewValueAssignment_3 )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1266:2: rule__Command__NewValueAssignment_3
+            {
+            pushFollow(FOLLOW_rule__Command__NewValueAssignment_3_in_rule__Command__Group__3__Impl2479);
+            rule__Command__NewValueAssignment_3();
+
+            state._fsp--;
+
+
+            }
+
+             after(grammarAccess.getCommandAccess().getNewValueAssignment_3()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__Group__3__Impl"
+
+
+    // $ANTLR start "rule__Statemachine__SignalsAssignment_1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1285:1: rule__Statemachine__SignalsAssignment_1 : ( ruleSignal ) ;
+    public final void rule__Statemachine__SignalsAssignment_1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1289:1: ( ( ruleSignal ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1290:1: ( ruleSignal )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1290:1: ( ruleSignal )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1291:1: ruleSignal
+            {
+             before(grammarAccess.getStatemachineAccess().getSignalsSignalParserRuleCall_1_0()); 
+            pushFollow(FOLLOW_ruleSignal_in_rule__Statemachine__SignalsAssignment_12522);
+            ruleSignal();
+
+            state._fsp--;
+
+             after(grammarAccess.getStatemachineAccess().getSignalsSignalParserRuleCall_1_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__SignalsAssignment_1"
+
+
+    // $ANTLR start "rule__Statemachine__StatesAssignment_2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1300:1: rule__Statemachine__StatesAssignment_2 : ( ruleState ) ;
+    public final void rule__Statemachine__StatesAssignment_2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1304:1: ( ( ruleState ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1305:1: ( ruleState )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1305:1: ( ruleState )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1306:1: ruleState
+            {
+             before(grammarAccess.getStatemachineAccess().getStatesStateParserRuleCall_2_0()); 
+            pushFollow(FOLLOW_ruleState_in_rule__Statemachine__StatesAssignment_22553);
+            ruleState();
+
+            state._fsp--;
+
+             after(grammarAccess.getStatemachineAccess().getStatesStateParserRuleCall_2_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Statemachine__StatesAssignment_2"
+
+
+    // $ANTLR start "rule__Signal__NameAssignment_2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1315:1: rule__Signal__NameAssignment_2 : ( RULE_ID ) ;
+    public final void rule__Signal__NameAssignment_2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1319:1: ( ( RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1320:1: ( RULE_ID )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1320:1: ( RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1321:1: RULE_ID
+            {
+             before(grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0()); 
+            match(input,RULE_ID,FOLLOW_RULE_ID_in_rule__Signal__NameAssignment_22584); 
+             after(grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Signal__NameAssignment_2"
+
+
+    // $ANTLR start "rule__State__NameAssignment_1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1330:1: rule__State__NameAssignment_1 : ( RULE_ID ) ;
+    public final void rule__State__NameAssignment_1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1334:1: ( ( RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1335:1: ( RULE_ID )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1335:1: ( RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1336:1: RULE_ID
+            {
+             before(grammarAccess.getStateAccess().getNameIDTerminalRuleCall_1_0()); 
+            match(input,RULE_ID,FOLLOW_RULE_ID_in_rule__State__NameAssignment_12615); 
+             after(grammarAccess.getStateAccess().getNameIDTerminalRuleCall_1_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__NameAssignment_1"
+
+
+    // $ANTLR start "rule__State__CommandsAssignment_2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1345:1: rule__State__CommandsAssignment_2 : ( ruleCommand ) ;
+    public final void rule__State__CommandsAssignment_2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1349:1: ( ( ruleCommand ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1350:1: ( ruleCommand )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1350:1: ( ruleCommand )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1351:1: ruleCommand
+            {
+             before(grammarAccess.getStateAccess().getCommandsCommandParserRuleCall_2_0()); 
+            pushFollow(FOLLOW_ruleCommand_in_rule__State__CommandsAssignment_22646);
+            ruleCommand();
+
+            state._fsp--;
+
+             after(grammarAccess.getStateAccess().getCommandsCommandParserRuleCall_2_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__CommandsAssignment_2"
+
+
+    // $ANTLR start "rule__State__TransitionsAssignment_3"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1360:1: rule__State__TransitionsAssignment_3 : ( ruleTransition ) ;
+    public final void rule__State__TransitionsAssignment_3() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1364:1: ( ( ruleTransition ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1365:1: ( ruleTransition )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1365:1: ( ruleTransition )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1366:1: ruleTransition
+            {
+             before(grammarAccess.getStateAccess().getTransitionsTransitionParserRuleCall_3_0()); 
+            pushFollow(FOLLOW_ruleTransition_in_rule__State__TransitionsAssignment_32677);
+            ruleTransition();
+
+            state._fsp--;
+
+             after(grammarAccess.getStateAccess().getTransitionsTransitionParserRuleCall_3_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__State__TransitionsAssignment_3"
+
+
+    // $ANTLR start "rule__Transition__ConditionAssignment_1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1375:1: rule__Transition__ConditionAssignment_1 : ( ruleCondition ) ;
+    public final void rule__Transition__ConditionAssignment_1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1379:1: ( ( ruleCondition ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1380:1: ( ruleCondition )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1380:1: ( ruleCondition )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1381:1: ruleCondition
+            {
+             before(grammarAccess.getTransitionAccess().getConditionConditionParserRuleCall_1_0()); 
+            pushFollow(FOLLOW_ruleCondition_in_rule__Transition__ConditionAssignment_12708);
+            ruleCondition();
+
+            state._fsp--;
+
+             after(grammarAccess.getTransitionAccess().getConditionConditionParserRuleCall_1_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__ConditionAssignment_1"
+
+
+    // $ANTLR start "rule__Transition__StateAssignment_3"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1390:1: rule__Transition__StateAssignment_3 : ( ( RULE_ID ) ) ;
+    public final void rule__Transition__StateAssignment_3() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1394:1: ( ( ( RULE_ID ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1395:1: ( ( RULE_ID ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1395:1: ( ( RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1396:1: ( RULE_ID )
+            {
+             before(grammarAccess.getTransitionAccess().getStateStateCrossReference_3_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1397:1: ( RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1398:1: RULE_ID
+            {
+             before(grammarAccess.getTransitionAccess().getStateStateIDTerminalRuleCall_3_0_1()); 
+            match(input,RULE_ID,FOLLOW_RULE_ID_in_rule__Transition__StateAssignment_32743); 
+             after(grammarAccess.getTransitionAccess().getStateStateIDTerminalRuleCall_3_0_1()); 
+
+            }
+
+             after(grammarAccess.getTransitionAccess().getStateStateCrossReference_3_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Transition__StateAssignment_3"
+
+
+    // $ANTLR start "rule__Condition__EventsAssignment_0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1409:1: rule__Condition__EventsAssignment_0 : ( ruleEvent ) ;
+    public final void rule__Condition__EventsAssignment_0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1413:1: ( ( ruleEvent ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1414:1: ( ruleEvent )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1414:1: ( ruleEvent )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1415:1: ruleEvent
+            {
+             before(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_0_0()); 
+            pushFollow(FOLLOW_ruleEvent_in_rule__Condition__EventsAssignment_02778);
+            ruleEvent();
+
+            state._fsp--;
+
+             after(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_0_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__EventsAssignment_0"
+
+
+    // $ANTLR start "rule__Condition__EventsAssignment_1_1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1424:1: rule__Condition__EventsAssignment_1_1 : ( ruleEvent ) ;
+    public final void rule__Condition__EventsAssignment_1_1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1428:1: ( ( ruleEvent ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1429:1: ( ruleEvent )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1429:1: ( ruleEvent )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1430:1: ruleEvent
+            {
+             before(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_1_1_0()); 
+            pushFollow(FOLLOW_ruleEvent_in_rule__Condition__EventsAssignment_1_12809);
+            ruleEvent();
+
+            state._fsp--;
+
+             after(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_1_1_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Condition__EventsAssignment_1_1"
+
+
+    // $ANTLR start "rule__Event__SignalAssignment_0"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1439:1: rule__Event__SignalAssignment_0 : ( ( RULE_ID ) ) ;
+    public final void rule__Event__SignalAssignment_0() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1443:1: ( ( ( RULE_ID ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1444:1: ( ( RULE_ID ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1444:1: ( ( RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1445:1: ( RULE_ID )
+            {
+             before(grammarAccess.getEventAccess().getSignalSignalCrossReference_0_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1446:1: ( RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1447:1: RULE_ID
+            {
+             before(grammarAccess.getEventAccess().getSignalSignalIDTerminalRuleCall_0_0_1()); 
+            match(input,RULE_ID,FOLLOW_RULE_ID_in_rule__Event__SignalAssignment_02844); 
+             after(grammarAccess.getEventAccess().getSignalSignalIDTerminalRuleCall_0_0_1()); 
+
+            }
+
+             after(grammarAccess.getEventAccess().getSignalSignalCrossReference_0_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__SignalAssignment_0"
+
+
+    // $ANTLR start "rule__Event__ValueAssignment_2"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1458:1: rule__Event__ValueAssignment_2 : ( RULE_BOOLEAN ) ;
+    public final void rule__Event__ValueAssignment_2() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1462:1: ( ( RULE_BOOLEAN ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1463:1: ( RULE_BOOLEAN )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1463:1: ( RULE_BOOLEAN )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1464:1: RULE_BOOLEAN
+            {
+             before(grammarAccess.getEventAccess().getValueBOOLEANTerminalRuleCall_2_0()); 
+            match(input,RULE_BOOLEAN,FOLLOW_RULE_BOOLEAN_in_rule__Event__ValueAssignment_22879); 
+             after(grammarAccess.getEventAccess().getValueBOOLEANTerminalRuleCall_2_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Event__ValueAssignment_2"
+
+
+    // $ANTLR start "rule__Command__SignalAssignment_1"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1473:1: rule__Command__SignalAssignment_1 : ( ( RULE_ID ) ) ;
+    public final void rule__Command__SignalAssignment_1() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1477:1: ( ( ( RULE_ID ) ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1478:1: ( ( RULE_ID ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1478:1: ( ( RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1479:1: ( RULE_ID )
+            {
+             before(grammarAccess.getCommandAccess().getSignalSignalCrossReference_1_0()); 
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1480:1: ( RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1481:1: RULE_ID
+            {
+             before(grammarAccess.getCommandAccess().getSignalSignalIDTerminalRuleCall_1_0_1()); 
+            match(input,RULE_ID,FOLLOW_RULE_ID_in_rule__Command__SignalAssignment_12914); 
+             after(grammarAccess.getCommandAccess().getSignalSignalIDTerminalRuleCall_1_0_1()); 
+
+            }
+
+             after(grammarAccess.getCommandAccess().getSignalSignalCrossReference_1_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__SignalAssignment_1"
+
+
+    // $ANTLR start "rule__Command__NewValueAssignment_3"
+    // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1492:1: rule__Command__NewValueAssignment_3 : ( RULE_BOOLEAN ) ;
+    public final void rule__Command__NewValueAssignment_3() throws RecognitionException {
+
+        		int stackSize = keepStackSize();
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1496:1: ( ( RULE_BOOLEAN ) )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1497:1: ( RULE_BOOLEAN )
+            {
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1497:1: ( RULE_BOOLEAN )
+            // ../org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g:1498:1: RULE_BOOLEAN
+            {
+             before(grammarAccess.getCommandAccess().getNewValueBOOLEANTerminalRuleCall_3_0()); 
+            match(input,RULE_BOOLEAN,FOLLOW_RULE_BOOLEAN_in_rule__Command__NewValueAssignment_32949); 
+             after(grammarAccess.getCommandAccess().getNewValueBOOLEANTerminalRuleCall_3_0()); 
+
+            }
+
+
+            }
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+
+            	restoreStackSize(stackSize);
+
+        }
+        return ;
+    }
+    // $ANTLR end "rule__Command__NewValueAssignment_3"
+
+    // Delegated rules
+
+
+ 
+
+    public static final BitSet FOLLOW_ruleStatemachine_in_entryRuleStatemachine61 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleStatemachine68 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Statemachine__Group__0_in_ruleStatemachine94 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleSignal_in_entryRuleSignal121 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleSignal128 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Signal__Group__0_in_ruleSignal154 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleInputSignal_in_entryRuleInputSignal181 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleInputSignal188 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__InputSignal__Group__0_in_ruleInputSignal214 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleOutputSignal_in_entryRuleOutputSignal241 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleOutputSignal248 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__OutputSignal__Group__0_in_ruleOutputSignal274 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleState_in_entryRuleState301 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleState308 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__State__Group__0_in_ruleState334 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleTransition_in_entryRuleTransition361 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleTransition368 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Transition__Group__0_in_ruleTransition394 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleCondition_in_entryRuleCondition421 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleCondition428 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Condition__Group__0_in_ruleCondition454 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleEvent_in_entryRuleEvent481 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleEvent488 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Event__Group__0_in_ruleEvent514 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleCommand_in_entryRuleCommand541 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleCommand548 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Command__Group__0_in_ruleCommand574 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleInputSignal_in_rule__Signal__Alternatives_0610 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleOutputSignal_in_rule__Signal__Alternatives_0627 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Statemachine__Group__0__Impl_in_rule__Statemachine__Group__0657 = new BitSet(new long[]{0x000000000000E000L});
+    public static final BitSet FOLLOW_rule__Statemachine__Group__1_in_rule__Statemachine__Group__0660 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Statemachine__Group__1__Impl_in_rule__Statemachine__Group__1718 = new BitSet(new long[]{0x000000000000E000L});
+    public static final BitSet FOLLOW_rule__Statemachine__Group__2_in_rule__Statemachine__Group__1721 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Statemachine__SignalsAssignment_1_in_rule__Statemachine__Group__1__Impl748 = new BitSet(new long[]{0x0000000000006002L});
+    public static final BitSet FOLLOW_rule__Statemachine__Group__2__Impl_in_rule__Statemachine__Group__2779 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Statemachine__StatesAssignment_2_in_rule__Statemachine__Group__2__Impl806 = new BitSet(new long[]{0x0000000000008002L});
+    public static final BitSet FOLLOW_rule__Signal__Group__0__Impl_in_rule__Signal__Group__0843 = new BitSet(new long[]{0x0000000000001000L});
+    public static final BitSet FOLLOW_rule__Signal__Group__1_in_rule__Signal__Group__0846 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Signal__Alternatives_0_in_rule__Signal__Group__0__Impl873 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Signal__Group__1__Impl_in_rule__Signal__Group__1903 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_rule__Signal__Group__2_in_rule__Signal__Group__1906 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_12_in_rule__Signal__Group__1__Impl934 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Signal__Group__2__Impl_in_rule__Signal__Group__2965 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Signal__NameAssignment_2_in_rule__Signal__Group__2__Impl992 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__InputSignal__Group__0__Impl_in_rule__InputSignal__Group__01028 = new BitSet(new long[]{0x0000000000002000L});
+    public static final BitSet FOLLOW_rule__InputSignal__Group__1_in_rule__InputSignal__Group__01031 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__InputSignal__Group__1__Impl_in_rule__InputSignal__Group__11089 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_13_in_rule__InputSignal__Group__1__Impl1117 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__OutputSignal__Group__0__Impl_in_rule__OutputSignal__Group__01152 = new BitSet(new long[]{0x0000000000006000L});
+    public static final BitSet FOLLOW_rule__OutputSignal__Group__1_in_rule__OutputSignal__Group__01155 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__OutputSignal__Group__1__Impl_in_rule__OutputSignal__Group__11213 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_14_in_rule__OutputSignal__Group__1__Impl1241 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__State__Group__0__Impl_in_rule__State__Group__01276 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_rule__State__Group__1_in_rule__State__Group__01279 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_15_in_rule__State__Group__0__Impl1307 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__State__Group__1__Impl_in_rule__State__Group__11338 = new BitSet(new long[]{0x0000000000230000L});
+    public static final BitSet FOLLOW_rule__State__Group__2_in_rule__State__Group__11341 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__State__NameAssignment_1_in_rule__State__Group__1__Impl1368 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__State__Group__2__Impl_in_rule__State__Group__21398 = new BitSet(new long[]{0x0000000000230000L});
+    public static final BitSet FOLLOW_rule__State__Group__3_in_rule__State__Group__21401 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__State__CommandsAssignment_2_in_rule__State__Group__2__Impl1428 = new BitSet(new long[]{0x0000000000200002L});
+    public static final BitSet FOLLOW_rule__State__Group__3__Impl_in_rule__State__Group__31459 = new BitSet(new long[]{0x0000000000230000L});
+    public static final BitSet FOLLOW_rule__State__Group__4_in_rule__State__Group__31462 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__State__TransitionsAssignment_3_in_rule__State__Group__3__Impl1489 = new BitSet(new long[]{0x0000000000020002L});
+    public static final BitSet FOLLOW_rule__State__Group__4__Impl_in_rule__State__Group__41520 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_16_in_rule__State__Group__4__Impl1548 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Transition__Group__0__Impl_in_rule__Transition__Group__01589 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_rule__Transition__Group__1_in_rule__Transition__Group__01592 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_17_in_rule__Transition__Group__0__Impl1620 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Transition__Group__1__Impl_in_rule__Transition__Group__11651 = new BitSet(new long[]{0x0000000000040000L});
+    public static final BitSet FOLLOW_rule__Transition__Group__2_in_rule__Transition__Group__11654 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Transition__ConditionAssignment_1_in_rule__Transition__Group__1__Impl1681 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Transition__Group__2__Impl_in_rule__Transition__Group__21711 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_rule__Transition__Group__3_in_rule__Transition__Group__21714 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_18_in_rule__Transition__Group__2__Impl1742 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Transition__Group__3__Impl_in_rule__Transition__Group__31773 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Transition__StateAssignment_3_in_rule__Transition__Group__3__Impl1800 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Condition__Group__0__Impl_in_rule__Condition__Group__01838 = new BitSet(new long[]{0x0000000000080000L});
+    public static final BitSet FOLLOW_rule__Condition__Group__1_in_rule__Condition__Group__01841 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Condition__EventsAssignment_0_in_rule__Condition__Group__0__Impl1868 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Condition__Group__1__Impl_in_rule__Condition__Group__11898 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Condition__Group_1__0_in_rule__Condition__Group__1__Impl1925 = new BitSet(new long[]{0x0000000000080002L});
+    public static final BitSet FOLLOW_rule__Condition__Group_1__0__Impl_in_rule__Condition__Group_1__01960 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_rule__Condition__Group_1__1_in_rule__Condition__Group_1__01963 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_19_in_rule__Condition__Group_1__0__Impl1991 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Condition__Group_1__1__Impl_in_rule__Condition__Group_1__12022 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Condition__EventsAssignment_1_1_in_rule__Condition__Group_1__1__Impl2049 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Event__Group__0__Impl_in_rule__Event__Group__02083 = new BitSet(new long[]{0x0000000000100000L});
+    public static final BitSet FOLLOW_rule__Event__Group__1_in_rule__Event__Group__02086 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Event__SignalAssignment_0_in_rule__Event__Group__0__Impl2113 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Event__Group__1__Impl_in_rule__Event__Group__12143 = new BitSet(new long[]{0x0000000000000020L});
+    public static final BitSet FOLLOW_rule__Event__Group__2_in_rule__Event__Group__12146 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_20_in_rule__Event__Group__1__Impl2174 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Event__Group__2__Impl_in_rule__Event__Group__22205 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Event__ValueAssignment_2_in_rule__Event__Group__2__Impl2232 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Command__Group__0__Impl_in_rule__Command__Group__02268 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_rule__Command__Group__1_in_rule__Command__Group__02271 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_21_in_rule__Command__Group__0__Impl2299 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Command__Group__1__Impl_in_rule__Command__Group__12330 = new BitSet(new long[]{0x0000000000400000L});
+    public static final BitSet FOLLOW_rule__Command__Group__2_in_rule__Command__Group__12333 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Command__SignalAssignment_1_in_rule__Command__Group__1__Impl2360 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Command__Group__2__Impl_in_rule__Command__Group__22390 = new BitSet(new long[]{0x0000000000000020L});
+    public static final BitSet FOLLOW_rule__Command__Group__3_in_rule__Command__Group__22393 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_22_in_rule__Command__Group__2__Impl2421 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Command__Group__3__Impl_in_rule__Command__Group__32452 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_rule__Command__NewValueAssignment_3_in_rule__Command__Group__3__Impl2479 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleSignal_in_rule__Statemachine__SignalsAssignment_12522 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleState_in_rule__Statemachine__StatesAssignment_22553 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_ID_in_rule__Signal__NameAssignment_22584 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_ID_in_rule__State__NameAssignment_12615 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleCommand_in_rule__State__CommandsAssignment_22646 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleTransition_in_rule__State__TransitionsAssignment_32677 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleCondition_in_rule__Transition__ConditionAssignment_12708 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_ID_in_rule__Transition__StateAssignment_32743 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleEvent_in_rule__Condition__EventsAssignment_02778 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleEvent_in_rule__Condition__EventsAssignment_1_12809 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_ID_in_rule__Event__SignalAssignment_02844 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_BOOLEAN_in_rule__Event__ValueAssignment_22879 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_ID_in_rule__Command__SignalAssignment_12914 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_BOOLEAN_in_rule__Command__NewValueAssignment_32949 = new BitSet(new long[]{0x0000000000000002L});
+
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine/.antlr-generator-3.2.0-patch.jar b/demos/org.eclipse.fx.xtext.statemachine/.antlr-generator-3.2.0-patch.jar
new file mode 100644
index 0000000..90516fd
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/.antlr-generator-3.2.0-patch.jar
Binary files differ
diff --git a/demos/org.eclipse.fx.xtext.statemachine/.classpath b/demos/org.eclipse.fx.xtext.statemachine/.classpath
new file mode 100644
index 0000000..9081d4f
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-gen"/>
+	<classpathentry kind="src" path="xtend-gen"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/demos/org.eclipse.fx.xtext.statemachine/.gitignore b/demos/org.eclipse.fx.xtext.statemachine/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git "a/demos/org.eclipse.fx.xtext.statemachine/.launch/Generate Statemachine \050state\051 Language Infrastructure.launch" "b/demos/org.eclipse.fx.xtext.statemachine/.launch/Generate Statemachine \050state\051 Language Infrastructure.launch"
new file mode 100644
index 0000000..f229de3
--- /dev/null
+++ "b/demos/org.eclipse.fx.xtext.statemachine/.launch/Generate Statemachine \050state\051 Language Infrastructure.launch"
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.emf.mwe2.launch.Mwe2LaunchConfigurationType">
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/org.eclipse.fx.xtext.statemachine&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/org.eclipse.fx.xtext.statemachine.ide&quot; type=&quot;4&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.fx.xtext.statemachine"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="src/org/eclipse/fx/xtext/statemachine/GenerateStatemachine.mwe2"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.fx.xtext.statemachine"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx512m"/>
+</launchConfiguration>
diff --git a/demos/org.eclipse.fx.xtext.statemachine/.project b/demos/org.eclipse.fx.xtext.statemachine/.project
new file mode 100644
index 0000000..31df77e
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.fx.xtext.statemachine</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>
+		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+	</natures>
+</projectDescription>
diff --git a/demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.core.resources.prefs b/demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.jdt.core.prefs b/demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/demos/org.eclipse.fx.xtext.statemachine/META-INF/MANIFEST.MF b/demos/org.eclipse.fx.xtext.statemachine/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c1a6daa
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/META-INF/MANIFEST.MF
@@ -0,0 +1,31 @@
+Manifest-Version: 1.0

+Bundle-ManifestVersion: 2

+Bundle-Name: org.eclipse.fx.xtext.statemachine

+Bundle-Vendor: My Company

+Bundle-Version: 1.0.0.qualifier

+Bundle-SymbolicName: org.eclipse.fx.xtext.statemachine; singleton:=true

+Bundle-ActivationPolicy: lazy

+Require-Bundle: org.eclipse.xtext;visibility:=reexport,

+ org.eclipse.equinox.common;bundle-version="3.5.0",

+ org.eclipse.xtext.util,

+ org.eclipse.emf.ecore,

+ org.eclipse.emf.common,

+ org.eclipse.xtext.xbase.lib,

+ org.antlr.runtime,

+ org.eclipse.xtext.common.types,

+ org.objectweb.asm;bundle-version="[5.0.1,6.0.0)";resolution:=optional

+Import-Package: org.apache.log4j

+Bundle-RequiredExecutionEnvironment: JavaSE-1.8

+Export-Package: org.eclipse.fx.xtext.statemachine,

+ org.eclipse.fx.xtext.statemachine.services,

+ org.eclipse.fx.xtext.statemachine.statemachine,

+ org.eclipse.fx.xtext.statemachine.statemachine.impl,

+ org.eclipse.fx.xtext.statemachine.statemachine.util,

+ org.eclipse.fx.xtext.statemachine.serializer,

+ org.eclipse.fx.xtext.statemachine.parser.antlr,

+ org.eclipse.fx.xtext.statemachine.parser.antlr.internal,

+ org.eclipse.fx.xtext.statemachine.validation,

+ org.eclipse.fx.xtext.statemachine.scoping,

+ org.eclipse.fx.xtext.statemachine.generator,

+ org.eclipse.fx.xtext.statemachine.formatting

+

diff --git a/demos/org.eclipse.fx.xtext.statemachine/build.properties b/demos/org.eclipse.fx.xtext.statemachine/build.properties
new file mode 100644
index 0000000..f9e12db
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/build.properties
@@ -0,0 +1,15 @@
+source.. = src/,\
+           src-gen/,\
+           xtend-gen/
+bin.includes = model/,\
+               META-INF/,\
+               .,\
+               plugin.xml
+additional.bundles = org.eclipse.xtext.xbase,\
+                     org.eclipse.xtext.generator,\
+                     org.apache.commons.logging,\
+                     org.eclipse.emf.codegen.ecore,\
+                     org.eclipse.emf.mwe.utils,\
+                     org.eclipse.emf.mwe2.launch,\
+                     org.eclipse.xtext.common.types,\
+                     org.objectweb.asm
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.ecore b/demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.ecore
new file mode 100644
index 0000000..25e51ca
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.ecore
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="statemachine" nsURI="http://www.eclipse.org/fx/xtext/statemachine/Statemachine"
+    nsPrefix="statemachine">
+  <eClassifiers xsi:type="ecore:EClass" name="Statemachine">
+    <eStructuralFeatures xsi:type="ecore:EReference" name="signals" upperBound="-1"
+        eType="#//Signal" containment="true"/>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="states" upperBound="-1"
+        eType="#//State" containment="true"/>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="Signal">
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="InputSignal" eSuperTypes="#//Signal"/>
+  <eClassifiers xsi:type="ecore:EClass" name="OutputSignal" eSuperTypes="#//Signal"/>
+  <eClassifiers xsi:type="ecore:EClass" name="State">
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="commands" upperBound="-1"
+        eType="#//Command" containment="true"/>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="transitions" upperBound="-1"
+        eType="#//Transition" containment="true"/>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="Transition">
+    <eStructuralFeatures xsi:type="ecore:EReference" name="condition" eType="#//Condition"
+        containment="true"/>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="state" eType="#//State"/>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="Condition">
+    <eStructuralFeatures xsi:type="ecore:EReference" name="events" upperBound="-1"
+        eType="#//Event" containment="true"/>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="Event">
+    <eStructuralFeatures xsi:type="ecore:EReference" name="signal" eType="#//Signal"/>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"/>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="Command">
+    <eStructuralFeatures xsi:type="ecore:EReference" name="signal" eType="#//Signal"/>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="newValue" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"/>
+  </eClassifiers>
+</ecore:EPackage>
diff --git a/demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.genmodel b/demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.genmodel
new file mode 100644
index 0000000..77f2f5b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.genmodel
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
+    xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" modelDirectory="/org.eclipse.fx.xtext.statemachine/src-gen" editDirectory="/org.eclipse.fx.xtext.statemachine.edit/src"
+    editorDirectory="/org.eclipse.fx.xtext.statemachine.editor/src" modelPluginID="org.eclipse.fx.xtext.statemachine"
+    forceOverwrite="true" modelName="Statemachine" updateClasspath="false" rootExtendsClass="org.eclipse.emf.ecore.impl.MinimalEObjectImpl$Container"
+    complianceLevel="6.0" copyrightFields="false" editPluginID="org.eclipse.fx.xtext.statemachine.edit"
+    editorPluginID="org.eclipse.fx.xtext.statemachine.editor" runtimeVersion="2.10">
+  <genPackages prefix="Statemachine" basePackage="org.eclipse.fx.xtext.statemachine"
+      disposableProviderFactory="true" fileExtensions="state" ecorePackage="Statemachine.ecore#/">
+    <genClasses ecoreClass="Statemachine.ecore#//Statemachine">
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference Statemachine.ecore#//Statemachine/signals"/>
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference Statemachine.ecore#//Statemachine/states"/>
+    </genClasses>
+    <genClasses ecoreClass="Statemachine.ecore#//Signal">
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute Statemachine.ecore#//Signal/name"/>
+    </genClasses>
+    <genClasses ecoreClass="Statemachine.ecore#//InputSignal"/>
+    <genClasses ecoreClass="Statemachine.ecore#//OutputSignal"/>
+    <genClasses ecoreClass="Statemachine.ecore#//State">
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute Statemachine.ecore#//State/name"/>
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference Statemachine.ecore#//State/commands"/>
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference Statemachine.ecore#//State/transitions"/>
+    </genClasses>
+    <genClasses ecoreClass="Statemachine.ecore#//Transition">
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference Statemachine.ecore#//Transition/condition"/>
+      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference Statemachine.ecore#//Transition/state"/>
+    </genClasses>
+    <genClasses ecoreClass="Statemachine.ecore#//Condition">
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference Statemachine.ecore#//Condition/events"/>
+    </genClasses>
+    <genClasses ecoreClass="Statemachine.ecore#//Event">
+      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference Statemachine.ecore#//Event/signal"/>
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute Statemachine.ecore#//Event/value"/>
+    </genClasses>
+    <genClasses ecoreClass="Statemachine.ecore#//Command">
+      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference Statemachine.ecore#//Command/signal"/>
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute Statemachine.ecore#//Command/newValue"/>
+    </genClasses>
+  </genPackages>
+</genmodel:GenModel>
diff --git a/demos/org.eclipse.fx.xtext.statemachine/plugin.xml b/demos/org.eclipse.fx.xtext.statemachine/plugin.xml
new file mode 100644
index 0000000..e4ae9b0
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/plugin.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+
+<plugin>
+
+  <extension point="org.eclipse.emf.ecore.generated_package">
+    <package 
+       uri = "http://www.eclipse.org/fx/xtext/statemachine/Statemachine" 
+       class = "org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage"
+       genModel = "model/generated/Statemachine.genmodel" /> 
+	
+  </extension>
+
+
+</plugin>
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/AbstractStatemachineRuntimeModule.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/AbstractStatemachineRuntimeModule.java
new file mode 100644
index 0000000..e7abd5e
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/AbstractStatemachineRuntimeModule.java
@@ -0,0 +1,136 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine;
+
+import java.util.Properties;
+
+import org.eclipse.xtext.Constants;
+
+import com.google.inject.Binder;
+import com.google.inject.name.Names;
+
+/**
+ * Manual modifications go to {org.eclipse.fx.xtext.statemachine.StatemachineRuntimeModule}
+ */
+@SuppressWarnings("all")
+public abstract class AbstractStatemachineRuntimeModule extends org.eclipse.xtext.common.types.DefaultCommonTypesRuntimeModule {
+
+	protected Properties properties = null;
+
+	@Override
+	public void configure(Binder binder) {
+		properties = tryBindProperties(binder, "org/eclipse/fx/xtext/statemachine/Statemachine.properties");
+		super.configure(binder);
+	}
+	
+	public void configureLanguageName(Binder binder) {
+		binder.bind(String.class).annotatedWith(Names.named(Constants.LANGUAGE_NAME)).toInstance("org.eclipse.fx.xtext.statemachine.Statemachine");
+	}
+	
+	public void configureFileExtensions(Binder binder) {
+		if (properties == null || properties.getProperty(Constants.FILE_EXTENSIONS) == null)
+			binder.bind(String.class).annotatedWith(Names.named(Constants.FILE_EXTENSIONS)).toInstance("state");
+	}
+	
+	// contributed by org.eclipse.xtext.generator.grammarAccess.GrammarAccessFragment
+	public java.lang.ClassLoader bindClassLoaderToInstance() {
+		return getClass().getClassLoader();
+	}
+
+	// contributed by org.eclipse.xtext.generator.grammarAccess.GrammarAccessFragment
+	public Class<? extends org.eclipse.xtext.IGrammarAccess> bindIGrammarAccess() {
+		return org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.serializer.SerializerFragment
+	public Class<? extends org.eclipse.xtext.serializer.sequencer.ISemanticSequencer> bindISemanticSequencer() {
+		return org.eclipse.fx.xtext.statemachine.serializer.StatemachineSemanticSequencer.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.serializer.SerializerFragment
+	public Class<? extends org.eclipse.xtext.serializer.sequencer.ISyntacticSequencer> bindISyntacticSequencer() {
+		return org.eclipse.fx.xtext.statemachine.serializer.StatemachineSyntacticSequencer.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.serializer.SerializerFragment
+	public Class<? extends org.eclipse.xtext.serializer.ISerializer> bindISerializer() {
+		return org.eclipse.xtext.serializer.impl.Serializer.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.parser.antlr.XtextAntlrGeneratorFragment
+	public Class<? extends org.eclipse.xtext.parser.IParser> bindIParser() {
+		return org.eclipse.fx.xtext.statemachine.parser.antlr.StatemachineParser.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.parser.antlr.XtextAntlrGeneratorFragment
+	public Class<? extends org.eclipse.xtext.parser.ITokenToStringConverter> bindITokenToStringConverter() {
+		return org.eclipse.xtext.parser.antlr.AntlrTokenToStringConverter.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.parser.antlr.XtextAntlrGeneratorFragment
+	public Class<? extends org.eclipse.xtext.parser.antlr.IAntlrTokenFileProvider> bindIAntlrTokenFileProvider() {
+		return org.eclipse.fx.xtext.statemachine.parser.antlr.StatemachineAntlrTokenFileProvider.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.parser.antlr.XtextAntlrGeneratorFragment
+	public Class<? extends org.eclipse.xtext.parser.antlr.Lexer> bindLexer() {
+		return org.eclipse.fx.xtext.statemachine.parser.antlr.internal.InternalStatemachineLexer.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.parser.antlr.XtextAntlrGeneratorFragment
+	public com.google.inject.Provider<org.eclipse.fx.xtext.statemachine.parser.antlr.internal.InternalStatemachineLexer> provideInternalStatemachineLexer() {
+		return org.eclipse.xtext.parser.antlr.LexerProvider.create(org.eclipse.fx.xtext.statemachine.parser.antlr.internal.InternalStatemachineLexer.class);
+	}
+
+	// contributed by org.eclipse.xtext.generator.parser.antlr.XtextAntlrGeneratorFragment
+	public void configureRuntimeLexer(com.google.inject.Binder binder) {
+		binder.bind(org.eclipse.xtext.parser.antlr.Lexer.class).annotatedWith(com.google.inject.name.Names.named(org.eclipse.xtext.parser.antlr.LexerBindings.RUNTIME)).to(org.eclipse.fx.xtext.statemachine.parser.antlr.internal.InternalStatemachineLexer.class);
+	}
+
+	// contributed by org.eclipse.xtext.generator.parser.antlr.XtextAntlrGeneratorFragment
+	public Class<? extends org.eclipse.xtext.parser.antlr.ITokenDefProvider> bindITokenDefProvider() {
+		return org.eclipse.xtext.parser.antlr.AntlrTokenDefProvider.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.validation.ValidatorFragment
+	@org.eclipse.xtext.service.SingletonBinding(eager=true)	public Class<? extends org.eclipse.fx.xtext.statemachine.validation.StatemachineValidator> bindStatemachineValidator() {
+		return org.eclipse.fx.xtext.statemachine.validation.StatemachineValidator.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.scoping.AbstractScopingFragment
+	public Class<? extends org.eclipse.xtext.scoping.IScopeProvider> bindIScopeProvider() {
+		return org.eclipse.fx.xtext.statemachine.scoping.StatemachineScopeProvider.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.scoping.AbstractScopingFragment
+	public void configureIScopeProviderDelegate(com.google.inject.Binder binder) {
+		binder.bind(org.eclipse.xtext.scoping.IScopeProvider.class).annotatedWith(com.google.inject.name.Names.named(org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.NAMED_DELEGATE)).to(org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.class);
+	}
+
+	// contributed by org.eclipse.xtext.generator.scoping.AbstractScopingFragment
+	public void configureIgnoreCaseLinking(com.google.inject.Binder binder) {
+		binder.bindConstant().annotatedWith(org.eclipse.xtext.scoping.IgnoreCaseLinking.class).to(false);
+	}
+
+	// contributed by org.eclipse.xtext.generator.exporting.QualifiedNamesFragment
+	public Class<? extends org.eclipse.xtext.naming.IQualifiedNameProvider> bindIQualifiedNameProvider() {
+		return org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.generator.GeneratorFragment
+	public Class<? extends org.eclipse.xtext.generator.IGenerator> bindIGenerator() {
+		return org.eclipse.fx.xtext.statemachine.generator.StatemachineGenerator.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.formatting.FormatterFragment
+	public Class<? extends org.eclipse.xtext.formatting.IFormatter> bindIFormatter() {
+		return org.eclipse.fx.xtext.statemachine.formatting.StatemachineFormatter.class;
+	}
+
+	// contributed by org.eclipse.xtext.generator.types.TypesGeneratorFragment
+	public Class<? extends org.eclipse.xtext.scoping.IGlobalScopeProvider> bindIGlobalScopeProvider() {
+		return org.eclipse.xtext.common.types.xtext.TypesAwareDefaultGlobalScopeProvider.class;
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/Statemachine.xtextbin b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/Statemachine.xtextbin
new file mode 100644
index 0000000..6573800
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/Statemachine.xtextbin
Binary files differ
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetupGenerated.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetupGenerated.java
new file mode 100644
index 0000000..07049f0
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetupGenerated.java
@@ -0,0 +1,53 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine;
+
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.xtext.ISetup;
+import org.eclipse.xtext.ISetupExtension;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * Generated from StandaloneSetup.xpt!
+ */
+@SuppressWarnings("all")
+public class StatemachineStandaloneSetupGenerated implements ISetup, ISetupExtension {
+
+	@Override
+	public List<String> getFileExtensions() {
+		return Arrays.asList("state");
+	}
+
+	@Override
+	public Injector createInjectorAndDoEMFRegistration() {
+		org.eclipse.xtext.common.TerminalsStandaloneSetup.doSetup();
+
+		Injector injector = createInjector();
+		register(injector);
+		return injector;
+	}
+	
+	public Injector createInjector() {
+		return Guice.createInjector(new org.eclipse.fx.xtext.statemachine.StatemachineRuntimeModule());
+	}
+	
+	public void register(Injector injector) {
+	if (!EPackage.Registry.INSTANCE.containsKey("http://www.eclipse.org/fx/xtext/statemachine/Statemachine")) {
+		EPackage.Registry.INSTANCE.put("http://www.eclipse.org/fx/xtext/statemachine/Statemachine", org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage.eINSTANCE);
+	}
+
+		org.eclipse.xtext.resource.IResourceFactory resourceFactory = injector.getInstance(org.eclipse.xtext.resource.IResourceFactory.class);
+		org.eclipse.xtext.resource.IResourceServiceProvider serviceProvider = injector.getInstance(org.eclipse.xtext.resource.IResourceServiceProvider.class);
+		Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("state", resourceFactory);
+		org.eclipse.xtext.resource.IResourceServiceProvider.Registry.INSTANCE.getExtensionToFactoryMap().put("state", serviceProvider);
+		
+
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineAntlrTokenFileProvider.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineAntlrTokenFileProvider.java
new file mode 100644
index 0000000..1b854cd
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineAntlrTokenFileProvider.java
@@ -0,0 +1,16 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.parser.antlr;
+
+import java.io.InputStream;
+import org.eclipse.xtext.parser.antlr.IAntlrTokenFileProvider;
+
+public class StatemachineAntlrTokenFileProvider implements IAntlrTokenFileProvider {
+	
+	@Override
+	public InputStream getAntlrTokenFile() {
+		ClassLoader classLoader = getClass().getClassLoader();
+    	return classLoader.getResourceAsStream("org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.tokens");
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineParser.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineParser.java
new file mode 100644
index 0000000..c712f21
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineParser.java
@@ -0,0 +1,39 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.parser.antlr;
+
+import com.google.inject.Inject;
+
+import org.eclipse.xtext.parser.antlr.XtextTokenStream;
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+
+public class StatemachineParser extends org.eclipse.xtext.parser.antlr.AbstractAntlrParser {
+	
+	@Inject
+	private StatemachineGrammarAccess grammarAccess;
+	
+	@Override
+	protected void setInitialHiddenTokens(XtextTokenStream tokenStream) {
+		tokenStream.setInitialHiddenTokens("RULE_WS", "RULE_ML_COMMENT", "RULE_SL_COMMENT");
+	}
+	
+	@Override
+	protected org.eclipse.fx.xtext.statemachine.parser.antlr.internal.InternalStatemachineParser createParser(XtextTokenStream stream) {
+		return new org.eclipse.fx.xtext.statemachine.parser.antlr.internal.InternalStatemachineParser(stream, getGrammarAccess());
+	}
+	
+	@Override 
+	protected String getDefaultRuleName() {
+		return "Statemachine";
+	}
+	
+	public StatemachineGrammarAccess getGrammarAccess() {
+		return this.grammarAccess;
+	}
+	
+	public void setGrammarAccess(StatemachineGrammarAccess grammarAccess) {
+		this.grammarAccess = grammarAccess;
+	}
+	
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g
new file mode 100644
index 0000000..e7a208a
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g
@@ -0,0 +1,589 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+grammar InternalStatemachine;
+
+options {
+	superClass=AbstractInternalAntlrParser;
+	
+}
+
+@lexer::header {
+package org.eclipse.fx.xtext.statemachine.parser.antlr.internal;
+
+// Hack: Use our own Lexer superclass by means of import. 
+// Currently there is no other way to specify the superclass for the lexer.
+import org.eclipse.xtext.parser.antlr.Lexer;
+}
+
+@parser::header {
+package org.eclipse.fx.xtext.statemachine.parser.antlr.internal; 
+
+import org.eclipse.xtext.*;
+import org.eclipse.xtext.parser.*;
+import org.eclipse.xtext.parser.impl.*;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.parser.antlr.AbstractInternalAntlrParser;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream.HiddenTokens;
+import org.eclipse.xtext.parser.antlr.AntlrDatatypeRuleToken;
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+
+}
+
+@parser::members {
+
+ 	private StatemachineGrammarAccess grammarAccess;
+ 	
+    public InternalStatemachineParser(TokenStream input, StatemachineGrammarAccess grammarAccess) {
+        this(input);
+        this.grammarAccess = grammarAccess;
+        registerRules(grammarAccess.getGrammar());
+    }
+    
+    @Override
+    protected String getFirstRuleName() {
+    	return "Statemachine";	
+   	}
+   	
+   	@Override
+   	protected StatemachineGrammarAccess getGrammarAccess() {
+   		return grammarAccess;
+   	}
+}
+
+@rulecatch { 
+    catch (RecognitionException re) { 
+        recover(input,re); 
+        appendSkippedTokens();
+    } 
+}
+
+
+
+
+// Entry rule entryRuleStatemachine
+entryRuleStatemachine returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getStatemachineRule()); }
+	 iv_ruleStatemachine=ruleStatemachine 
+	 { $current=$iv_ruleStatemachine.current; } 
+	 EOF 
+;
+
+// Rule Statemachine
+ruleStatemachine returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+((
+    {
+        $current = forceCreateModelElement(
+            grammarAccess.getStatemachineAccess().getStatemachineAction_0(),
+            $current);
+    }
+)(
+(
+		{ 
+	        newCompositeNode(grammarAccess.getStatemachineAccess().getSignalsSignalParserRuleCall_1_0()); 
+	    }
+		lv_signals_1_0=ruleSignal		{
+	        if ($current==null) {
+	            $current = createModelElementForParent(grammarAccess.getStatemachineRule());
+	        }
+       		add(
+       			$current, 
+       			"signals",
+        		lv_signals_1_0, 
+        		"Signal");
+	        afterParserOrEnumRuleCall();
+	    }
+
+)
+)*(
+(
+		{ 
+	        newCompositeNode(grammarAccess.getStatemachineAccess().getStatesStateParserRuleCall_2_0()); 
+	    }
+		lv_states_2_0=ruleState		{
+	        if ($current==null) {
+	            $current = createModelElementForParent(grammarAccess.getStatemachineRule());
+	        }
+       		add(
+       			$current, 
+       			"states",
+        		lv_states_2_0, 
+        		"State");
+	        afterParserOrEnumRuleCall();
+	    }
+
+)
+)*)
+;
+
+
+
+
+
+// Entry rule entryRuleSignal
+entryRuleSignal returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getSignalRule()); }
+	 iv_ruleSignal=ruleSignal 
+	 { $current=$iv_ruleSignal.current; } 
+	 EOF 
+;
+
+// Rule Signal
+ruleSignal returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+((
+    { 
+        newCompositeNode(grammarAccess.getSignalAccess().getInputSignalParserRuleCall_0_0()); 
+    }
+    this_InputSignal_0=ruleInputSignal
+    { 
+        $current = $this_InputSignal_0.current; 
+        afterParserOrEnumRuleCall();
+    }
+
+    |
+    { 
+        newCompositeNode(grammarAccess.getSignalAccess().getOutputSignalParserRuleCall_0_1()); 
+    }
+    this_OutputSignal_1=ruleOutputSignal
+    { 
+        $current = $this_OutputSignal_1.current; 
+        afterParserOrEnumRuleCall();
+    }
+)	otherlv_2='signal' 
+    {
+    	newLeafNode(otherlv_2, grammarAccess.getSignalAccess().getSignalKeyword_1());
+    }
+(
+(
+		lv_name_3_0=RULE_ID
+		{
+			newLeafNode(lv_name_3_0, grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0()); 
+		}
+		{
+	        if ($current==null) {
+	            $current = createModelElement(grammarAccess.getSignalRule());
+	        }
+       		setWithLastConsumed(
+       			$current, 
+       			"name",
+        		lv_name_3_0, 
+        		"ID");
+	    }
+
+)
+))
+;
+
+
+
+
+
+// Entry rule entryRuleInputSignal
+entryRuleInputSignal returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getInputSignalRule()); }
+	 iv_ruleInputSignal=ruleInputSignal 
+	 { $current=$iv_ruleInputSignal.current; } 
+	 EOF 
+;
+
+// Rule InputSignal
+ruleInputSignal returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+((
+    {
+        $current = forceCreateModelElement(
+            grammarAccess.getInputSignalAccess().getInputSignalAction_0(),
+            $current);
+    }
+)	otherlv_1='input' 
+    {
+    	newLeafNode(otherlv_1, grammarAccess.getInputSignalAccess().getInputKeyword_1());
+    }
+)
+;
+
+
+
+
+
+// Entry rule entryRuleOutputSignal
+entryRuleOutputSignal returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getOutputSignalRule()); }
+	 iv_ruleOutputSignal=ruleOutputSignal 
+	 { $current=$iv_ruleOutputSignal.current; } 
+	 EOF 
+;
+
+// Rule OutputSignal
+ruleOutputSignal returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+((
+    {
+        $current = forceCreateModelElement(
+            grammarAccess.getOutputSignalAccess().getOutputSignalAction_0(),
+            $current);
+    }
+)	otherlv_1='output' 
+    {
+    	newLeafNode(otherlv_1, grammarAccess.getOutputSignalAccess().getOutputKeyword_1());
+    }
+)
+;
+
+
+
+
+
+// Entry rule entryRuleState
+entryRuleState returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getStateRule()); }
+	 iv_ruleState=ruleState 
+	 { $current=$iv_ruleState.current; } 
+	 EOF 
+;
+
+// Rule State
+ruleState returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+(	otherlv_0='state' 
+    {
+    	newLeafNode(otherlv_0, grammarAccess.getStateAccess().getStateKeyword_0());
+    }
+(
+(
+		lv_name_1_0=RULE_ID
+		{
+			newLeafNode(lv_name_1_0, grammarAccess.getStateAccess().getNameIDTerminalRuleCall_1_0()); 
+		}
+		{
+	        if ($current==null) {
+	            $current = createModelElement(grammarAccess.getStateRule());
+	        }
+       		setWithLastConsumed(
+       			$current, 
+       			"name",
+        		lv_name_1_0, 
+        		"ID");
+	    }
+
+)
+)(
+(
+		{ 
+	        newCompositeNode(grammarAccess.getStateAccess().getCommandsCommandParserRuleCall_2_0()); 
+	    }
+		lv_commands_2_0=ruleCommand		{
+	        if ($current==null) {
+	            $current = createModelElementForParent(grammarAccess.getStateRule());
+	        }
+       		add(
+       			$current, 
+       			"commands",
+        		lv_commands_2_0, 
+        		"Command");
+	        afterParserOrEnumRuleCall();
+	    }
+
+)
+)*(
+(
+		{ 
+	        newCompositeNode(grammarAccess.getStateAccess().getTransitionsTransitionParserRuleCall_3_0()); 
+	    }
+		lv_transitions_3_0=ruleTransition		{
+	        if ($current==null) {
+	            $current = createModelElementForParent(grammarAccess.getStateRule());
+	        }
+       		add(
+       			$current, 
+       			"transitions",
+        		lv_transitions_3_0, 
+        		"Transition");
+	        afterParserOrEnumRuleCall();
+	    }
+
+)
+)*	otherlv_4='end' 
+    {
+    	newLeafNode(otherlv_4, grammarAccess.getStateAccess().getEndKeyword_4());
+    }
+)
+;
+
+
+
+
+
+// Entry rule entryRuleTransition
+entryRuleTransition returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getTransitionRule()); }
+	 iv_ruleTransition=ruleTransition 
+	 { $current=$iv_ruleTransition.current; } 
+	 EOF 
+;
+
+// Rule Transition
+ruleTransition returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+(	otherlv_0='if' 
+    {
+    	newLeafNode(otherlv_0, grammarAccess.getTransitionAccess().getIfKeyword_0());
+    }
+(
+(
+		{ 
+	        newCompositeNode(grammarAccess.getTransitionAccess().getConditionConditionParserRuleCall_1_0()); 
+	    }
+		lv_condition_1_0=ruleCondition		{
+	        if ($current==null) {
+	            $current = createModelElementForParent(grammarAccess.getTransitionRule());
+	        }
+       		set(
+       			$current, 
+       			"condition",
+        		lv_condition_1_0, 
+        		"Condition");
+	        afterParserOrEnumRuleCall();
+	    }
+
+)
+)	otherlv_2='goto' 
+    {
+    	newLeafNode(otherlv_2, grammarAccess.getTransitionAccess().getGotoKeyword_2());
+    }
+(
+(
+		{
+			if ($current==null) {
+	            $current = createModelElement(grammarAccess.getTransitionRule());
+	        }
+        }
+	otherlv_3=RULE_ID
+	{
+		newLeafNode(otherlv_3, grammarAccess.getTransitionAccess().getStateStateCrossReference_3_0()); 
+	}
+
+)
+))
+;
+
+
+
+
+
+// Entry rule entryRuleCondition
+entryRuleCondition returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getConditionRule()); }
+	 iv_ruleCondition=ruleCondition 
+	 { $current=$iv_ruleCondition.current; } 
+	 EOF 
+;
+
+// Rule Condition
+ruleCondition returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+((
+(
+		{ 
+	        newCompositeNode(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_0_0()); 
+	    }
+		lv_events_0_0=ruleEvent		{
+	        if ($current==null) {
+	            $current = createModelElementForParent(grammarAccess.getConditionRule());
+	        }
+       		add(
+       			$current, 
+       			"events",
+        		lv_events_0_0, 
+        		"Event");
+	        afterParserOrEnumRuleCall();
+	    }
+
+)
+)(	otherlv_1='and' 
+    {
+    	newLeafNode(otherlv_1, grammarAccess.getConditionAccess().getAndKeyword_1_0());
+    }
+(
+(
+		{ 
+	        newCompositeNode(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_1_1_0()); 
+	    }
+		lv_events_2_0=ruleEvent		{
+	        if ($current==null) {
+	            $current = createModelElementForParent(grammarAccess.getConditionRule());
+	        }
+       		add(
+       			$current, 
+       			"events",
+        		lv_events_2_0, 
+        		"Event");
+	        afterParserOrEnumRuleCall();
+	    }
+
+)
+))*)
+;
+
+
+
+
+
+// Entry rule entryRuleEvent
+entryRuleEvent returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getEventRule()); }
+	 iv_ruleEvent=ruleEvent 
+	 { $current=$iv_ruleEvent.current; } 
+	 EOF 
+;
+
+// Rule Event
+ruleEvent returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+((
+(
+		{
+			if ($current==null) {
+	            $current = createModelElement(grammarAccess.getEventRule());
+	        }
+        }
+	otherlv_0=RULE_ID
+	{
+		newLeafNode(otherlv_0, grammarAccess.getEventAccess().getSignalSignalCrossReference_0_0()); 
+	}
+
+)
+)	otherlv_1='==' 
+    {
+    	newLeafNode(otherlv_1, grammarAccess.getEventAccess().getEqualsSignEqualsSignKeyword_1());
+    }
+(
+(
+		lv_value_2_0=RULE_BOOLEAN
+		{
+			newLeafNode(lv_value_2_0, grammarAccess.getEventAccess().getValueBOOLEANTerminalRuleCall_2_0()); 
+		}
+		{
+	        if ($current==null) {
+	            $current = createModelElement(grammarAccess.getEventRule());
+	        }
+       		setWithLastConsumed(
+       			$current, 
+       			"value",
+        		lv_value_2_0, 
+        		"BOOLEAN");
+	    }
+
+)
+))
+;
+
+
+
+
+
+// Entry rule entryRuleCommand
+entryRuleCommand returns [EObject current=null] 
+	:
+	{ newCompositeNode(grammarAccess.getCommandRule()); }
+	 iv_ruleCommand=ruleCommand 
+	 { $current=$iv_ruleCommand.current; } 
+	 EOF 
+;
+
+// Rule Command
+ruleCommand returns [EObject current=null] 
+    @init { enterRule(); 
+    }
+    @after { leaveRule(); }:
+(	otherlv_0='set' 
+    {
+    	newLeafNode(otherlv_0, grammarAccess.getCommandAccess().getSetKeyword_0());
+    }
+(
+(
+		{
+			if ($current==null) {
+	            $current = createModelElement(grammarAccess.getCommandRule());
+	        }
+        }
+	otherlv_1=RULE_ID
+	{
+		newLeafNode(otherlv_1, grammarAccess.getCommandAccess().getSignalSignalCrossReference_1_0()); 
+	}
+
+)
+)	otherlv_2='=' 
+    {
+    	newLeafNode(otherlv_2, grammarAccess.getCommandAccess().getEqualsSignKeyword_2());
+    }
+(
+(
+		lv_newValue_3_0=RULE_BOOLEAN
+		{
+			newLeafNode(lv_newValue_3_0, grammarAccess.getCommandAccess().getNewValueBOOLEANTerminalRuleCall_3_0()); 
+		}
+		{
+	        if ($current==null) {
+	            $current = createModelElement(grammarAccess.getCommandRule());
+	        }
+       		setWithLastConsumed(
+       			$current, 
+       			"newValue",
+        		lv_newValue_3_0, 
+        		"BOOLEAN");
+	    }
+
+)
+))
+;
+
+
+
+
+
+RULE_BOOLEAN : ('true'|'false');
+
+RULE_ID : '^'? ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
+
+RULE_INT : ('0'..'9')+;
+
+RULE_STRING : ('"' ('\\' .|~(('\\'|'"')))* '"'|'\'' ('\\' .|~(('\\'|'\'')))* '\'');
+
+RULE_ML_COMMENT : '/*' ( options {greedy=false;} : . )*'*/';
+
+RULE_SL_COMMENT : '//' ~(('\n'|'\r'))* ('\r'? '\n')?;
+
+RULE_WS : (' '|'\t'|'\r'|'\n')+;
+
+RULE_ANY_OTHER : .;
+
+
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.tokens b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.tokens
new file mode 100644
index 0000000..4cf4071
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.tokens
@@ -0,0 +1,30 @@
+'='=22
+'=='=20
+'and'=19
+'end'=16
+'goto'=18
+'if'=17
+'input'=13
+'output'=14
+'set'=21
+'signal'=12
+'state'=15
+RULE_ANY_OTHER=11
+RULE_BOOLEAN=5
+RULE_ID=4
+RULE_INT=6
+RULE_ML_COMMENT=8
+RULE_SL_COMMENT=9
+RULE_STRING=7
+RULE_WS=10
+T__12=12
+T__13=13
+T__14=14
+T__15=15
+T__16=16
+T__17=17
+T__18=18
+T__19=19
+T__20=20
+T__21=21
+T__22=22
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineLexer.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineLexer.java
new file mode 100644
index 0000000..ee110a4
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineLexer.java
@@ -0,0 +1,1168 @@
+package org.eclipse.fx.xtext.statemachine.parser.antlr.internal;
+
+// Hack: Use our own Lexer superclass by means of import. 
+// Currently there is no other way to specify the superclass for the lexer.
+import org.eclipse.xtext.parser.antlr.Lexer;
+
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+@SuppressWarnings("all")
+public class InternalStatemachineLexer extends Lexer {
+    public static final int RULE_BOOLEAN=5;
+    public static final int RULE_STRING=7;
+    public static final int RULE_SL_COMMENT=9;
+    public static final int T__19=19;
+    public static final int T__15=15;
+    public static final int T__16=16;
+    public static final int T__17=17;
+    public static final int T__18=18;
+    public static final int T__12=12;
+    public static final int T__13=13;
+    public static final int T__14=14;
+    public static final int EOF=-1;
+    public static final int RULE_ID=4;
+    public static final int RULE_WS=10;
+    public static final int RULE_ANY_OTHER=11;
+    public static final int RULE_INT=6;
+    public static final int T__22=22;
+    public static final int RULE_ML_COMMENT=8;
+    public static final int T__20=20;
+    public static final int T__21=21;
+
+    // delegates
+    // delegators
+
+    public InternalStatemachineLexer() {;} 
+    public InternalStatemachineLexer(CharStream input) {
+        this(input, new RecognizerSharedState());
+    }
+    public InternalStatemachineLexer(CharStream input, RecognizerSharedState state) {
+        super(input,state);
+
+    }
+    public String getGrammarFileName() { return "../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g"; }
+
+    // $ANTLR start "T__12"
+    public final void mT__12() throws RecognitionException {
+        try {
+            int _type = T__12;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:11:7: ( 'signal' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:11:9: 'signal'
+            {
+            match("signal"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__12"
+
+    // $ANTLR start "T__13"
+    public final void mT__13() throws RecognitionException {
+        try {
+            int _type = T__13;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:12:7: ( 'input' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:12:9: 'input'
+            {
+            match("input"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__13"
+
+    // $ANTLR start "T__14"
+    public final void mT__14() throws RecognitionException {
+        try {
+            int _type = T__14;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:13:7: ( 'output' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:13:9: 'output'
+            {
+            match("output"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__14"
+
+    // $ANTLR start "T__15"
+    public final void mT__15() throws RecognitionException {
+        try {
+            int _type = T__15;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:14:7: ( 'state' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:14:9: 'state'
+            {
+            match("state"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__15"
+
+    // $ANTLR start "T__16"
+    public final void mT__16() throws RecognitionException {
+        try {
+            int _type = T__16;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:15:7: ( 'end' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:15:9: 'end'
+            {
+            match("end"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__16"
+
+    // $ANTLR start "T__17"
+    public final void mT__17() throws RecognitionException {
+        try {
+            int _type = T__17;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:16:7: ( 'if' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:16:9: 'if'
+            {
+            match("if"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__17"
+
+    // $ANTLR start "T__18"
+    public final void mT__18() throws RecognitionException {
+        try {
+            int _type = T__18;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:17:7: ( 'goto' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:17:9: 'goto'
+            {
+            match("goto"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__18"
+
+    // $ANTLR start "T__19"
+    public final void mT__19() throws RecognitionException {
+        try {
+            int _type = T__19;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:18:7: ( 'and' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:18:9: 'and'
+            {
+            match("and"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__19"
+
+    // $ANTLR start "T__20"
+    public final void mT__20() throws RecognitionException {
+        try {
+            int _type = T__20;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:19:7: ( '==' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:19:9: '=='
+            {
+            match("=="); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__20"
+
+    // $ANTLR start "T__21"
+    public final void mT__21() throws RecognitionException {
+        try {
+            int _type = T__21;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:20:7: ( 'set' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:20:9: 'set'
+            {
+            match("set"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__21"
+
+    // $ANTLR start "T__22"
+    public final void mT__22() throws RecognitionException {
+        try {
+            int _type = T__22;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:21:7: ( '=' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:21:9: '='
+            {
+            match('='); 
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "T__22"
+
+    // $ANTLR start "RULE_BOOLEAN"
+    public final void mRULE_BOOLEAN() throws RecognitionException {
+        try {
+            int _type = RULE_BOOLEAN;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:573:14: ( ( 'true' | 'false' ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:573:16: ( 'true' | 'false' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:573:16: ( 'true' | 'false' )
+            int alt1=2;
+            int LA1_0 = input.LA(1);
+
+            if ( (LA1_0=='t') ) {
+                alt1=1;
+            }
+            else if ( (LA1_0=='f') ) {
+                alt1=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 1, 0, input);
+
+                throw nvae;
+            }
+            switch (alt1) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:573:17: 'true'
+                    {
+                    match("true"); 
+
+
+                    }
+                    break;
+                case 2 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:573:24: 'false'
+                    {
+                    match("false"); 
+
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_BOOLEAN"
+
+    // $ANTLR start "RULE_ID"
+    public final void mRULE_ID() throws RecognitionException {
+        try {
+            int _type = RULE_ID;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:575:9: ( ( '^' )? ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )* )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:575:11: ( '^' )? ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )*
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:575:11: ( '^' )?
+            int alt2=2;
+            int LA2_0 = input.LA(1);
+
+            if ( (LA2_0=='^') ) {
+                alt2=1;
+            }
+            switch (alt2) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:575:11: '^'
+                    {
+                    match('^'); 
+
+                    }
+                    break;
+
+            }
+
+            if ( (input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse = new MismatchedSetException(null,input);
+                recover(mse);
+                throw mse;}
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:575:40: ( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )*
+            loop3:
+            do {
+                int alt3=2;
+                int LA3_0 = input.LA(1);
+
+                if ( ((LA3_0>='0' && LA3_0<='9')||(LA3_0>='A' && LA3_0<='Z')||LA3_0=='_'||(LA3_0>='a' && LA3_0<='z')) ) {
+                    alt3=1;
+                }
+
+
+                switch (alt3) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:
+            	    {
+            	    if ( (input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        recover(mse);
+            	        throw mse;}
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop3;
+                }
+            } while (true);
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_ID"
+
+    // $ANTLR start "RULE_INT"
+    public final void mRULE_INT() throws RecognitionException {
+        try {
+            int _type = RULE_INT;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:577:10: ( ( '0' .. '9' )+ )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:577:12: ( '0' .. '9' )+
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:577:12: ( '0' .. '9' )+
+            int cnt4=0;
+            loop4:
+            do {
+                int alt4=2;
+                int LA4_0 = input.LA(1);
+
+                if ( ((LA4_0>='0' && LA4_0<='9')) ) {
+                    alt4=1;
+                }
+
+
+                switch (alt4) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:577:13: '0' .. '9'
+            	    {
+            	    matchRange('0','9'); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt4 >= 1 ) break loop4;
+                        EarlyExitException eee =
+                            new EarlyExitException(4, input);
+                        throw eee;
+                }
+                cnt4++;
+            } while (true);
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_INT"
+
+    // $ANTLR start "RULE_STRING"
+    public final void mRULE_STRING() throws RecognitionException {
+        try {
+            int _type = RULE_STRING;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:13: ( ( '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"' | '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\'' ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:15: ( '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"' | '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\'' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:15: ( '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"' | '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\'' )
+            int alt7=2;
+            int LA7_0 = input.LA(1);
+
+            if ( (LA7_0=='\"') ) {
+                alt7=1;
+            }
+            else if ( (LA7_0=='\'') ) {
+                alt7=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 7, 0, input);
+
+                throw nvae;
+            }
+            switch (alt7) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:16: '\"' ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )* '\"'
+                    {
+                    match('\"'); 
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:20: ( '\\\\' . | ~ ( ( '\\\\' | '\"' ) ) )*
+                    loop5:
+                    do {
+                        int alt5=3;
+                        int LA5_0 = input.LA(1);
+
+                        if ( (LA5_0=='\\') ) {
+                            alt5=1;
+                        }
+                        else if ( ((LA5_0>='\u0000' && LA5_0<='!')||(LA5_0>='#' && LA5_0<='[')||(LA5_0>=']' && LA5_0<='\uFFFF')) ) {
+                            alt5=2;
+                        }
+
+
+                        switch (alt5) {
+                    	case 1 :
+                    	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:21: '\\\\' .
+                    	    {
+                    	    match('\\'); 
+                    	    matchAny(); 
+
+                    	    }
+                    	    break;
+                    	case 2 :
+                    	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:28: ~ ( ( '\\\\' | '\"' ) )
+                    	    {
+                    	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='!')||(input.LA(1)>='#' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFF') ) {
+                    	        input.consume();
+
+                    	    }
+                    	    else {
+                    	        MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        recover(mse);
+                    	        throw mse;}
+
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop5;
+                        }
+                    } while (true);
+
+                    match('\"'); 
+
+                    }
+                    break;
+                case 2 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:48: '\\'' ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )* '\\''
+                    {
+                    match('\''); 
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:53: ( '\\\\' . | ~ ( ( '\\\\' | '\\'' ) ) )*
+                    loop6:
+                    do {
+                        int alt6=3;
+                        int LA6_0 = input.LA(1);
+
+                        if ( (LA6_0=='\\') ) {
+                            alt6=1;
+                        }
+                        else if ( ((LA6_0>='\u0000' && LA6_0<='&')||(LA6_0>='(' && LA6_0<='[')||(LA6_0>=']' && LA6_0<='\uFFFF')) ) {
+                            alt6=2;
+                        }
+
+
+                        switch (alt6) {
+                    	case 1 :
+                    	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:54: '\\\\' .
+                    	    {
+                    	    match('\\'); 
+                    	    matchAny(); 
+
+                    	    }
+                    	    break;
+                    	case 2 :
+                    	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:579:61: ~ ( ( '\\\\' | '\\'' ) )
+                    	    {
+                    	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFF') ) {
+                    	        input.consume();
+
+                    	    }
+                    	    else {
+                    	        MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        recover(mse);
+                    	        throw mse;}
+
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop6;
+                        }
+                    } while (true);
+
+                    match('\''); 
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_STRING"
+
+    // $ANTLR start "RULE_ML_COMMENT"
+    public final void mRULE_ML_COMMENT() throws RecognitionException {
+        try {
+            int _type = RULE_ML_COMMENT;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:581:17: ( '/*' ( options {greedy=false; } : . )* '*/' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:581:19: '/*' ( options {greedy=false; } : . )* '*/'
+            {
+            match("/*"); 
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:581:24: ( options {greedy=false; } : . )*
+            loop8:
+            do {
+                int alt8=2;
+                int LA8_0 = input.LA(1);
+
+                if ( (LA8_0=='*') ) {
+                    int LA8_1 = input.LA(2);
+
+                    if ( (LA8_1=='/') ) {
+                        alt8=2;
+                    }
+                    else if ( ((LA8_1>='\u0000' && LA8_1<='.')||(LA8_1>='0' && LA8_1<='\uFFFF')) ) {
+                        alt8=1;
+                    }
+
+
+                }
+                else if ( ((LA8_0>='\u0000' && LA8_0<=')')||(LA8_0>='+' && LA8_0<='\uFFFF')) ) {
+                    alt8=1;
+                }
+
+
+                switch (alt8) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:581:52: .
+            	    {
+            	    matchAny(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop8;
+                }
+            } while (true);
+
+            match("*/"); 
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_ML_COMMENT"
+
+    // $ANTLR start "RULE_SL_COMMENT"
+    public final void mRULE_SL_COMMENT() throws RecognitionException {
+        try {
+            int _type = RULE_SL_COMMENT;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:17: ( '//' (~ ( ( '\\n' | '\\r' ) ) )* ( ( '\\r' )? '\\n' )? )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:19: '//' (~ ( ( '\\n' | '\\r' ) ) )* ( ( '\\r' )? '\\n' )?
+            {
+            match("//"); 
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:24: (~ ( ( '\\n' | '\\r' ) ) )*
+            loop9:
+            do {
+                int alt9=2;
+                int LA9_0 = input.LA(1);
+
+                if ( ((LA9_0>='\u0000' && LA9_0<='\t')||(LA9_0>='\u000B' && LA9_0<='\f')||(LA9_0>='\u000E' && LA9_0<='\uFFFF')) ) {
+                    alt9=1;
+                }
+
+
+                switch (alt9) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:24: ~ ( ( '\\n' | '\\r' ) )
+            	    {
+            	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='\t')||(input.LA(1)>='\u000B' && input.LA(1)<='\f')||(input.LA(1)>='\u000E' && input.LA(1)<='\uFFFF') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        recover(mse);
+            	        throw mse;}
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop9;
+                }
+            } while (true);
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:40: ( ( '\\r' )? '\\n' )?
+            int alt11=2;
+            int LA11_0 = input.LA(1);
+
+            if ( (LA11_0=='\n'||LA11_0=='\r') ) {
+                alt11=1;
+            }
+            switch (alt11) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:41: ( '\\r' )? '\\n'
+                    {
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:41: ( '\\r' )?
+                    int alt10=2;
+                    int LA10_0 = input.LA(1);
+
+                    if ( (LA10_0=='\r') ) {
+                        alt10=1;
+                    }
+                    switch (alt10) {
+                        case 1 :
+                            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:583:41: '\\r'
+                            {
+                            match('\r'); 
+
+                            }
+                            break;
+
+                    }
+
+                    match('\n'); 
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_SL_COMMENT"
+
+    // $ANTLR start "RULE_WS"
+    public final void mRULE_WS() throws RecognitionException {
+        try {
+            int _type = RULE_WS;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:585:9: ( ( ' ' | '\\t' | '\\r' | '\\n' )+ )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:585:11: ( ' ' | '\\t' | '\\r' | '\\n' )+
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:585:11: ( ' ' | '\\t' | '\\r' | '\\n' )+
+            int cnt12=0;
+            loop12:
+            do {
+                int alt12=2;
+                int LA12_0 = input.LA(1);
+
+                if ( ((LA12_0>='\t' && LA12_0<='\n')||LA12_0=='\r'||LA12_0==' ') ) {
+                    alt12=1;
+                }
+
+
+                switch (alt12) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:
+            	    {
+            	    if ( (input.LA(1)>='\t' && input.LA(1)<='\n')||input.LA(1)=='\r'||input.LA(1)==' ' ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        recover(mse);
+            	        throw mse;}
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt12 >= 1 ) break loop12;
+                        EarlyExitException eee =
+                            new EarlyExitException(12, input);
+                        throw eee;
+                }
+                cnt12++;
+            } while (true);
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_WS"
+
+    // $ANTLR start "RULE_ANY_OTHER"
+    public final void mRULE_ANY_OTHER() throws RecognitionException {
+        try {
+            int _type = RULE_ANY_OTHER;
+            int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:587:16: ( . )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:587:18: .
+            {
+            matchAny(); 
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end "RULE_ANY_OTHER"
+
+    public void mTokens() throws RecognitionException {
+        // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:8: ( T__12 | T__13 | T__14 | T__15 | T__16 | T__17 | T__18 | T__19 | T__20 | T__21 | T__22 | RULE_BOOLEAN | RULE_ID | RULE_INT | RULE_STRING | RULE_ML_COMMENT | RULE_SL_COMMENT | RULE_WS | RULE_ANY_OTHER )
+        int alt13=19;
+        alt13 = dfa13.predict(input);
+        switch (alt13) {
+            case 1 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:10: T__12
+                {
+                mT__12(); 
+
+                }
+                break;
+            case 2 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:16: T__13
+                {
+                mT__13(); 
+
+                }
+                break;
+            case 3 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:22: T__14
+                {
+                mT__14(); 
+
+                }
+                break;
+            case 4 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:28: T__15
+                {
+                mT__15(); 
+
+                }
+                break;
+            case 5 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:34: T__16
+                {
+                mT__16(); 
+
+                }
+                break;
+            case 6 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:40: T__17
+                {
+                mT__17(); 
+
+                }
+                break;
+            case 7 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:46: T__18
+                {
+                mT__18(); 
+
+                }
+                break;
+            case 8 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:52: T__19
+                {
+                mT__19(); 
+
+                }
+                break;
+            case 9 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:58: T__20
+                {
+                mT__20(); 
+
+                }
+                break;
+            case 10 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:64: T__21
+                {
+                mT__21(); 
+
+                }
+                break;
+            case 11 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:70: T__22
+                {
+                mT__22(); 
+
+                }
+                break;
+            case 12 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:76: RULE_BOOLEAN
+                {
+                mRULE_BOOLEAN(); 
+
+                }
+                break;
+            case 13 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:89: RULE_ID
+                {
+                mRULE_ID(); 
+
+                }
+                break;
+            case 14 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:97: RULE_INT
+                {
+                mRULE_INT(); 
+
+                }
+                break;
+            case 15 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:106: RULE_STRING
+                {
+                mRULE_STRING(); 
+
+                }
+                break;
+            case 16 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:118: RULE_ML_COMMENT
+                {
+                mRULE_ML_COMMENT(); 
+
+                }
+                break;
+            case 17 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:134: RULE_SL_COMMENT
+                {
+                mRULE_SL_COMMENT(); 
+
+                }
+                break;
+            case 18 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:150: RULE_WS
+                {
+                mRULE_WS(); 
+
+                }
+                break;
+            case 19 :
+                // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:1:158: RULE_ANY_OTHER
+                {
+                mRULE_ANY_OTHER(); 
+
+                }
+                break;
+
+        }
+
+    }
+
+
+    protected DFA13 dfa13 = new DFA13(this);
+    static final String DFA13_eotS =
+        "\1\uffff\6\25\1\35\2\25\1\21\2\uffff\3\21\2\uffff\3\25\1\uffff\1\25\1\51\4\25\2\uffff\2\25\5\uffff\2\25\1\62\1\25\1\uffff\1\25\1\65\1\25\1\67\4\25\1\uffff\2\25\1\uffff\1\76\1\uffff\1\77\2\25\1\102\1\103\1\25\2\uffff\1\77\1\105\2\uffff\1\106\2\uffff";
+    static final String DFA13_eofS =
+        "\107\uffff";
+    static final String DFA13_minS =
+        "\1\0\1\145\1\146\1\165\1\156\1\157\1\156\1\75\1\162\1\141\1\101\2\uffff\2\0\1\52\2\uffff\1\147\1\141\1\164\1\uffff\1\160\1\60\1\164\1\144\1\164\1\144\2\uffff\1\165\1\154\5\uffff\1\156\1\164\1\60\1\165\1\uffff\1\160\1\60\1\157\1\60\1\145\1\163\1\141\1\145\1\uffff\1\164\1\165\1\uffff\1\60\1\uffff\1\60\1\145\1\154\2\60\1\164\2\uffff\2\60\2\uffff\1\60\2\uffff";
+    static final String DFA13_maxS =
+        "\1\uffff\1\164\1\156\1\165\1\156\1\157\1\156\1\75\1\162\1\141\1\172\2\uffff\2\uffff\1\57\2\uffff\1\147\1\141\1\164\1\uffff\1\160\1\172\1\164\1\144\1\164\1\144\2\uffff\1\165\1\154\5\uffff\1\156\1\164\1\172\1\165\1\uffff\1\160\1\172\1\157\1\172\1\145\1\163\1\141\1\145\1\uffff\1\164\1\165\1\uffff\1\172\1\uffff\1\172\1\145\1\154\2\172\1\164\2\uffff\2\172\2\uffff\1\172\2\uffff";
+    static final String DFA13_acceptS =
+        "\13\uffff\1\15\1\16\3\uffff\1\22\1\23\3\uffff\1\15\6\uffff\1\11\1\13\2\uffff\1\16\1\17\1\20\1\21\1\22\4\uffff\1\6\10\uffff\1\12\2\uffff\1\5\1\uffff\1\10\6\uffff\1\7\1\14\2\uffff\1\4\1\2\1\uffff\1\1\1\3";
+    static final String DFA13_specialS =
+        "\1\1\14\uffff\1\0\1\2\70\uffff}>";
+    static final String[] DFA13_transitionS = {
+            "\11\21\2\20\2\21\1\20\22\21\1\20\1\21\1\15\4\21\1\16\7\21\1\17\12\14\3\21\1\7\3\21\32\13\3\21\1\12\1\13\1\21\1\6\3\13\1\4\1\11\1\5\1\13\1\2\5\13\1\3\3\13\1\1\1\10\6\13\uff85\21",
+            "\1\24\3\uffff\1\22\12\uffff\1\23",
+            "\1\27\7\uffff\1\26",
+            "\1\30",
+            "\1\31",
+            "\1\32",
+            "\1\33",
+            "\1\34",
+            "\1\36",
+            "\1\37",
+            "\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            "",
+            "\0\41",
+            "\0\41",
+            "\1\42\4\uffff\1\43",
+            "",
+            "",
+            "\1\45",
+            "\1\46",
+            "\1\47",
+            "",
+            "\1\50",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\52",
+            "\1\53",
+            "\1\54",
+            "\1\55",
+            "",
+            "",
+            "\1\56",
+            "\1\57",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\1\60",
+            "\1\61",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\63",
+            "",
+            "\1\64",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\66",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\70",
+            "\1\71",
+            "\1\72",
+            "\1\73",
+            "",
+            "\1\74",
+            "\1\75",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\100",
+            "\1\101",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\1\104",
+            "",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            "",
+            "\12\25\7\uffff\32\25\4\uffff\1\25\1\uffff\32\25",
+            "",
+            ""
+    };
+
+    static final short[] DFA13_eot = DFA.unpackEncodedString(DFA13_eotS);
+    static final short[] DFA13_eof = DFA.unpackEncodedString(DFA13_eofS);
+    static final char[] DFA13_min = DFA.unpackEncodedStringToUnsignedChars(DFA13_minS);
+    static final char[] DFA13_max = DFA.unpackEncodedStringToUnsignedChars(DFA13_maxS);
+    static final short[] DFA13_accept = DFA.unpackEncodedString(DFA13_acceptS);
+    static final short[] DFA13_special = DFA.unpackEncodedString(DFA13_specialS);
+    static final short[][] DFA13_transition;
+
+    static {
+        int numStates = DFA13_transitionS.length;
+        DFA13_transition = new short[numStates][];
+        for (int i=0; i<numStates; i++) {
+            DFA13_transition[i] = DFA.unpackEncodedString(DFA13_transitionS[i]);
+        }
+    }
+
+    class DFA13 extends DFA {
+
+        public DFA13(BaseRecognizer recognizer) {
+            this.recognizer = recognizer;
+            this.decisionNumber = 13;
+            this.eot = DFA13_eot;
+            this.eof = DFA13_eof;
+            this.min = DFA13_min;
+            this.max = DFA13_max;
+            this.accept = DFA13_accept;
+            this.special = DFA13_special;
+            this.transition = DFA13_transition;
+        }
+        public String getDescription() {
+            return "1:1: Tokens : ( T__12 | T__13 | T__14 | T__15 | T__16 | T__17 | T__18 | T__19 | T__20 | T__21 | T__22 | RULE_BOOLEAN | RULE_ID | RULE_INT | RULE_STRING | RULE_ML_COMMENT | RULE_SL_COMMENT | RULE_WS | RULE_ANY_OTHER );";
+        }
+        public int specialStateTransition(int s, IntStream _input) throws NoViableAltException {
+            IntStream input = _input;
+        	int _s = s;
+            switch ( s ) {
+                    case 0 : 
+                        int LA13_13 = input.LA(1);
+
+                        s = -1;
+                        if ( ((LA13_13>='\u0000' && LA13_13<='\uFFFF')) ) {s = 33;}
+
+                        else s = 17;
+
+                        if ( s>=0 ) return s;
+                        break;
+                    case 1 : 
+                        int LA13_0 = input.LA(1);
+
+                        s = -1;
+                        if ( (LA13_0=='s') ) {s = 1;}
+
+                        else if ( (LA13_0=='i') ) {s = 2;}
+
+                        else if ( (LA13_0=='o') ) {s = 3;}
+
+                        else if ( (LA13_0=='e') ) {s = 4;}
+
+                        else if ( (LA13_0=='g') ) {s = 5;}
+
+                        else if ( (LA13_0=='a') ) {s = 6;}
+
+                        else if ( (LA13_0=='=') ) {s = 7;}
+
+                        else if ( (LA13_0=='t') ) {s = 8;}
+
+                        else if ( (LA13_0=='f') ) {s = 9;}
+
+                        else if ( (LA13_0=='^') ) {s = 10;}
+
+                        else if ( ((LA13_0>='A' && LA13_0<='Z')||LA13_0=='_'||(LA13_0>='b' && LA13_0<='d')||LA13_0=='h'||(LA13_0>='j' && LA13_0<='n')||(LA13_0>='p' && LA13_0<='r')||(LA13_0>='u' && LA13_0<='z')) ) {s = 11;}
+
+                        else if ( ((LA13_0>='0' && LA13_0<='9')) ) {s = 12;}
+
+                        else if ( (LA13_0=='\"') ) {s = 13;}
+
+                        else if ( (LA13_0=='\'') ) {s = 14;}
+
+                        else if ( (LA13_0=='/') ) {s = 15;}
+
+                        else if ( ((LA13_0>='\t' && LA13_0<='\n')||LA13_0=='\r'||LA13_0==' ') ) {s = 16;}
+
+                        else if ( ((LA13_0>='\u0000' && LA13_0<='\b')||(LA13_0>='\u000B' && LA13_0<='\f')||(LA13_0>='\u000E' && LA13_0<='\u001F')||LA13_0=='!'||(LA13_0>='#' && LA13_0<='&')||(LA13_0>='(' && LA13_0<='.')||(LA13_0>=':' && LA13_0<='<')||(LA13_0>='>' && LA13_0<='@')||(LA13_0>='[' && LA13_0<=']')||LA13_0=='`'||(LA13_0>='{' && LA13_0<='\uFFFF')) ) {s = 17;}
+
+                        if ( s>=0 ) return s;
+                        break;
+                    case 2 : 
+                        int LA13_14 = input.LA(1);
+
+                        s = -1;
+                        if ( ((LA13_14>='\u0000' && LA13_14<='\uFFFF')) ) {s = 33;}
+
+                        else s = 17;
+
+                        if ( s>=0 ) return s;
+                        break;
+            }
+            NoViableAltException nvae =
+                new NoViableAltException(getDescription(), 13, _s, input);
+            error(nvae);
+            throw nvae;
+        }
+    }
+ 
+
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineParser.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineParser.java
new file mode 100644
index 0000000..f862228
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineParser.java
@@ -0,0 +1,1423 @@
+package org.eclipse.fx.xtext.statemachine.parser.antlr.internal; 
+
+import org.eclipse.xtext.*;
+import org.eclipse.xtext.parser.*;
+import org.eclipse.xtext.parser.impl.*;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.parser.antlr.AbstractInternalAntlrParser;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream;
+import org.eclipse.xtext.parser.antlr.XtextTokenStream.HiddenTokens;
+import org.eclipse.xtext.parser.antlr.AntlrDatatypeRuleToken;
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+
+
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+@SuppressWarnings("all")
+public class InternalStatemachineParser extends AbstractInternalAntlrParser {
+    public static final String[] tokenNames = new String[] {
+        "<invalid>", "<EOR>", "<DOWN>", "<UP>", "RULE_ID", "RULE_BOOLEAN", "RULE_INT", "RULE_STRING", "RULE_ML_COMMENT", "RULE_SL_COMMENT", "RULE_WS", "RULE_ANY_OTHER", "'signal'", "'input'", "'output'", "'state'", "'end'", "'if'", "'goto'", "'and'", "'=='", "'set'", "'='"
+    };
+    public static final int RULE_BOOLEAN=5;
+    public static final int RULE_STRING=7;
+    public static final int RULE_SL_COMMENT=9;
+    public static final int T__19=19;
+    public static final int T__15=15;
+    public static final int T__16=16;
+    public static final int T__17=17;
+    public static final int T__18=18;
+    public static final int T__12=12;
+    public static final int T__13=13;
+    public static final int T__14=14;
+    public static final int EOF=-1;
+    public static final int RULE_ID=4;
+    public static final int RULE_WS=10;
+    public static final int RULE_ANY_OTHER=11;
+    public static final int RULE_INT=6;
+    public static final int T__22=22;
+    public static final int RULE_ML_COMMENT=8;
+    public static final int T__20=20;
+    public static final int T__21=21;
+
+    // delegates
+    // delegators
+
+
+        public InternalStatemachineParser(TokenStream input) {
+            this(input, new RecognizerSharedState());
+        }
+        public InternalStatemachineParser(TokenStream input, RecognizerSharedState state) {
+            super(input, state);
+             
+        }
+        
+
+    public String[] getTokenNames() { return InternalStatemachineParser.tokenNames; }
+    public String getGrammarFileName() { return "../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g"; }
+
+
+
+     	private StatemachineGrammarAccess grammarAccess;
+     	
+        public InternalStatemachineParser(TokenStream input, StatemachineGrammarAccess grammarAccess) {
+            this(input);
+            this.grammarAccess = grammarAccess;
+            registerRules(grammarAccess.getGrammar());
+        }
+        
+        @Override
+        protected String getFirstRuleName() {
+        	return "Statemachine";	
+       	}
+       	
+       	@Override
+       	protected StatemachineGrammarAccess getGrammarAccess() {
+       		return grammarAccess;
+       	}
+
+
+
+    // $ANTLR start "entryRuleStatemachine"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:67:1: entryRuleStatemachine returns [EObject current=null] : iv_ruleStatemachine= ruleStatemachine EOF ;
+    public final EObject entryRuleStatemachine() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleStatemachine = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:68:2: (iv_ruleStatemachine= ruleStatemachine EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:69:2: iv_ruleStatemachine= ruleStatemachine EOF
+            {
+             newCompositeNode(grammarAccess.getStatemachineRule()); 
+            pushFollow(FOLLOW_ruleStatemachine_in_entryRuleStatemachine75);
+            iv_ruleStatemachine=ruleStatemachine();
+
+            state._fsp--;
+
+             current =iv_ruleStatemachine; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleStatemachine85); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleStatemachine"
+
+
+    // $ANTLR start "ruleStatemachine"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:76:1: ruleStatemachine returns [EObject current=null] : ( () ( (lv_signals_1_0= ruleSignal ) )* ( (lv_states_2_0= ruleState ) )* ) ;
+    public final EObject ruleStatemachine() throws RecognitionException {
+        EObject current = null;
+
+        EObject lv_signals_1_0 = null;
+
+        EObject lv_states_2_0 = null;
+
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:79:28: ( ( () ( (lv_signals_1_0= ruleSignal ) )* ( (lv_states_2_0= ruleState ) )* ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:80:1: ( () ( (lv_signals_1_0= ruleSignal ) )* ( (lv_states_2_0= ruleState ) )* )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:80:1: ( () ( (lv_signals_1_0= ruleSignal ) )* ( (lv_states_2_0= ruleState ) )* )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:80:2: () ( (lv_signals_1_0= ruleSignal ) )* ( (lv_states_2_0= ruleState ) )*
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:80:2: ()
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:81:5: 
+            {
+
+                    current = forceCreateModelElement(
+                        grammarAccess.getStatemachineAccess().getStatemachineAction_0(),
+                        current);
+                
+
+            }
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:86:2: ( (lv_signals_1_0= ruleSignal ) )*
+            loop1:
+            do {
+                int alt1=2;
+                int LA1_0 = input.LA(1);
+
+                if ( ((LA1_0>=13 && LA1_0<=14)) ) {
+                    alt1=1;
+                }
+
+
+                switch (alt1) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:87:1: (lv_signals_1_0= ruleSignal )
+            	    {
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:87:1: (lv_signals_1_0= ruleSignal )
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:88:3: lv_signals_1_0= ruleSignal
+            	    {
+            	     
+            	    	        newCompositeNode(grammarAccess.getStatemachineAccess().getSignalsSignalParserRuleCall_1_0()); 
+            	    	    
+            	    pushFollow(FOLLOW_ruleSignal_in_ruleStatemachine140);
+            	    lv_signals_1_0=ruleSignal();
+
+            	    state._fsp--;
+
+
+            	    	        if (current==null) {
+            	    	            current = createModelElementForParent(grammarAccess.getStatemachineRule());
+            	    	        }
+            	           		add(
+            	           			current, 
+            	           			"signals",
+            	            		lv_signals_1_0, 
+            	            		"Signal");
+            	    	        afterParserOrEnumRuleCall();
+            	    	    
+
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop1;
+                }
+            } while (true);
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:104:3: ( (lv_states_2_0= ruleState ) )*
+            loop2:
+            do {
+                int alt2=2;
+                int LA2_0 = input.LA(1);
+
+                if ( (LA2_0==15) ) {
+                    alt2=1;
+                }
+
+
+                switch (alt2) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:105:1: (lv_states_2_0= ruleState )
+            	    {
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:105:1: (lv_states_2_0= ruleState )
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:106:3: lv_states_2_0= ruleState
+            	    {
+            	     
+            	    	        newCompositeNode(grammarAccess.getStatemachineAccess().getStatesStateParserRuleCall_2_0()); 
+            	    	    
+            	    pushFollow(FOLLOW_ruleState_in_ruleStatemachine162);
+            	    lv_states_2_0=ruleState();
+
+            	    state._fsp--;
+
+
+            	    	        if (current==null) {
+            	    	            current = createModelElementForParent(grammarAccess.getStatemachineRule());
+            	    	        }
+            	           		add(
+            	           			current, 
+            	           			"states",
+            	            		lv_states_2_0, 
+            	            		"State");
+            	    	        afterParserOrEnumRuleCall();
+            	    	    
+
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop2;
+                }
+            } while (true);
+
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleStatemachine"
+
+
+    // $ANTLR start "entryRuleSignal"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:130:1: entryRuleSignal returns [EObject current=null] : iv_ruleSignal= ruleSignal EOF ;
+    public final EObject entryRuleSignal() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleSignal = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:131:2: (iv_ruleSignal= ruleSignal EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:132:2: iv_ruleSignal= ruleSignal EOF
+            {
+             newCompositeNode(grammarAccess.getSignalRule()); 
+            pushFollow(FOLLOW_ruleSignal_in_entryRuleSignal199);
+            iv_ruleSignal=ruleSignal();
+
+            state._fsp--;
+
+             current =iv_ruleSignal; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleSignal209); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleSignal"
+
+
+    // $ANTLR start "ruleSignal"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:139:1: ruleSignal returns [EObject current=null] : ( (this_InputSignal_0= ruleInputSignal | this_OutputSignal_1= ruleOutputSignal ) otherlv_2= 'signal' ( (lv_name_3_0= RULE_ID ) ) ) ;
+    public final EObject ruleSignal() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_2=null;
+        Token lv_name_3_0=null;
+        EObject this_InputSignal_0 = null;
+
+        EObject this_OutputSignal_1 = null;
+
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:142:28: ( ( (this_InputSignal_0= ruleInputSignal | this_OutputSignal_1= ruleOutputSignal ) otherlv_2= 'signal' ( (lv_name_3_0= RULE_ID ) ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:143:1: ( (this_InputSignal_0= ruleInputSignal | this_OutputSignal_1= ruleOutputSignal ) otherlv_2= 'signal' ( (lv_name_3_0= RULE_ID ) ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:143:1: ( (this_InputSignal_0= ruleInputSignal | this_OutputSignal_1= ruleOutputSignal ) otherlv_2= 'signal' ( (lv_name_3_0= RULE_ID ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:143:2: (this_InputSignal_0= ruleInputSignal | this_OutputSignal_1= ruleOutputSignal ) otherlv_2= 'signal' ( (lv_name_3_0= RULE_ID ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:143:2: (this_InputSignal_0= ruleInputSignal | this_OutputSignal_1= ruleOutputSignal )
+            int alt3=2;
+            int LA3_0 = input.LA(1);
+
+            if ( (LA3_0==13) ) {
+                alt3=1;
+            }
+            else if ( (LA3_0==14) ) {
+                alt3=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 3, 0, input);
+
+                throw nvae;
+            }
+            switch (alt3) {
+                case 1 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:144:5: this_InputSignal_0= ruleInputSignal
+                    {
+                     
+                            newCompositeNode(grammarAccess.getSignalAccess().getInputSignalParserRuleCall_0_0()); 
+                        
+                    pushFollow(FOLLOW_ruleInputSignal_in_ruleSignal257);
+                    this_InputSignal_0=ruleInputSignal();
+
+                    state._fsp--;
+
+                     
+                            current = this_InputSignal_0; 
+                            afterParserOrEnumRuleCall();
+                        
+
+                    }
+                    break;
+                case 2 :
+                    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:154:5: this_OutputSignal_1= ruleOutputSignal
+                    {
+                     
+                            newCompositeNode(grammarAccess.getSignalAccess().getOutputSignalParserRuleCall_0_1()); 
+                        
+                    pushFollow(FOLLOW_ruleOutputSignal_in_ruleSignal284);
+                    this_OutputSignal_1=ruleOutputSignal();
+
+                    state._fsp--;
+
+                     
+                            current = this_OutputSignal_1; 
+                            afterParserOrEnumRuleCall();
+                        
+
+                    }
+                    break;
+
+            }
+
+            otherlv_2=(Token)match(input,12,FOLLOW_12_in_ruleSignal296); 
+
+                	newLeafNode(otherlv_2, grammarAccess.getSignalAccess().getSignalKeyword_1());
+                
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:166:1: ( (lv_name_3_0= RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:167:1: (lv_name_3_0= RULE_ID )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:167:1: (lv_name_3_0= RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:168:3: lv_name_3_0= RULE_ID
+            {
+            lv_name_3_0=(Token)match(input,RULE_ID,FOLLOW_RULE_ID_in_ruleSignal313); 
+
+            			newLeafNode(lv_name_3_0, grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0()); 
+            		
+
+            	        if (current==null) {
+            	            current = createModelElement(grammarAccess.getSignalRule());
+            	        }
+                   		setWithLastConsumed(
+                   			current, 
+                   			"name",
+                    		lv_name_3_0, 
+                    		"ID");
+            	    
+
+            }
+
+
+            }
+
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleSignal"
+
+
+    // $ANTLR start "entryRuleInputSignal"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:192:1: entryRuleInputSignal returns [EObject current=null] : iv_ruleInputSignal= ruleInputSignal EOF ;
+    public final EObject entryRuleInputSignal() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleInputSignal = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:193:2: (iv_ruleInputSignal= ruleInputSignal EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:194:2: iv_ruleInputSignal= ruleInputSignal EOF
+            {
+             newCompositeNode(grammarAccess.getInputSignalRule()); 
+            pushFollow(FOLLOW_ruleInputSignal_in_entryRuleInputSignal354);
+            iv_ruleInputSignal=ruleInputSignal();
+
+            state._fsp--;
+
+             current =iv_ruleInputSignal; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleInputSignal364); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleInputSignal"
+
+
+    // $ANTLR start "ruleInputSignal"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:201:1: ruleInputSignal returns [EObject current=null] : ( () otherlv_1= 'input' ) ;
+    public final EObject ruleInputSignal() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_1=null;
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:204:28: ( ( () otherlv_1= 'input' ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:205:1: ( () otherlv_1= 'input' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:205:1: ( () otherlv_1= 'input' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:205:2: () otherlv_1= 'input'
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:205:2: ()
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:206:5: 
+            {
+
+                    current = forceCreateModelElement(
+                        grammarAccess.getInputSignalAccess().getInputSignalAction_0(),
+                        current);
+                
+
+            }
+
+            otherlv_1=(Token)match(input,13,FOLLOW_13_in_ruleInputSignal410); 
+
+                	newLeafNode(otherlv_1, grammarAccess.getInputSignalAccess().getInputKeyword_1());
+                
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleInputSignal"
+
+
+    // $ANTLR start "entryRuleOutputSignal"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:223:1: entryRuleOutputSignal returns [EObject current=null] : iv_ruleOutputSignal= ruleOutputSignal EOF ;
+    public final EObject entryRuleOutputSignal() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleOutputSignal = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:224:2: (iv_ruleOutputSignal= ruleOutputSignal EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:225:2: iv_ruleOutputSignal= ruleOutputSignal EOF
+            {
+             newCompositeNode(grammarAccess.getOutputSignalRule()); 
+            pushFollow(FOLLOW_ruleOutputSignal_in_entryRuleOutputSignal446);
+            iv_ruleOutputSignal=ruleOutputSignal();
+
+            state._fsp--;
+
+             current =iv_ruleOutputSignal; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleOutputSignal456); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleOutputSignal"
+
+
+    // $ANTLR start "ruleOutputSignal"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:232:1: ruleOutputSignal returns [EObject current=null] : ( () otherlv_1= 'output' ) ;
+    public final EObject ruleOutputSignal() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_1=null;
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:235:28: ( ( () otherlv_1= 'output' ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:236:1: ( () otherlv_1= 'output' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:236:1: ( () otherlv_1= 'output' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:236:2: () otherlv_1= 'output'
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:236:2: ()
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:237:5: 
+            {
+
+                    current = forceCreateModelElement(
+                        grammarAccess.getOutputSignalAccess().getOutputSignalAction_0(),
+                        current);
+                
+
+            }
+
+            otherlv_1=(Token)match(input,14,FOLLOW_14_in_ruleOutputSignal502); 
+
+                	newLeafNode(otherlv_1, grammarAccess.getOutputSignalAccess().getOutputKeyword_1());
+                
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleOutputSignal"
+
+
+    // $ANTLR start "entryRuleState"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:254:1: entryRuleState returns [EObject current=null] : iv_ruleState= ruleState EOF ;
+    public final EObject entryRuleState() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleState = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:255:2: (iv_ruleState= ruleState EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:256:2: iv_ruleState= ruleState EOF
+            {
+             newCompositeNode(grammarAccess.getStateRule()); 
+            pushFollow(FOLLOW_ruleState_in_entryRuleState538);
+            iv_ruleState=ruleState();
+
+            state._fsp--;
+
+             current =iv_ruleState; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleState548); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleState"
+
+
+    // $ANTLR start "ruleState"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:263:1: ruleState returns [EObject current=null] : (otherlv_0= 'state' ( (lv_name_1_0= RULE_ID ) ) ( (lv_commands_2_0= ruleCommand ) )* ( (lv_transitions_3_0= ruleTransition ) )* otherlv_4= 'end' ) ;
+    public final EObject ruleState() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_0=null;
+        Token lv_name_1_0=null;
+        Token otherlv_4=null;
+        EObject lv_commands_2_0 = null;
+
+        EObject lv_transitions_3_0 = null;
+
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:266:28: ( (otherlv_0= 'state' ( (lv_name_1_0= RULE_ID ) ) ( (lv_commands_2_0= ruleCommand ) )* ( (lv_transitions_3_0= ruleTransition ) )* otherlv_4= 'end' ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:267:1: (otherlv_0= 'state' ( (lv_name_1_0= RULE_ID ) ) ( (lv_commands_2_0= ruleCommand ) )* ( (lv_transitions_3_0= ruleTransition ) )* otherlv_4= 'end' )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:267:1: (otherlv_0= 'state' ( (lv_name_1_0= RULE_ID ) ) ( (lv_commands_2_0= ruleCommand ) )* ( (lv_transitions_3_0= ruleTransition ) )* otherlv_4= 'end' )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:267:3: otherlv_0= 'state' ( (lv_name_1_0= RULE_ID ) ) ( (lv_commands_2_0= ruleCommand ) )* ( (lv_transitions_3_0= ruleTransition ) )* otherlv_4= 'end'
+            {
+            otherlv_0=(Token)match(input,15,FOLLOW_15_in_ruleState585); 
+
+                	newLeafNode(otherlv_0, grammarAccess.getStateAccess().getStateKeyword_0());
+                
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:271:1: ( (lv_name_1_0= RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:272:1: (lv_name_1_0= RULE_ID )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:272:1: (lv_name_1_0= RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:273:3: lv_name_1_0= RULE_ID
+            {
+            lv_name_1_0=(Token)match(input,RULE_ID,FOLLOW_RULE_ID_in_ruleState602); 
+
+            			newLeafNode(lv_name_1_0, grammarAccess.getStateAccess().getNameIDTerminalRuleCall_1_0()); 
+            		
+
+            	        if (current==null) {
+            	            current = createModelElement(grammarAccess.getStateRule());
+            	        }
+                   		setWithLastConsumed(
+                   			current, 
+                   			"name",
+                    		lv_name_1_0, 
+                    		"ID");
+            	    
+
+            }
+
+
+            }
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:289:2: ( (lv_commands_2_0= ruleCommand ) )*
+            loop4:
+            do {
+                int alt4=2;
+                int LA4_0 = input.LA(1);
+
+                if ( (LA4_0==21) ) {
+                    alt4=1;
+                }
+
+
+                switch (alt4) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:290:1: (lv_commands_2_0= ruleCommand )
+            	    {
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:290:1: (lv_commands_2_0= ruleCommand )
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:291:3: lv_commands_2_0= ruleCommand
+            	    {
+            	     
+            	    	        newCompositeNode(grammarAccess.getStateAccess().getCommandsCommandParserRuleCall_2_0()); 
+            	    	    
+            	    pushFollow(FOLLOW_ruleCommand_in_ruleState628);
+            	    lv_commands_2_0=ruleCommand();
+
+            	    state._fsp--;
+
+
+            	    	        if (current==null) {
+            	    	            current = createModelElementForParent(grammarAccess.getStateRule());
+            	    	        }
+            	           		add(
+            	           			current, 
+            	           			"commands",
+            	            		lv_commands_2_0, 
+            	            		"Command");
+            	    	        afterParserOrEnumRuleCall();
+            	    	    
+
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop4;
+                }
+            } while (true);
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:307:3: ( (lv_transitions_3_0= ruleTransition ) )*
+            loop5:
+            do {
+                int alt5=2;
+                int LA5_0 = input.LA(1);
+
+                if ( (LA5_0==17) ) {
+                    alt5=1;
+                }
+
+
+                switch (alt5) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:308:1: (lv_transitions_3_0= ruleTransition )
+            	    {
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:308:1: (lv_transitions_3_0= ruleTransition )
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:309:3: lv_transitions_3_0= ruleTransition
+            	    {
+            	     
+            	    	        newCompositeNode(grammarAccess.getStateAccess().getTransitionsTransitionParserRuleCall_3_0()); 
+            	    	    
+            	    pushFollow(FOLLOW_ruleTransition_in_ruleState650);
+            	    lv_transitions_3_0=ruleTransition();
+
+            	    state._fsp--;
+
+
+            	    	        if (current==null) {
+            	    	            current = createModelElementForParent(grammarAccess.getStateRule());
+            	    	        }
+            	           		add(
+            	           			current, 
+            	           			"transitions",
+            	            		lv_transitions_3_0, 
+            	            		"Transition");
+            	    	        afterParserOrEnumRuleCall();
+            	    	    
+
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop5;
+                }
+            } while (true);
+
+            otherlv_4=(Token)match(input,16,FOLLOW_16_in_ruleState663); 
+
+                	newLeafNode(otherlv_4, grammarAccess.getStateAccess().getEndKeyword_4());
+                
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleState"
+
+
+    // $ANTLR start "entryRuleTransition"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:337:1: entryRuleTransition returns [EObject current=null] : iv_ruleTransition= ruleTransition EOF ;
+    public final EObject entryRuleTransition() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleTransition = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:338:2: (iv_ruleTransition= ruleTransition EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:339:2: iv_ruleTransition= ruleTransition EOF
+            {
+             newCompositeNode(grammarAccess.getTransitionRule()); 
+            pushFollow(FOLLOW_ruleTransition_in_entryRuleTransition699);
+            iv_ruleTransition=ruleTransition();
+
+            state._fsp--;
+
+             current =iv_ruleTransition; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleTransition709); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleTransition"
+
+
+    // $ANTLR start "ruleTransition"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:346:1: ruleTransition returns [EObject current=null] : (otherlv_0= 'if' ( (lv_condition_1_0= ruleCondition ) ) otherlv_2= 'goto' ( (otherlv_3= RULE_ID ) ) ) ;
+    public final EObject ruleTransition() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_0=null;
+        Token otherlv_2=null;
+        Token otherlv_3=null;
+        EObject lv_condition_1_0 = null;
+
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:349:28: ( (otherlv_0= 'if' ( (lv_condition_1_0= ruleCondition ) ) otherlv_2= 'goto' ( (otherlv_3= RULE_ID ) ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:350:1: (otherlv_0= 'if' ( (lv_condition_1_0= ruleCondition ) ) otherlv_2= 'goto' ( (otherlv_3= RULE_ID ) ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:350:1: (otherlv_0= 'if' ( (lv_condition_1_0= ruleCondition ) ) otherlv_2= 'goto' ( (otherlv_3= RULE_ID ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:350:3: otherlv_0= 'if' ( (lv_condition_1_0= ruleCondition ) ) otherlv_2= 'goto' ( (otherlv_3= RULE_ID ) )
+            {
+            otherlv_0=(Token)match(input,17,FOLLOW_17_in_ruleTransition746); 
+
+                	newLeafNode(otherlv_0, grammarAccess.getTransitionAccess().getIfKeyword_0());
+                
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:354:1: ( (lv_condition_1_0= ruleCondition ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:355:1: (lv_condition_1_0= ruleCondition )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:355:1: (lv_condition_1_0= ruleCondition )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:356:3: lv_condition_1_0= ruleCondition
+            {
+             
+            	        newCompositeNode(grammarAccess.getTransitionAccess().getConditionConditionParserRuleCall_1_0()); 
+            	    
+            pushFollow(FOLLOW_ruleCondition_in_ruleTransition767);
+            lv_condition_1_0=ruleCondition();
+
+            state._fsp--;
+
+
+            	        if (current==null) {
+            	            current = createModelElementForParent(grammarAccess.getTransitionRule());
+            	        }
+                   		set(
+                   			current, 
+                   			"condition",
+                    		lv_condition_1_0, 
+                    		"Condition");
+            	        afterParserOrEnumRuleCall();
+            	    
+
+            }
+
+
+            }
+
+            otherlv_2=(Token)match(input,18,FOLLOW_18_in_ruleTransition779); 
+
+                	newLeafNode(otherlv_2, grammarAccess.getTransitionAccess().getGotoKeyword_2());
+                
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:376:1: ( (otherlv_3= RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:377:1: (otherlv_3= RULE_ID )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:377:1: (otherlv_3= RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:378:3: otherlv_3= RULE_ID
+            {
+
+            			if (current==null) {
+            	            current = createModelElement(grammarAccess.getTransitionRule());
+            	        }
+                    
+            otherlv_3=(Token)match(input,RULE_ID,FOLLOW_RULE_ID_in_ruleTransition799); 
+
+            		newLeafNode(otherlv_3, grammarAccess.getTransitionAccess().getStateStateCrossReference_3_0()); 
+            	
+
+            }
+
+
+            }
+
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleTransition"
+
+
+    // $ANTLR start "entryRuleCondition"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:397:1: entryRuleCondition returns [EObject current=null] : iv_ruleCondition= ruleCondition EOF ;
+    public final EObject entryRuleCondition() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleCondition = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:398:2: (iv_ruleCondition= ruleCondition EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:399:2: iv_ruleCondition= ruleCondition EOF
+            {
+             newCompositeNode(grammarAccess.getConditionRule()); 
+            pushFollow(FOLLOW_ruleCondition_in_entryRuleCondition835);
+            iv_ruleCondition=ruleCondition();
+
+            state._fsp--;
+
+             current =iv_ruleCondition; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleCondition845); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleCondition"
+
+
+    // $ANTLR start "ruleCondition"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:406:1: ruleCondition returns [EObject current=null] : ( ( (lv_events_0_0= ruleEvent ) ) (otherlv_1= 'and' ( (lv_events_2_0= ruleEvent ) ) )* ) ;
+    public final EObject ruleCondition() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_1=null;
+        EObject lv_events_0_0 = null;
+
+        EObject lv_events_2_0 = null;
+
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:409:28: ( ( ( (lv_events_0_0= ruleEvent ) ) (otherlv_1= 'and' ( (lv_events_2_0= ruleEvent ) ) )* ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:410:1: ( ( (lv_events_0_0= ruleEvent ) ) (otherlv_1= 'and' ( (lv_events_2_0= ruleEvent ) ) )* )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:410:1: ( ( (lv_events_0_0= ruleEvent ) ) (otherlv_1= 'and' ( (lv_events_2_0= ruleEvent ) ) )* )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:410:2: ( (lv_events_0_0= ruleEvent ) ) (otherlv_1= 'and' ( (lv_events_2_0= ruleEvent ) ) )*
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:410:2: ( (lv_events_0_0= ruleEvent ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:411:1: (lv_events_0_0= ruleEvent )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:411:1: (lv_events_0_0= ruleEvent )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:412:3: lv_events_0_0= ruleEvent
+            {
+             
+            	        newCompositeNode(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_0_0()); 
+            	    
+            pushFollow(FOLLOW_ruleEvent_in_ruleCondition891);
+            lv_events_0_0=ruleEvent();
+
+            state._fsp--;
+
+
+            	        if (current==null) {
+            	            current = createModelElementForParent(grammarAccess.getConditionRule());
+            	        }
+                   		add(
+                   			current, 
+                   			"events",
+                    		lv_events_0_0, 
+                    		"Event");
+            	        afterParserOrEnumRuleCall();
+            	    
+
+            }
+
+
+            }
+
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:428:2: (otherlv_1= 'and' ( (lv_events_2_0= ruleEvent ) ) )*
+            loop6:
+            do {
+                int alt6=2;
+                int LA6_0 = input.LA(1);
+
+                if ( (LA6_0==19) ) {
+                    alt6=1;
+                }
+
+
+                switch (alt6) {
+            	case 1 :
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:428:4: otherlv_1= 'and' ( (lv_events_2_0= ruleEvent ) )
+            	    {
+            	    otherlv_1=(Token)match(input,19,FOLLOW_19_in_ruleCondition904); 
+
+            	        	newLeafNode(otherlv_1, grammarAccess.getConditionAccess().getAndKeyword_1_0());
+            	        
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:432:1: ( (lv_events_2_0= ruleEvent ) )
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:433:1: (lv_events_2_0= ruleEvent )
+            	    {
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:433:1: (lv_events_2_0= ruleEvent )
+            	    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:434:3: lv_events_2_0= ruleEvent
+            	    {
+            	     
+            	    	        newCompositeNode(grammarAccess.getConditionAccess().getEventsEventParserRuleCall_1_1_0()); 
+            	    	    
+            	    pushFollow(FOLLOW_ruleEvent_in_ruleCondition925);
+            	    lv_events_2_0=ruleEvent();
+
+            	    state._fsp--;
+
+
+            	    	        if (current==null) {
+            	    	            current = createModelElementForParent(grammarAccess.getConditionRule());
+            	    	        }
+            	           		add(
+            	           			current, 
+            	           			"events",
+            	            		lv_events_2_0, 
+            	            		"Event");
+            	    	        afterParserOrEnumRuleCall();
+            	    	    
+
+            	    }
+
+
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop6;
+                }
+            } while (true);
+
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleCondition"
+
+
+    // $ANTLR start "entryRuleEvent"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:458:1: entryRuleEvent returns [EObject current=null] : iv_ruleEvent= ruleEvent EOF ;
+    public final EObject entryRuleEvent() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleEvent = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:459:2: (iv_ruleEvent= ruleEvent EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:460:2: iv_ruleEvent= ruleEvent EOF
+            {
+             newCompositeNode(grammarAccess.getEventRule()); 
+            pushFollow(FOLLOW_ruleEvent_in_entryRuleEvent963);
+            iv_ruleEvent=ruleEvent();
+
+            state._fsp--;
+
+             current =iv_ruleEvent; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleEvent973); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleEvent"
+
+
+    // $ANTLR start "ruleEvent"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:467:1: ruleEvent returns [EObject current=null] : ( ( (otherlv_0= RULE_ID ) ) otherlv_1= '==' ( (lv_value_2_0= RULE_BOOLEAN ) ) ) ;
+    public final EObject ruleEvent() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_0=null;
+        Token otherlv_1=null;
+        Token lv_value_2_0=null;
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:470:28: ( ( ( (otherlv_0= RULE_ID ) ) otherlv_1= '==' ( (lv_value_2_0= RULE_BOOLEAN ) ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:471:1: ( ( (otherlv_0= RULE_ID ) ) otherlv_1= '==' ( (lv_value_2_0= RULE_BOOLEAN ) ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:471:1: ( ( (otherlv_0= RULE_ID ) ) otherlv_1= '==' ( (lv_value_2_0= RULE_BOOLEAN ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:471:2: ( (otherlv_0= RULE_ID ) ) otherlv_1= '==' ( (lv_value_2_0= RULE_BOOLEAN ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:471:2: ( (otherlv_0= RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:472:1: (otherlv_0= RULE_ID )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:472:1: (otherlv_0= RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:473:3: otherlv_0= RULE_ID
+            {
+
+            			if (current==null) {
+            	            current = createModelElement(grammarAccess.getEventRule());
+            	        }
+                    
+            otherlv_0=(Token)match(input,RULE_ID,FOLLOW_RULE_ID_in_ruleEvent1018); 
+
+            		newLeafNode(otherlv_0, grammarAccess.getEventAccess().getSignalSignalCrossReference_0_0()); 
+            	
+
+            }
+
+
+            }
+
+            otherlv_1=(Token)match(input,20,FOLLOW_20_in_ruleEvent1030); 
+
+                	newLeafNode(otherlv_1, grammarAccess.getEventAccess().getEqualsSignEqualsSignKeyword_1());
+                
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:488:1: ( (lv_value_2_0= RULE_BOOLEAN ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:489:1: (lv_value_2_0= RULE_BOOLEAN )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:489:1: (lv_value_2_0= RULE_BOOLEAN )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:490:3: lv_value_2_0= RULE_BOOLEAN
+            {
+            lv_value_2_0=(Token)match(input,RULE_BOOLEAN,FOLLOW_RULE_BOOLEAN_in_ruleEvent1047); 
+
+            			newLeafNode(lv_value_2_0, grammarAccess.getEventAccess().getValueBOOLEANTerminalRuleCall_2_0()); 
+            		
+
+            	        if (current==null) {
+            	            current = createModelElement(grammarAccess.getEventRule());
+            	        }
+                   		setWithLastConsumed(
+                   			current, 
+                   			"value",
+                    		lv_value_2_0, 
+                    		"BOOLEAN");
+            	    
+
+            }
+
+
+            }
+
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleEvent"
+
+
+    // $ANTLR start "entryRuleCommand"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:514:1: entryRuleCommand returns [EObject current=null] : iv_ruleCommand= ruleCommand EOF ;
+    public final EObject entryRuleCommand() throws RecognitionException {
+        EObject current = null;
+
+        EObject iv_ruleCommand = null;
+
+
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:515:2: (iv_ruleCommand= ruleCommand EOF )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:516:2: iv_ruleCommand= ruleCommand EOF
+            {
+             newCompositeNode(grammarAccess.getCommandRule()); 
+            pushFollow(FOLLOW_ruleCommand_in_entryRuleCommand1088);
+            iv_ruleCommand=ruleCommand();
+
+            state._fsp--;
+
+             current =iv_ruleCommand; 
+            match(input,EOF,FOLLOW_EOF_in_entryRuleCommand1098); 
+
+            }
+
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "entryRuleCommand"
+
+
+    // $ANTLR start "ruleCommand"
+    // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:523:1: ruleCommand returns [EObject current=null] : (otherlv_0= 'set' ( (otherlv_1= RULE_ID ) ) otherlv_2= '=' ( (lv_newValue_3_0= RULE_BOOLEAN ) ) ) ;
+    public final EObject ruleCommand() throws RecognitionException {
+        EObject current = null;
+
+        Token otherlv_0=null;
+        Token otherlv_1=null;
+        Token otherlv_2=null;
+        Token lv_newValue_3_0=null;
+
+         enterRule(); 
+            
+        try {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:526:28: ( (otherlv_0= 'set' ( (otherlv_1= RULE_ID ) ) otherlv_2= '=' ( (lv_newValue_3_0= RULE_BOOLEAN ) ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:527:1: (otherlv_0= 'set' ( (otherlv_1= RULE_ID ) ) otherlv_2= '=' ( (lv_newValue_3_0= RULE_BOOLEAN ) ) )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:527:1: (otherlv_0= 'set' ( (otherlv_1= RULE_ID ) ) otherlv_2= '=' ( (lv_newValue_3_0= RULE_BOOLEAN ) ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:527:3: otherlv_0= 'set' ( (otherlv_1= RULE_ID ) ) otherlv_2= '=' ( (lv_newValue_3_0= RULE_BOOLEAN ) )
+            {
+            otherlv_0=(Token)match(input,21,FOLLOW_21_in_ruleCommand1135); 
+
+                	newLeafNode(otherlv_0, grammarAccess.getCommandAccess().getSetKeyword_0());
+                
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:531:1: ( (otherlv_1= RULE_ID ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:532:1: (otherlv_1= RULE_ID )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:532:1: (otherlv_1= RULE_ID )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:533:3: otherlv_1= RULE_ID
+            {
+
+            			if (current==null) {
+            	            current = createModelElement(grammarAccess.getCommandRule());
+            	        }
+                    
+            otherlv_1=(Token)match(input,RULE_ID,FOLLOW_RULE_ID_in_ruleCommand1155); 
+
+            		newLeafNode(otherlv_1, grammarAccess.getCommandAccess().getSignalSignalCrossReference_1_0()); 
+            	
+
+            }
+
+
+            }
+
+            otherlv_2=(Token)match(input,22,FOLLOW_22_in_ruleCommand1167); 
+
+                	newLeafNode(otherlv_2, grammarAccess.getCommandAccess().getEqualsSignKeyword_2());
+                
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:548:1: ( (lv_newValue_3_0= RULE_BOOLEAN ) )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:549:1: (lv_newValue_3_0= RULE_BOOLEAN )
+            {
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:549:1: (lv_newValue_3_0= RULE_BOOLEAN )
+            // ../org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g:550:3: lv_newValue_3_0= RULE_BOOLEAN
+            {
+            lv_newValue_3_0=(Token)match(input,RULE_BOOLEAN,FOLLOW_RULE_BOOLEAN_in_ruleCommand1184); 
+
+            			newLeafNode(lv_newValue_3_0, grammarAccess.getCommandAccess().getNewValueBOOLEANTerminalRuleCall_3_0()); 
+            		
+
+            	        if (current==null) {
+            	            current = createModelElement(grammarAccess.getCommandRule());
+            	        }
+                   		setWithLastConsumed(
+                   			current, 
+                   			"newValue",
+                    		lv_newValue_3_0, 
+                    		"BOOLEAN");
+            	    
+
+            }
+
+
+            }
+
+
+            }
+
+
+            }
+
+             leaveRule(); 
+        }
+         
+            catch (RecognitionException re) { 
+                recover(input,re); 
+                appendSkippedTokens();
+            } 
+        finally {
+        }
+        return current;
+    }
+    // $ANTLR end "ruleCommand"
+
+    // Delegated rules
+
+
+ 
+
+    public static final BitSet FOLLOW_ruleStatemachine_in_entryRuleStatemachine75 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleStatemachine85 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleSignal_in_ruleStatemachine140 = new BitSet(new long[]{0x000000000000E002L});
+    public static final BitSet FOLLOW_ruleState_in_ruleStatemachine162 = new BitSet(new long[]{0x0000000000008002L});
+    public static final BitSet FOLLOW_ruleSignal_in_entryRuleSignal199 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleSignal209 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleInputSignal_in_ruleSignal257 = new BitSet(new long[]{0x0000000000001000L});
+    public static final BitSet FOLLOW_ruleOutputSignal_in_ruleSignal284 = new BitSet(new long[]{0x0000000000001000L});
+    public static final BitSet FOLLOW_12_in_ruleSignal296 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_RULE_ID_in_ruleSignal313 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleInputSignal_in_entryRuleInputSignal354 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleInputSignal364 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_13_in_ruleInputSignal410 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleOutputSignal_in_entryRuleOutputSignal446 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleOutputSignal456 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_14_in_ruleOutputSignal502 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleState_in_entryRuleState538 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleState548 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_15_in_ruleState585 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_RULE_ID_in_ruleState602 = new BitSet(new long[]{0x0000000000230000L});
+    public static final BitSet FOLLOW_ruleCommand_in_ruleState628 = new BitSet(new long[]{0x0000000000230000L});
+    public static final BitSet FOLLOW_ruleTransition_in_ruleState650 = new BitSet(new long[]{0x0000000000030000L});
+    public static final BitSet FOLLOW_16_in_ruleState663 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleTransition_in_entryRuleTransition699 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleTransition709 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_17_in_ruleTransition746 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_ruleCondition_in_ruleTransition767 = new BitSet(new long[]{0x0000000000040000L});
+    public static final BitSet FOLLOW_18_in_ruleTransition779 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_RULE_ID_in_ruleTransition799 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleCondition_in_entryRuleCondition835 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleCondition845 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleEvent_in_ruleCondition891 = new BitSet(new long[]{0x0000000000080002L});
+    public static final BitSet FOLLOW_19_in_ruleCondition904 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_ruleEvent_in_ruleCondition925 = new BitSet(new long[]{0x0000000000080002L});
+    public static final BitSet FOLLOW_ruleEvent_in_entryRuleEvent963 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleEvent973 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_RULE_ID_in_ruleEvent1018 = new BitSet(new long[]{0x0000000000100000L});
+    public static final BitSet FOLLOW_20_in_ruleEvent1030 = new BitSet(new long[]{0x0000000000000020L});
+    public static final BitSet FOLLOW_RULE_BOOLEAN_in_ruleEvent1047 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_ruleCommand_in_entryRuleCommand1088 = new BitSet(new long[]{0x0000000000000000L});
+    public static final BitSet FOLLOW_EOF_in_entryRuleCommand1098 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_21_in_ruleCommand1135 = new BitSet(new long[]{0x0000000000000010L});
+    public static final BitSet FOLLOW_RULE_ID_in_ruleCommand1155 = new BitSet(new long[]{0x0000000000400000L});
+    public static final BitSet FOLLOW_22_in_ruleCommand1167 = new BitSet(new long[]{0x0000000000000020L});
+    public static final BitSet FOLLOW_RULE_BOOLEAN_in_ruleCommand1184 = new BitSet(new long[]{0x0000000000000002L});
+
+}
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSemanticSequencer.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSemanticSequencer.java
new file mode 100644
index 0000000..a7d2818
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSemanticSequencer.java
@@ -0,0 +1,213 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.serializer;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+import org.eclipse.fx.xtext.statemachine.statemachine.Command;
+import org.eclipse.fx.xtext.statemachine.statemachine.Condition;
+import org.eclipse.fx.xtext.statemachine.statemachine.Event;
+import org.eclipse.fx.xtext.statemachine.statemachine.InputSignal;
+import org.eclipse.fx.xtext.statemachine.statemachine.OutputSignal;
+import org.eclipse.fx.xtext.statemachine.statemachine.State;
+import org.eclipse.fx.xtext.statemachine.statemachine.Statemachine;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+import org.eclipse.fx.xtext.statemachine.statemachine.Transition;
+import org.eclipse.xtext.serializer.acceptor.ISemanticSequenceAcceptor;
+import org.eclipse.xtext.serializer.acceptor.SequenceFeeder;
+import org.eclipse.xtext.serializer.diagnostic.ISemanticSequencerDiagnosticProvider;
+import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
+import org.eclipse.xtext.serializer.sequencer.AbstractDelegatingSemanticSequencer;
+import org.eclipse.xtext.serializer.sequencer.GenericSequencer;
+import org.eclipse.xtext.serializer.sequencer.ISemanticNodeProvider.INodesForEObjectProvider;
+import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
+import org.eclipse.xtext.serializer.sequencer.ITransientValueService;
+import org.eclipse.xtext.serializer.sequencer.ITransientValueService.ValueTransient;
+
+@SuppressWarnings("all")
+public class StatemachineSemanticSequencer extends AbstractDelegatingSemanticSequencer {
+
+	@Inject
+	private StatemachineGrammarAccess grammarAccess;
+	
+	@Override
+	public void createSequence(EObject context, EObject semanticObject) {
+		if(semanticObject.eClass().getEPackage() == StatemachinePackage.eINSTANCE) switch(semanticObject.eClass().getClassifierID()) {
+			case StatemachinePackage.COMMAND:
+				sequence_Command(context, (Command) semanticObject); 
+				return; 
+			case StatemachinePackage.CONDITION:
+				sequence_Condition(context, (Condition) semanticObject); 
+				return; 
+			case StatemachinePackage.EVENT:
+				sequence_Event(context, (Event) semanticObject); 
+				return; 
+			case StatemachinePackage.INPUT_SIGNAL:
+				if(context == grammarAccess.getInputSignalRule()) {
+					sequence_InputSignal(context, (InputSignal) semanticObject); 
+					return; 
+				}
+				else if(context == grammarAccess.getSignalRule()) {
+					sequence_Signal(context, (InputSignal) semanticObject); 
+					return; 
+				}
+				else break;
+			case StatemachinePackage.OUTPUT_SIGNAL:
+				if(context == grammarAccess.getOutputSignalRule()) {
+					sequence_OutputSignal(context, (OutputSignal) semanticObject); 
+					return; 
+				}
+				else if(context == grammarAccess.getSignalRule()) {
+					sequence_Signal(context, (OutputSignal) semanticObject); 
+					return; 
+				}
+				else break;
+			case StatemachinePackage.STATE:
+				sequence_State(context, (State) semanticObject); 
+				return; 
+			case StatemachinePackage.STATEMACHINE:
+				sequence_Statemachine(context, (Statemachine) semanticObject); 
+				return; 
+			case StatemachinePackage.TRANSITION:
+				sequence_Transition(context, (Transition) semanticObject); 
+				return; 
+			}
+		if (errorAcceptor != null) errorAcceptor.accept(diagnosticProvider.createInvalidContextOrTypeDiagnostic(semanticObject, context));
+	}
+	
+	/**
+	 * Constraint:
+	 *     (signal=[Signal|ID] newValue=BOOLEAN)
+	 */
+	protected void sequence_Command(EObject context, Command semanticObject) {
+		if(errorAcceptor != null) {
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.COMMAND__SIGNAL) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.COMMAND__SIGNAL));
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.COMMAND__NEW_VALUE) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.COMMAND__NEW_VALUE));
+		}
+		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
+		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
+		feeder.accept(grammarAccess.getCommandAccess().getSignalSignalIDTerminalRuleCall_1_0_1(), semanticObject.getSignal());
+		feeder.accept(grammarAccess.getCommandAccess().getNewValueBOOLEANTerminalRuleCall_3_0(), semanticObject.isNewValue());
+		feeder.finish();
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     (events+=Event events+=Event*)
+	 */
+	protected void sequence_Condition(EObject context, Condition semanticObject) {
+		genericSequencer.createSequence(context, semanticObject);
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     (signal=[Signal|ID] value=BOOLEAN)
+	 */
+	protected void sequence_Event(EObject context, Event semanticObject) {
+		if(errorAcceptor != null) {
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.EVENT__SIGNAL) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.EVENT__SIGNAL));
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.EVENT__VALUE) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.EVENT__VALUE));
+		}
+		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
+		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
+		feeder.accept(grammarAccess.getEventAccess().getSignalSignalIDTerminalRuleCall_0_0_1(), semanticObject.getSignal());
+		feeder.accept(grammarAccess.getEventAccess().getValueBOOLEANTerminalRuleCall_2_0(), semanticObject.isValue());
+		feeder.finish();
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     {InputSignal}
+	 */
+	protected void sequence_InputSignal(EObject context, InputSignal semanticObject) {
+		genericSequencer.createSequence(context, semanticObject);
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     {OutputSignal}
+	 */
+	protected void sequence_OutputSignal(EObject context, OutputSignal semanticObject) {
+		genericSequencer.createSequence(context, semanticObject);
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     name=ID
+	 */
+	protected void sequence_Signal(EObject context, InputSignal semanticObject) {
+		if(errorAcceptor != null) {
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.SIGNAL__NAME) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.SIGNAL__NAME));
+		}
+		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
+		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
+		feeder.accept(grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0(), semanticObject.getName());
+		feeder.finish();
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     name=ID
+	 */
+	protected void sequence_Signal(EObject context, OutputSignal semanticObject) {
+		if(errorAcceptor != null) {
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.SIGNAL__NAME) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.SIGNAL__NAME));
+		}
+		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
+		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
+		feeder.accept(grammarAccess.getSignalAccess().getNameIDTerminalRuleCall_2_0(), semanticObject.getName());
+		feeder.finish();
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     (name=ID commands+=Command* transitions+=Transition*)
+	 */
+	protected void sequence_State(EObject context, State semanticObject) {
+		genericSequencer.createSequence(context, semanticObject);
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     (signals+=Signal* states+=State*)
+	 */
+	protected void sequence_Statemachine(EObject context, Statemachine semanticObject) {
+		genericSequencer.createSequence(context, semanticObject);
+	}
+	
+	
+	/**
+	 * Constraint:
+	 *     (condition=Condition state=[State|ID])
+	 */
+	protected void sequence_Transition(EObject context, Transition semanticObject) {
+		if(errorAcceptor != null) {
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.TRANSITION__CONDITION) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.TRANSITION__CONDITION));
+			if(transientValues.isValueTransient(semanticObject, StatemachinePackage.Literals.TRANSITION__STATE) == ValueTransient.YES)
+				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, StatemachinePackage.Literals.TRANSITION__STATE));
+		}
+		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
+		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
+		feeder.accept(grammarAccess.getTransitionAccess().getConditionConditionParserRuleCall_1_0(), semanticObject.getCondition());
+		feeder.accept(grammarAccess.getTransitionAccess().getStateStateIDTerminalRuleCall_3_0_1(), semanticObject.getState());
+		feeder.finish();
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSyntacticSequencer.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSyntacticSequencer.java
new file mode 100644
index 0000000..128f11b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSyntacticSequencer.java
@@ -0,0 +1,43 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.serializer;
+
+import com.google.inject.Inject;
+import java.util.List;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess;
+import org.eclipse.xtext.IGrammarAccess;
+import org.eclipse.xtext.RuleCall;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.serializer.analysis.GrammarAlias.AbstractElementAlias;
+import org.eclipse.xtext.serializer.analysis.ISyntacticSequencerPDAProvider.ISynTransition;
+import org.eclipse.xtext.serializer.sequencer.AbstractSyntacticSequencer;
+
+@SuppressWarnings("all")
+public class StatemachineSyntacticSequencer extends AbstractSyntacticSequencer {
+
+	protected StatemachineGrammarAccess grammarAccess;
+	
+	@Inject
+	protected void init(IGrammarAccess access) {
+		grammarAccess = (StatemachineGrammarAccess) access;
+	}
+	
+	@Override
+	protected String getUnassignedRuleCallToken(EObject semanticObject, RuleCall ruleCall, INode node) {
+		return "";
+	}
+	
+	
+	@Override
+	protected void emitUnassignedTokens(EObject semanticObject, ISynTransition transition, INode fromNode, INode toNode) {
+		if (transition.getAmbiguousSyntaxes().isEmpty()) return;
+		List<INode> transitionNodes = collectNodes(fromNode, toNode);
+		for (AbstractElementAlias syntax : transition.getAmbiguousSyntaxes()) {
+			List<INode> syntaxNodes = getNodesFor(transitionNodes, syntax);
+			acceptNodes(getLastNavigableState(), syntaxNodes);
+		}
+	}
+
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/services/StatemachineGrammarAccess.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/services/StatemachineGrammarAccess.java
new file mode 100644
index 0000000..7bc5d9f
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/services/StatemachineGrammarAccess.java
@@ -0,0 +1,523 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.services;
+
+import com.google.inject.Singleton;
+import com.google.inject.Inject;
+
+import java.util.List;
+
+import org.eclipse.xtext.*;
+import org.eclipse.xtext.service.GrammarProvider;
+import org.eclipse.xtext.service.AbstractElementFinder.*;
+
+import org.eclipse.xtext.common.services.TerminalsGrammarAccess;
+
+@Singleton
+public class StatemachineGrammarAccess extends AbstractGrammarElementFinder {
+	
+	
+	public class StatemachineElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "Statemachine");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Action cStatemachineAction_0 = (Action)cGroup.eContents().get(0);
+		private final Assignment cSignalsAssignment_1 = (Assignment)cGroup.eContents().get(1);
+		private final RuleCall cSignalsSignalParserRuleCall_1_0 = (RuleCall)cSignalsAssignment_1.eContents().get(0);
+		private final Assignment cStatesAssignment_2 = (Assignment)cGroup.eContents().get(2);
+		private final RuleCall cStatesStateParserRuleCall_2_0 = (RuleCall)cStatesAssignment_2.eContents().get(0);
+		
+		//Statemachine:
+		//	{Statemachine} signals+=Signal* states+=State*;
+		@Override public ParserRule getRule() { return rule; }
+
+		//{Statemachine} signals+=Signal* states+=State*
+		public Group getGroup() { return cGroup; }
+
+		//{Statemachine}
+		public Action getStatemachineAction_0() { return cStatemachineAction_0; }
+
+		//signals+=Signal*
+		public Assignment getSignalsAssignment_1() { return cSignalsAssignment_1; }
+
+		//Signal
+		public RuleCall getSignalsSignalParserRuleCall_1_0() { return cSignalsSignalParserRuleCall_1_0; }
+
+		//states+=State*
+		public Assignment getStatesAssignment_2() { return cStatesAssignment_2; }
+
+		//State
+		public RuleCall getStatesStateParserRuleCall_2_0() { return cStatesStateParserRuleCall_2_0; }
+	}
+
+	public class SignalElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "Signal");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Alternatives cAlternatives_0 = (Alternatives)cGroup.eContents().get(0);
+		private final RuleCall cInputSignalParserRuleCall_0_0 = (RuleCall)cAlternatives_0.eContents().get(0);
+		private final RuleCall cOutputSignalParserRuleCall_0_1 = (RuleCall)cAlternatives_0.eContents().get(1);
+		private final Keyword cSignalKeyword_1 = (Keyword)cGroup.eContents().get(1);
+		private final Assignment cNameAssignment_2 = (Assignment)cGroup.eContents().get(2);
+		private final RuleCall cNameIDTerminalRuleCall_2_0 = (RuleCall)cNameAssignment_2.eContents().get(0);
+		
+		//Signal:
+		//	(InputSignal | OutputSignal) "signal" name=ID;
+		@Override public ParserRule getRule() { return rule; }
+
+		//(InputSignal | OutputSignal) "signal" name=ID
+		public Group getGroup() { return cGroup; }
+
+		//InputSignal | OutputSignal
+		public Alternatives getAlternatives_0() { return cAlternatives_0; }
+
+		//InputSignal
+		public RuleCall getInputSignalParserRuleCall_0_0() { return cInputSignalParserRuleCall_0_0; }
+
+		//OutputSignal
+		public RuleCall getOutputSignalParserRuleCall_0_1() { return cOutputSignalParserRuleCall_0_1; }
+
+		//"signal"
+		public Keyword getSignalKeyword_1() { return cSignalKeyword_1; }
+
+		//name=ID
+		public Assignment getNameAssignment_2() { return cNameAssignment_2; }
+
+		//ID
+		public RuleCall getNameIDTerminalRuleCall_2_0() { return cNameIDTerminalRuleCall_2_0; }
+	}
+
+	public class InputSignalElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "InputSignal");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Action cInputSignalAction_0 = (Action)cGroup.eContents().get(0);
+		private final Keyword cInputKeyword_1 = (Keyword)cGroup.eContents().get(1);
+		
+		//InputSignal:
+		//	{InputSignal} "input";
+		@Override public ParserRule getRule() { return rule; }
+
+		//{InputSignal} "input"
+		public Group getGroup() { return cGroup; }
+
+		//{InputSignal}
+		public Action getInputSignalAction_0() { return cInputSignalAction_0; }
+
+		//"input"
+		public Keyword getInputKeyword_1() { return cInputKeyword_1; }
+	}
+
+	public class OutputSignalElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "OutputSignal");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Action cOutputSignalAction_0 = (Action)cGroup.eContents().get(0);
+		private final Keyword cOutputKeyword_1 = (Keyword)cGroup.eContents().get(1);
+		
+		//OutputSignal:
+		//	{OutputSignal} "output";
+		@Override public ParserRule getRule() { return rule; }
+
+		//{OutputSignal} "output"
+		public Group getGroup() { return cGroup; }
+
+		//{OutputSignal}
+		public Action getOutputSignalAction_0() { return cOutputSignalAction_0; }
+
+		//"output"
+		public Keyword getOutputKeyword_1() { return cOutputKeyword_1; }
+	}
+
+	public class StateElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "State");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Keyword cStateKeyword_0 = (Keyword)cGroup.eContents().get(0);
+		private final Assignment cNameAssignment_1 = (Assignment)cGroup.eContents().get(1);
+		private final RuleCall cNameIDTerminalRuleCall_1_0 = (RuleCall)cNameAssignment_1.eContents().get(0);
+		private final Assignment cCommandsAssignment_2 = (Assignment)cGroup.eContents().get(2);
+		private final RuleCall cCommandsCommandParserRuleCall_2_0 = (RuleCall)cCommandsAssignment_2.eContents().get(0);
+		private final Assignment cTransitionsAssignment_3 = (Assignment)cGroup.eContents().get(3);
+		private final RuleCall cTransitionsTransitionParserRuleCall_3_0 = (RuleCall)cTransitionsAssignment_3.eContents().get(0);
+		private final Keyword cEndKeyword_4 = (Keyword)cGroup.eContents().get(4);
+		
+		//State:
+		//	"state" name=ID commands+=Command* transitions+=Transition* "end";
+		@Override public ParserRule getRule() { return rule; }
+
+		//"state" name=ID commands+=Command* transitions+=Transition* "end"
+		public Group getGroup() { return cGroup; }
+
+		//"state"
+		public Keyword getStateKeyword_0() { return cStateKeyword_0; }
+
+		//name=ID
+		public Assignment getNameAssignment_1() { return cNameAssignment_1; }
+
+		//ID
+		public RuleCall getNameIDTerminalRuleCall_1_0() { return cNameIDTerminalRuleCall_1_0; }
+
+		//commands+=Command*
+		public Assignment getCommandsAssignment_2() { return cCommandsAssignment_2; }
+
+		//Command
+		public RuleCall getCommandsCommandParserRuleCall_2_0() { return cCommandsCommandParserRuleCall_2_0; }
+
+		//transitions+=Transition*
+		public Assignment getTransitionsAssignment_3() { return cTransitionsAssignment_3; }
+
+		//Transition
+		public RuleCall getTransitionsTransitionParserRuleCall_3_0() { return cTransitionsTransitionParserRuleCall_3_0; }
+
+		//"end"
+		public Keyword getEndKeyword_4() { return cEndKeyword_4; }
+	}
+
+	public class TransitionElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "Transition");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Keyword cIfKeyword_0 = (Keyword)cGroup.eContents().get(0);
+		private final Assignment cConditionAssignment_1 = (Assignment)cGroup.eContents().get(1);
+		private final RuleCall cConditionConditionParserRuleCall_1_0 = (RuleCall)cConditionAssignment_1.eContents().get(0);
+		private final Keyword cGotoKeyword_2 = (Keyword)cGroup.eContents().get(2);
+		private final Assignment cStateAssignment_3 = (Assignment)cGroup.eContents().get(3);
+		private final CrossReference cStateStateCrossReference_3_0 = (CrossReference)cStateAssignment_3.eContents().get(0);
+		private final RuleCall cStateStateIDTerminalRuleCall_3_0_1 = (RuleCall)cStateStateCrossReference_3_0.eContents().get(1);
+		
+		//Transition:
+		//	"if" condition=Condition "goto" state=[State];
+		@Override public ParserRule getRule() { return rule; }
+
+		//"if" condition=Condition "goto" state=[State]
+		public Group getGroup() { return cGroup; }
+
+		//"if"
+		public Keyword getIfKeyword_0() { return cIfKeyword_0; }
+
+		//condition=Condition
+		public Assignment getConditionAssignment_1() { return cConditionAssignment_1; }
+
+		//Condition
+		public RuleCall getConditionConditionParserRuleCall_1_0() { return cConditionConditionParserRuleCall_1_0; }
+
+		//"goto"
+		public Keyword getGotoKeyword_2() { return cGotoKeyword_2; }
+
+		//state=[State]
+		public Assignment getStateAssignment_3() { return cStateAssignment_3; }
+
+		//[State]
+		public CrossReference getStateStateCrossReference_3_0() { return cStateStateCrossReference_3_0; }
+
+		//ID
+		public RuleCall getStateStateIDTerminalRuleCall_3_0_1() { return cStateStateIDTerminalRuleCall_3_0_1; }
+	}
+
+	public class ConditionElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "Condition");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Assignment cEventsAssignment_0 = (Assignment)cGroup.eContents().get(0);
+		private final RuleCall cEventsEventParserRuleCall_0_0 = (RuleCall)cEventsAssignment_0.eContents().get(0);
+		private final Group cGroup_1 = (Group)cGroup.eContents().get(1);
+		private final Keyword cAndKeyword_1_0 = (Keyword)cGroup_1.eContents().get(0);
+		private final Assignment cEventsAssignment_1_1 = (Assignment)cGroup_1.eContents().get(1);
+		private final RuleCall cEventsEventParserRuleCall_1_1_0 = (RuleCall)cEventsAssignment_1_1.eContents().get(0);
+		
+		//Condition:
+		//	events+=Event ("and" events+=Event)*;
+		@Override public ParserRule getRule() { return rule; }
+
+		//events+=Event ("and" events+=Event)*
+		public Group getGroup() { return cGroup; }
+
+		//events+=Event
+		public Assignment getEventsAssignment_0() { return cEventsAssignment_0; }
+
+		//Event
+		public RuleCall getEventsEventParserRuleCall_0_0() { return cEventsEventParserRuleCall_0_0; }
+
+		//("and" events+=Event)*
+		public Group getGroup_1() { return cGroup_1; }
+
+		//"and"
+		public Keyword getAndKeyword_1_0() { return cAndKeyword_1_0; }
+
+		//events+=Event
+		public Assignment getEventsAssignment_1_1() { return cEventsAssignment_1_1; }
+
+		//Event
+		public RuleCall getEventsEventParserRuleCall_1_1_0() { return cEventsEventParserRuleCall_1_1_0; }
+	}
+
+	public class EventElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "Event");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Assignment cSignalAssignment_0 = (Assignment)cGroup.eContents().get(0);
+		private final CrossReference cSignalSignalCrossReference_0_0 = (CrossReference)cSignalAssignment_0.eContents().get(0);
+		private final RuleCall cSignalSignalIDTerminalRuleCall_0_0_1 = (RuleCall)cSignalSignalCrossReference_0_0.eContents().get(1);
+		private final Keyword cEqualsSignEqualsSignKeyword_1 = (Keyword)cGroup.eContents().get(1);
+		private final Assignment cValueAssignment_2 = (Assignment)cGroup.eContents().get(2);
+		private final RuleCall cValueBOOLEANTerminalRuleCall_2_0 = (RuleCall)cValueAssignment_2.eContents().get(0);
+		
+		//Event:
+		//	signal=[Signal] "==" value=BOOLEAN;
+		@Override public ParserRule getRule() { return rule; }
+
+		//signal=[Signal] "==" value=BOOLEAN
+		public Group getGroup() { return cGroup; }
+
+		//signal=[Signal]
+		public Assignment getSignalAssignment_0() { return cSignalAssignment_0; }
+
+		//[Signal]
+		public CrossReference getSignalSignalCrossReference_0_0() { return cSignalSignalCrossReference_0_0; }
+
+		//ID
+		public RuleCall getSignalSignalIDTerminalRuleCall_0_0_1() { return cSignalSignalIDTerminalRuleCall_0_0_1; }
+
+		//"=="
+		public Keyword getEqualsSignEqualsSignKeyword_1() { return cEqualsSignEqualsSignKeyword_1; }
+
+		//value=BOOLEAN
+		public Assignment getValueAssignment_2() { return cValueAssignment_2; }
+
+		//BOOLEAN
+		public RuleCall getValueBOOLEANTerminalRuleCall_2_0() { return cValueBOOLEANTerminalRuleCall_2_0; }
+	}
+
+	public class CommandElements extends AbstractParserRuleElementFinder {
+		private final ParserRule rule = (ParserRule) GrammarUtil.findRuleForName(getGrammar(), "Command");
+		private final Group cGroup = (Group)rule.eContents().get(1);
+		private final Keyword cSetKeyword_0 = (Keyword)cGroup.eContents().get(0);
+		private final Assignment cSignalAssignment_1 = (Assignment)cGroup.eContents().get(1);
+		private final CrossReference cSignalSignalCrossReference_1_0 = (CrossReference)cSignalAssignment_1.eContents().get(0);
+		private final RuleCall cSignalSignalIDTerminalRuleCall_1_0_1 = (RuleCall)cSignalSignalCrossReference_1_0.eContents().get(1);
+		private final Keyword cEqualsSignKeyword_2 = (Keyword)cGroup.eContents().get(2);
+		private final Assignment cNewValueAssignment_3 = (Assignment)cGroup.eContents().get(3);
+		private final RuleCall cNewValueBOOLEANTerminalRuleCall_3_0 = (RuleCall)cNewValueAssignment_3.eContents().get(0);
+		
+		//Command:
+		//	"set" signal=[Signal] "=" newValue=BOOLEAN;
+		@Override public ParserRule getRule() { return rule; }
+
+		//"set" signal=[Signal] "=" newValue=BOOLEAN
+		public Group getGroup() { return cGroup; }
+
+		//"set"
+		public Keyword getSetKeyword_0() { return cSetKeyword_0; }
+
+		//signal=[Signal]
+		public Assignment getSignalAssignment_1() { return cSignalAssignment_1; }
+
+		//[Signal]
+		public CrossReference getSignalSignalCrossReference_1_0() { return cSignalSignalCrossReference_1_0; }
+
+		//ID
+		public RuleCall getSignalSignalIDTerminalRuleCall_1_0_1() { return cSignalSignalIDTerminalRuleCall_1_0_1; }
+
+		//"="
+		public Keyword getEqualsSignKeyword_2() { return cEqualsSignKeyword_2; }
+
+		//newValue=BOOLEAN
+		public Assignment getNewValueAssignment_3() { return cNewValueAssignment_3; }
+
+		//BOOLEAN
+		public RuleCall getNewValueBOOLEANTerminalRuleCall_3_0() { return cNewValueBOOLEANTerminalRuleCall_3_0; }
+	}
+	
+	
+	private final StatemachineElements pStatemachine;
+	private final SignalElements pSignal;
+	private final InputSignalElements pInputSignal;
+	private final OutputSignalElements pOutputSignal;
+	private final StateElements pState;
+	private final TransitionElements pTransition;
+	private final ConditionElements pCondition;
+	private final EventElements pEvent;
+	private final CommandElements pCommand;
+	private final TerminalRule tBOOLEAN;
+	
+	private final Grammar grammar;
+
+	private final TerminalsGrammarAccess gaTerminals;
+
+	@Inject
+	public StatemachineGrammarAccess(GrammarProvider grammarProvider,
+		TerminalsGrammarAccess gaTerminals) {
+		this.grammar = internalFindGrammar(grammarProvider);
+		this.gaTerminals = gaTerminals;
+		this.pStatemachine = new StatemachineElements();
+		this.pSignal = new SignalElements();
+		this.pInputSignal = new InputSignalElements();
+		this.pOutputSignal = new OutputSignalElements();
+		this.pState = new StateElements();
+		this.pTransition = new TransitionElements();
+		this.pCondition = new ConditionElements();
+		this.pEvent = new EventElements();
+		this.pCommand = new CommandElements();
+		this.tBOOLEAN = (TerminalRule) GrammarUtil.findRuleForName(getGrammar(), "BOOLEAN");
+	}
+	
+	protected Grammar internalFindGrammar(GrammarProvider grammarProvider) {
+		Grammar grammar = grammarProvider.getGrammar(this);
+		while (grammar != null) {
+			if ("org.eclipse.fx.xtext.statemachine.Statemachine".equals(grammar.getName())) {
+				return grammar;
+			}
+			List<Grammar> grammars = grammar.getUsedGrammars();
+			if (!grammars.isEmpty()) {
+				grammar = grammars.iterator().next();
+			} else {
+				return null;
+			}
+		}
+		return grammar;
+	}
+	
+	@Override
+	public Grammar getGrammar() {
+		return grammar;
+	}
+	
+
+	public TerminalsGrammarAccess getTerminalsGrammarAccess() {
+		return gaTerminals;
+	}
+
+	
+	//Statemachine:
+	//	{Statemachine} signals+=Signal* states+=State*;
+	public StatemachineElements getStatemachineAccess() {
+		return pStatemachine;
+	}
+	
+	public ParserRule getStatemachineRule() {
+		return getStatemachineAccess().getRule();
+	}
+
+	//Signal:
+	//	(InputSignal | OutputSignal) "signal" name=ID;
+	public SignalElements getSignalAccess() {
+		return pSignal;
+	}
+	
+	public ParserRule getSignalRule() {
+		return getSignalAccess().getRule();
+	}
+
+	//InputSignal:
+	//	{InputSignal} "input";
+	public InputSignalElements getInputSignalAccess() {
+		return pInputSignal;
+	}
+	
+	public ParserRule getInputSignalRule() {
+		return getInputSignalAccess().getRule();
+	}
+
+	//OutputSignal:
+	//	{OutputSignal} "output";
+	public OutputSignalElements getOutputSignalAccess() {
+		return pOutputSignal;
+	}
+	
+	public ParserRule getOutputSignalRule() {
+		return getOutputSignalAccess().getRule();
+	}
+
+	//State:
+	//	"state" name=ID commands+=Command* transitions+=Transition* "end";
+	public StateElements getStateAccess() {
+		return pState;
+	}
+	
+	public ParserRule getStateRule() {
+		return getStateAccess().getRule();
+	}
+
+	//Transition:
+	//	"if" condition=Condition "goto" state=[State];
+	public TransitionElements getTransitionAccess() {
+		return pTransition;
+	}
+	
+	public ParserRule getTransitionRule() {
+		return getTransitionAccess().getRule();
+	}
+
+	//Condition:
+	//	events+=Event ("and" events+=Event)*;
+	public ConditionElements getConditionAccess() {
+		return pCondition;
+	}
+	
+	public ParserRule getConditionRule() {
+		return getConditionAccess().getRule();
+	}
+
+	//Event:
+	//	signal=[Signal] "==" value=BOOLEAN;
+	public EventElements getEventAccess() {
+		return pEvent;
+	}
+	
+	public ParserRule getEventRule() {
+		return getEventAccess().getRule();
+	}
+
+	//Command:
+	//	"set" signal=[Signal] "=" newValue=BOOLEAN;
+	public CommandElements getCommandAccess() {
+		return pCommand;
+	}
+	
+	public ParserRule getCommandRule() {
+		return getCommandAccess().getRule();
+	}
+
+	//terminal BOOLEAN returns ecore::EBoolean:
+	//	"true" | "false";
+	public TerminalRule getBOOLEANRule() {
+		return tBOOLEAN;
+	} 
+
+	//terminal ID:
+	//	"^"? ("a".."z" | "A".."Z" | "_") ("a".."z" | "A".."Z" | "_" | "0".."9")*;
+	public TerminalRule getIDRule() {
+		return gaTerminals.getIDRule();
+	} 
+
+	//terminal INT returns ecore::EInt:
+	//	"0".."9"+;
+	public TerminalRule getINTRule() {
+		return gaTerminals.getINTRule();
+	} 
+
+	//terminal STRING:
+	//	"\"" ("\\" . / * 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' * / | !("\\" | "\""))* "\"" | "\'" ("\\" .
+	//	/ * 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' * / | !("\\" | "\'"))* "\'";
+	public TerminalRule getSTRINGRule() {
+		return gaTerminals.getSTRINGRule();
+	} 
+
+	//terminal ML_COMMENT:
+	//	"/ *"->"* /";
+	public TerminalRule getML_COMMENTRule() {
+		return gaTerminals.getML_COMMENTRule();
+	} 
+
+	//terminal SL_COMMENT:
+	//	"//" !("\n" | "\r")* ("\r"? "\n")?;
+	public TerminalRule getSL_COMMENTRule() {
+		return gaTerminals.getSL_COMMENTRule();
+	} 
+
+	//terminal WS:
+	//	(" " | "\t" | "\r" | "\n")+;
+	public TerminalRule getWSRule() {
+		return gaTerminals.getWSRule();
+	} 
+
+	//terminal ANY_OTHER:
+	//	.;
+	public TerminalRule getANY_OTHERRule() {
+		return gaTerminals.getANY_OTHERRule();
+	} 
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Command.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Command.java
new file mode 100644
index 0000000..c26d3b1
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Command.java
@@ -0,0 +1,78 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Command</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Command#getSignal <em>Signal</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Command#isNewValue <em>New Value</em>}</li>
+ * </ul>
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getCommand()
+ * @model
+ * @generated
+ */
+public interface Command extends EObject
+{
+  /**
+   * Returns the value of the '<em><b>Signal</b></em>' reference.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Signal</em>' reference isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Signal</em>' reference.
+   * @see #setSignal(Signal)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getCommand_Signal()
+   * @model
+   * @generated
+   */
+  Signal getSignal();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.Command#getSignal <em>Signal</em>}' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>Signal</em>' reference.
+   * @see #getSignal()
+   * @generated
+   */
+  void setSignal(Signal value);
+
+  /**
+   * Returns the value of the '<em><b>New Value</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>New Value</em>' attribute isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>New Value</em>' attribute.
+   * @see #setNewValue(boolean)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getCommand_NewValue()
+   * @model
+   * @generated
+   */
+  boolean isNewValue();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.Command#isNewValue <em>New Value</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>New Value</em>' attribute.
+   * @see #isNewValue()
+   * @generated
+   */
+  void setNewValue(boolean value);
+
+} // Command
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Condition.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Condition.java
new file mode 100644
index 0000000..e04b67b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Condition.java
@@ -0,0 +1,43 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.common.util.EList;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Condition</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Condition#getEvents <em>Events</em>}</li>
+ * </ul>
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getCondition()
+ * @model
+ * @generated
+ */
+public interface Condition extends EObject
+{
+  /**
+   * Returns the value of the '<em><b>Events</b></em>' containment reference list.
+   * The list contents are of type {@link org.eclipse.fx.xtext.statemachine.statemachine.Event}.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Events</em>' containment reference list isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Events</em>' containment reference list.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getCondition_Events()
+   * @model containment="true"
+   * @generated
+   */
+  EList<Event> getEvents();
+
+} // Condition
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Event.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Event.java
new file mode 100644
index 0000000..12cc312
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Event.java
@@ -0,0 +1,78 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Event</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Event#getSignal <em>Signal</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Event#isValue <em>Value</em>}</li>
+ * </ul>
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getEvent()
+ * @model
+ * @generated
+ */
+public interface Event extends EObject
+{
+  /**
+   * Returns the value of the '<em><b>Signal</b></em>' reference.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Signal</em>' reference isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Signal</em>' reference.
+   * @see #setSignal(Signal)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getEvent_Signal()
+   * @model
+   * @generated
+   */
+  Signal getSignal();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.Event#getSignal <em>Signal</em>}' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>Signal</em>' reference.
+   * @see #getSignal()
+   * @generated
+   */
+  void setSignal(Signal value);
+
+  /**
+   * Returns the value of the '<em><b>Value</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Value</em>' attribute isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Value</em>' attribute.
+   * @see #setValue(boolean)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getEvent_Value()
+   * @model
+   * @generated
+   */
+  boolean isValue();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.Event#isValue <em>Value</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>Value</em>' attribute.
+   * @see #isValue()
+   * @generated
+   */
+  void setValue(boolean value);
+
+} // Event
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/InputSignal.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/InputSignal.java
new file mode 100644
index 0000000..b72537b
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/InputSignal.java
@@ -0,0 +1,18 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Input Signal</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getInputSignal()
+ * @model
+ * @generated
+ */
+public interface InputSignal extends Signal
+{
+} // InputSignal
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/OutputSignal.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/OutputSignal.java
new file mode 100644
index 0000000..5ca8828
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/OutputSignal.java
@@ -0,0 +1,18 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Output Signal</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getOutputSignal()
+ * @model
+ * @generated
+ */
+public interface OutputSignal extends Signal
+{
+} // OutputSignal
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Signal.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Signal.java
new file mode 100644
index 0000000..05ffcfb
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Signal.java
@@ -0,0 +1,51 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Signal</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Signal#getName <em>Name</em>}</li>
+ * </ul>
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getSignal()
+ * @model
+ * @generated
+ */
+public interface Signal extends EObject
+{
+  /**
+   * Returns the value of the '<em><b>Name</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Name</em>' attribute isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Name</em>' attribute.
+   * @see #setName(String)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getSignal_Name()
+   * @model
+   * @generated
+   */
+  String getName();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.Signal#getName <em>Name</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>Name</em>' attribute.
+   * @see #getName()
+   * @generated
+   */
+  void setName(String value);
+
+} // Signal
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/State.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/State.java
new file mode 100644
index 0000000..e7d1c4f
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/State.java
@@ -0,0 +1,87 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.common.util.EList;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>State</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.State#getName <em>Name</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.State#getCommands <em>Commands</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.State#getTransitions <em>Transitions</em>}</li>
+ * </ul>
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getState()
+ * @model
+ * @generated
+ */
+public interface State extends EObject
+{
+  /**
+   * Returns the value of the '<em><b>Name</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Name</em>' attribute isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Name</em>' attribute.
+   * @see #setName(String)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getState_Name()
+   * @model
+   * @generated
+   */
+  String getName();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.State#getName <em>Name</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>Name</em>' attribute.
+   * @see #getName()
+   * @generated
+   */
+  void setName(String value);
+
+  /**
+   * Returns the value of the '<em><b>Commands</b></em>' containment reference list.
+   * The list contents are of type {@link org.eclipse.fx.xtext.statemachine.statemachine.Command}.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Commands</em>' containment reference list isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Commands</em>' containment reference list.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getState_Commands()
+   * @model containment="true"
+   * @generated
+   */
+  EList<Command> getCommands();
+
+  /**
+   * Returns the value of the '<em><b>Transitions</b></em>' containment reference list.
+   * The list contents are of type {@link org.eclipse.fx.xtext.statemachine.statemachine.Transition}.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Transitions</em>' containment reference list isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Transitions</em>' containment reference list.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getState_Transitions()
+   * @model containment="true"
+   * @generated
+   */
+  EList<Transition> getTransitions();
+
+} // State
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Statemachine.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Statemachine.java
new file mode 100644
index 0000000..47777b8
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Statemachine.java
@@ -0,0 +1,60 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.common.util.EList;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Statemachine</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Statemachine#getSignals <em>Signals</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Statemachine#getStates <em>States</em>}</li>
+ * </ul>
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getStatemachine()
+ * @model
+ * @generated
+ */
+public interface Statemachine extends EObject
+{
+  /**
+   * Returns the value of the '<em><b>Signals</b></em>' containment reference list.
+   * The list contents are of type {@link org.eclipse.fx.xtext.statemachine.statemachine.Signal}.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Signals</em>' containment reference list isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Signals</em>' containment reference list.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getStatemachine_Signals()
+   * @model containment="true"
+   * @generated
+   */
+  EList<Signal> getSignals();
+
+  /**
+   * Returns the value of the '<em><b>States</b></em>' containment reference list.
+   * The list contents are of type {@link org.eclipse.fx.xtext.statemachine.statemachine.State}.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>States</em>' containment reference list isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>States</em>' containment reference list.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getStatemachine_States()
+   * @model containment="true"
+   * @generated
+   */
+  EList<State> getStates();
+
+} // Statemachine
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachineFactory.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachineFactory.java
new file mode 100644
index 0000000..3045970
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachineFactory.java
@@ -0,0 +1,115 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.ecore.EFactory;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Factory</b> for the model.
+ * It provides a create method for each non-abstract class of the model.
+ * <!-- end-user-doc -->
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage
+ * @generated
+ */
+public interface StatemachineFactory extends EFactory
+{
+  /**
+   * The singleton instance of the factory.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  StatemachineFactory eINSTANCE = org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachineFactoryImpl.init();
+
+  /**
+   * Returns a new object of class '<em>Statemachine</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Statemachine</em>'.
+   * @generated
+   */
+  Statemachine createStatemachine();
+
+  /**
+   * Returns a new object of class '<em>Signal</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Signal</em>'.
+   * @generated
+   */
+  Signal createSignal();
+
+  /**
+   * Returns a new object of class '<em>Input Signal</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Input Signal</em>'.
+   * @generated
+   */
+  InputSignal createInputSignal();
+
+  /**
+   * Returns a new object of class '<em>Output Signal</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Output Signal</em>'.
+   * @generated
+   */
+  OutputSignal createOutputSignal();
+
+  /**
+   * Returns a new object of class '<em>State</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>State</em>'.
+   * @generated
+   */
+  State createState();
+
+  /**
+   * Returns a new object of class '<em>Transition</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Transition</em>'.
+   * @generated
+   */
+  Transition createTransition();
+
+  /**
+   * Returns a new object of class '<em>Condition</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Condition</em>'.
+   * @generated
+   */
+  Condition createCondition();
+
+  /**
+   * Returns a new object of class '<em>Event</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Event</em>'.
+   * @generated
+   */
+  Event createEvent();
+
+  /**
+   * Returns a new object of class '<em>Command</em>'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return a new object of class '<em>Command</em>'.
+   * @generated
+   */
+  Command createCommand();
+
+  /**
+   * Returns the package supported by this factory.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the package supported by this factory.
+   * @generated
+   */
+  StatemachinePackage getStatemachinePackage();
+
+} //StatemachineFactory
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachinePackage.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachinePackage.java
new file mode 100644
index 0000000..f50ca3c
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachinePackage.java
@@ -0,0 +1,818 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Package</b> for the model.
+ * It contains accessors for the meta objects to represent
+ * <ul>
+ *   <li>each class,</li>
+ *   <li>each feature of each class,</li>
+ *   <li>each enum,</li>
+ *   <li>and each data type</li>
+ * </ul>
+ * <!-- end-user-doc -->
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachineFactory
+ * @model kind="package"
+ * @generated
+ */
+public interface StatemachinePackage extends EPackage
+{
+  /**
+   * The package name.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  String eNAME = "statemachine";
+
+  /**
+   * The package namespace URI.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  String eNS_URI = "http://www.eclipse.org/fx/xtext/statemachine/Statemachine";
+
+  /**
+   * The package namespace name.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  String eNS_PREFIX = "statemachine";
+
+  /**
+   * The singleton instance of the package.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  StatemachinePackage eINSTANCE = org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl.init();
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachineImpl <em>Statemachine</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachineImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getStatemachine()
+   * @generated
+   */
+  int STATEMACHINE = 0;
+
+  /**
+   * The feature id for the '<em><b>Signals</b></em>' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int STATEMACHINE__SIGNALS = 0;
+
+  /**
+   * The feature id for the '<em><b>States</b></em>' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int STATEMACHINE__STATES = 1;
+
+  /**
+   * The number of structural features of the '<em>Statemachine</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int STATEMACHINE_FEATURE_COUNT = 2;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.SignalImpl <em>Signal</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.SignalImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getSignal()
+   * @generated
+   */
+  int SIGNAL = 1;
+
+  /**
+   * The feature id for the '<em><b>Name</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int SIGNAL__NAME = 0;
+
+  /**
+   * The number of structural features of the '<em>Signal</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int SIGNAL_FEATURE_COUNT = 1;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.InputSignalImpl <em>Input Signal</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.InputSignalImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getInputSignal()
+   * @generated
+   */
+  int INPUT_SIGNAL = 2;
+
+  /**
+   * The feature id for the '<em><b>Name</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int INPUT_SIGNAL__NAME = SIGNAL__NAME;
+
+  /**
+   * The number of structural features of the '<em>Input Signal</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int INPUT_SIGNAL_FEATURE_COUNT = SIGNAL_FEATURE_COUNT + 0;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.OutputSignalImpl <em>Output Signal</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.OutputSignalImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getOutputSignal()
+   * @generated
+   */
+  int OUTPUT_SIGNAL = 3;
+
+  /**
+   * The feature id for the '<em><b>Name</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int OUTPUT_SIGNAL__NAME = SIGNAL__NAME;
+
+  /**
+   * The number of structural features of the '<em>Output Signal</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int OUTPUT_SIGNAL_FEATURE_COUNT = SIGNAL_FEATURE_COUNT + 0;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StateImpl <em>State</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StateImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getState()
+   * @generated
+   */
+  int STATE = 4;
+
+  /**
+   * The feature id for the '<em><b>Name</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int STATE__NAME = 0;
+
+  /**
+   * The feature id for the '<em><b>Commands</b></em>' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int STATE__COMMANDS = 1;
+
+  /**
+   * The feature id for the '<em><b>Transitions</b></em>' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int STATE__TRANSITIONS = 2;
+
+  /**
+   * The number of structural features of the '<em>State</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int STATE_FEATURE_COUNT = 3;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.TransitionImpl <em>Transition</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.TransitionImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getTransition()
+   * @generated
+   */
+  int TRANSITION = 5;
+
+  /**
+   * The feature id for the '<em><b>Condition</b></em>' containment reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int TRANSITION__CONDITION = 0;
+
+  /**
+   * The feature id for the '<em><b>State</b></em>' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int TRANSITION__STATE = 1;
+
+  /**
+   * The number of structural features of the '<em>Transition</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int TRANSITION_FEATURE_COUNT = 2;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.ConditionImpl <em>Condition</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.ConditionImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getCondition()
+   * @generated
+   */
+  int CONDITION = 6;
+
+  /**
+   * The feature id for the '<em><b>Events</b></em>' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int CONDITION__EVENTS = 0;
+
+  /**
+   * The number of structural features of the '<em>Condition</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int CONDITION_FEATURE_COUNT = 1;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.EventImpl <em>Event</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.EventImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getEvent()
+   * @generated
+   */
+  int EVENT = 7;
+
+  /**
+   * The feature id for the '<em><b>Signal</b></em>' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int EVENT__SIGNAL = 0;
+
+  /**
+   * The feature id for the '<em><b>Value</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int EVENT__VALUE = 1;
+
+  /**
+   * The number of structural features of the '<em>Event</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int EVENT_FEATURE_COUNT = 2;
+
+  /**
+   * The meta object id for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.CommandImpl <em>Command</em>}' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.CommandImpl
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getCommand()
+   * @generated
+   */
+  int COMMAND = 8;
+
+  /**
+   * The feature id for the '<em><b>Signal</b></em>' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int COMMAND__SIGNAL = 0;
+
+  /**
+   * The feature id for the '<em><b>New Value</b></em>' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int COMMAND__NEW_VALUE = 1;
+
+  /**
+   * The number of structural features of the '<em>Command</em>' class.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   * @ordered
+   */
+  int COMMAND_FEATURE_COUNT = 2;
+
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Statemachine <em>Statemachine</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Statemachine</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Statemachine
+   * @generated
+   */
+  EClass getStatemachine();
+
+  /**
+   * Returns the meta object for the containment reference list '{@link org.eclipse.fx.xtext.statemachine.statemachine.Statemachine#getSignals <em>Signals</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the containment reference list '<em>Signals</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Statemachine#getSignals()
+   * @see #getStatemachine()
+   * @generated
+   */
+  EReference getStatemachine_Signals();
+
+  /**
+   * Returns the meta object for the containment reference list '{@link org.eclipse.fx.xtext.statemachine.statemachine.Statemachine#getStates <em>States</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the containment reference list '<em>States</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Statemachine#getStates()
+   * @see #getStatemachine()
+   * @generated
+   */
+  EReference getStatemachine_States();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Signal <em>Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Signal</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Signal
+   * @generated
+   */
+  EClass getSignal();
+
+  /**
+   * Returns the meta object for the attribute '{@link org.eclipse.fx.xtext.statemachine.statemachine.Signal#getName <em>Name</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the attribute '<em>Name</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Signal#getName()
+   * @see #getSignal()
+   * @generated
+   */
+  EAttribute getSignal_Name();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.InputSignal <em>Input Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Input Signal</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.InputSignal
+   * @generated
+   */
+  EClass getInputSignal();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.OutputSignal <em>Output Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Output Signal</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.OutputSignal
+   * @generated
+   */
+  EClass getOutputSignal();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.State <em>State</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>State</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.State
+   * @generated
+   */
+  EClass getState();
+
+  /**
+   * Returns the meta object for the attribute '{@link org.eclipse.fx.xtext.statemachine.statemachine.State#getName <em>Name</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the attribute '<em>Name</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.State#getName()
+   * @see #getState()
+   * @generated
+   */
+  EAttribute getState_Name();
+
+  /**
+   * Returns the meta object for the containment reference list '{@link org.eclipse.fx.xtext.statemachine.statemachine.State#getCommands <em>Commands</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the containment reference list '<em>Commands</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.State#getCommands()
+   * @see #getState()
+   * @generated
+   */
+  EReference getState_Commands();
+
+  /**
+   * Returns the meta object for the containment reference list '{@link org.eclipse.fx.xtext.statemachine.statemachine.State#getTransitions <em>Transitions</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the containment reference list '<em>Transitions</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.State#getTransitions()
+   * @see #getState()
+   * @generated
+   */
+  EReference getState_Transitions();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition <em>Transition</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Transition</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Transition
+   * @generated
+   */
+  EClass getTransition();
+
+  /**
+   * Returns the meta object for the containment reference '{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition#getCondition <em>Condition</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the containment reference '<em>Condition</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Transition#getCondition()
+   * @see #getTransition()
+   * @generated
+   */
+  EReference getTransition_Condition();
+
+  /**
+   * Returns the meta object for the reference '{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition#getState <em>State</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the reference '<em>State</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Transition#getState()
+   * @see #getTransition()
+   * @generated
+   */
+  EReference getTransition_State();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Condition <em>Condition</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Condition</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Condition
+   * @generated
+   */
+  EClass getCondition();
+
+  /**
+   * Returns the meta object for the containment reference list '{@link org.eclipse.fx.xtext.statemachine.statemachine.Condition#getEvents <em>Events</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the containment reference list '<em>Events</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Condition#getEvents()
+   * @see #getCondition()
+   * @generated
+   */
+  EReference getCondition_Events();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Event <em>Event</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Event</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Event
+   * @generated
+   */
+  EClass getEvent();
+
+  /**
+   * Returns the meta object for the reference '{@link org.eclipse.fx.xtext.statemachine.statemachine.Event#getSignal <em>Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the reference '<em>Signal</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Event#getSignal()
+   * @see #getEvent()
+   * @generated
+   */
+  EReference getEvent_Signal();
+
+  /**
+   * Returns the meta object for the attribute '{@link org.eclipse.fx.xtext.statemachine.statemachine.Event#isValue <em>Value</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the attribute '<em>Value</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Event#isValue()
+   * @see #getEvent()
+   * @generated
+   */
+  EAttribute getEvent_Value();
+
+  /**
+   * Returns the meta object for class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Command <em>Command</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for class '<em>Command</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Command
+   * @generated
+   */
+  EClass getCommand();
+
+  /**
+   * Returns the meta object for the reference '{@link org.eclipse.fx.xtext.statemachine.statemachine.Command#getSignal <em>Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the reference '<em>Signal</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Command#getSignal()
+   * @see #getCommand()
+   * @generated
+   */
+  EReference getCommand_Signal();
+
+  /**
+   * Returns the meta object for the attribute '{@link org.eclipse.fx.xtext.statemachine.statemachine.Command#isNewValue <em>New Value</em>}'.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the meta object for the attribute '<em>New Value</em>'.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Command#isNewValue()
+   * @see #getCommand()
+   * @generated
+   */
+  EAttribute getCommand_NewValue();
+
+  /**
+   * Returns the factory that creates the instances of the model.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the factory that creates the instances of the model.
+   * @generated
+   */
+  StatemachineFactory getStatemachineFactory();
+
+  /**
+   * <!-- begin-user-doc -->
+   * Defines literals for the meta objects that represent
+   * <ul>
+   *   <li>each class,</li>
+   *   <li>each feature of each class,</li>
+   *   <li>each enum,</li>
+   *   <li>and each data type</li>
+   * </ul>
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  interface Literals
+  {
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachineImpl <em>Statemachine</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachineImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getStatemachine()
+     * @generated
+     */
+    EClass STATEMACHINE = eINSTANCE.getStatemachine();
+
+    /**
+     * The meta object literal for the '<em><b>Signals</b></em>' containment reference list feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference STATEMACHINE__SIGNALS = eINSTANCE.getStatemachine_Signals();
+
+    /**
+     * The meta object literal for the '<em><b>States</b></em>' containment reference list feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference STATEMACHINE__STATES = eINSTANCE.getStatemachine_States();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.SignalImpl <em>Signal</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.SignalImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getSignal()
+     * @generated
+     */
+    EClass SIGNAL = eINSTANCE.getSignal();
+
+    /**
+     * The meta object literal for the '<em><b>Name</b></em>' attribute feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EAttribute SIGNAL__NAME = eINSTANCE.getSignal_Name();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.InputSignalImpl <em>Input Signal</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.InputSignalImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getInputSignal()
+     * @generated
+     */
+    EClass INPUT_SIGNAL = eINSTANCE.getInputSignal();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.OutputSignalImpl <em>Output Signal</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.OutputSignalImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getOutputSignal()
+     * @generated
+     */
+    EClass OUTPUT_SIGNAL = eINSTANCE.getOutputSignal();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StateImpl <em>State</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StateImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getState()
+     * @generated
+     */
+    EClass STATE = eINSTANCE.getState();
+
+    /**
+     * The meta object literal for the '<em><b>Name</b></em>' attribute feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EAttribute STATE__NAME = eINSTANCE.getState_Name();
+
+    /**
+     * The meta object literal for the '<em><b>Commands</b></em>' containment reference list feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference STATE__COMMANDS = eINSTANCE.getState_Commands();
+
+    /**
+     * The meta object literal for the '<em><b>Transitions</b></em>' containment reference list feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference STATE__TRANSITIONS = eINSTANCE.getState_Transitions();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.TransitionImpl <em>Transition</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.TransitionImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getTransition()
+     * @generated
+     */
+    EClass TRANSITION = eINSTANCE.getTransition();
+
+    /**
+     * The meta object literal for the '<em><b>Condition</b></em>' containment reference feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference TRANSITION__CONDITION = eINSTANCE.getTransition_Condition();
+
+    /**
+     * The meta object literal for the '<em><b>State</b></em>' reference feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference TRANSITION__STATE = eINSTANCE.getTransition_State();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.ConditionImpl <em>Condition</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.ConditionImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getCondition()
+     * @generated
+     */
+    EClass CONDITION = eINSTANCE.getCondition();
+
+    /**
+     * The meta object literal for the '<em><b>Events</b></em>' containment reference list feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference CONDITION__EVENTS = eINSTANCE.getCondition_Events();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.EventImpl <em>Event</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.EventImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getEvent()
+     * @generated
+     */
+    EClass EVENT = eINSTANCE.getEvent();
+
+    /**
+     * The meta object literal for the '<em><b>Signal</b></em>' reference feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference EVENT__SIGNAL = eINSTANCE.getEvent_Signal();
+
+    /**
+     * The meta object literal for the '<em><b>Value</b></em>' attribute feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EAttribute EVENT__VALUE = eINSTANCE.getEvent_Value();
+
+    /**
+     * The meta object literal for the '{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.CommandImpl <em>Command</em>}' class.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.CommandImpl
+     * @see org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachinePackageImpl#getCommand()
+     * @generated
+     */
+    EClass COMMAND = eINSTANCE.getCommand();
+
+    /**
+     * The meta object literal for the '<em><b>Signal</b></em>' reference feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EReference COMMAND__SIGNAL = eINSTANCE.getCommand_Signal();
+
+    /**
+     * The meta object literal for the '<em><b>New Value</b></em>' attribute feature.
+     * <!-- begin-user-doc -->
+     * <!-- end-user-doc -->
+     * @generated
+     */
+    EAttribute COMMAND__NEW_VALUE = eINSTANCE.getCommand_NewValue();
+
+  }
+
+} //StatemachinePackage
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Transition.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Transition.java
new file mode 100644
index 0000000..f786cd9
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Transition.java
@@ -0,0 +1,78 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Transition</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition#getCondition <em>Condition</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition#getState <em>State</em>}</li>
+ * </ul>
+ *
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getTransition()
+ * @model
+ * @generated
+ */
+public interface Transition extends EObject
+{
+  /**
+   * Returns the value of the '<em><b>Condition</b></em>' containment reference.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>Condition</em>' containment reference isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>Condition</em>' containment reference.
+   * @see #setCondition(Condition)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getTransition_Condition()
+   * @model containment="true"
+   * @generated
+   */
+  Condition getCondition();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition#getCondition <em>Condition</em>}' containment reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>Condition</em>' containment reference.
+   * @see #getCondition()
+   * @generated
+   */
+  void setCondition(Condition value);
+
+  /**
+   * Returns the value of the '<em><b>State</b></em>' reference.
+   * <!-- begin-user-doc -->
+   * <p>
+   * If the meaning of the '<em>State</em>' reference isn't clear,
+   * there really should be more of a description here...
+   * </p>
+   * <!-- end-user-doc -->
+   * @return the value of the '<em>State</em>' reference.
+   * @see #setState(State)
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#getTransition_State()
+   * @model
+   * @generated
+   */
+  State getState();
+
+  /**
+   * Sets the value of the '{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition#getState <em>State</em>}' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param value the new value of the '<em>State</em>' reference.
+   * @see #getState()
+   * @generated
+   */
+  void setState(State value);
+
+} // Transition
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/CommandImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/CommandImpl.java
new file mode 100644
index 0000000..944261c
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/CommandImpl.java
@@ -0,0 +1,244 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.common.notify.Notification;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Command;
+import org.eclipse.fx.xtext.statemachine.statemachine.Signal;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Command</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.CommandImpl#getSignal <em>Signal</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.CommandImpl#isNewValue <em>New Value</em>}</li>
+ * </ul>
+ *
+ * @generated
+ */
+public class CommandImpl extends MinimalEObjectImpl.Container implements Command
+{
+  /**
+   * The cached value of the '{@link #getSignal() <em>Signal</em>}' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getSignal()
+   * @generated
+   * @ordered
+   */
+  protected Signal signal;
+
+  /**
+   * The default value of the '{@link #isNewValue() <em>New Value</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #isNewValue()
+   * @generated
+   * @ordered
+   */
+  protected static final boolean NEW_VALUE_EDEFAULT = false;
+
+  /**
+   * The cached value of the '{@link #isNewValue() <em>New Value</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #isNewValue()
+   * @generated
+   * @ordered
+   */
+  protected boolean newValue = NEW_VALUE_EDEFAULT;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected CommandImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.COMMAND;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Signal getSignal()
+  {
+    if (signal != null && signal.eIsProxy())
+    {
+      InternalEObject oldSignal = (InternalEObject)signal;
+      signal = (Signal)eResolveProxy(oldSignal);
+      if (signal != oldSignal)
+      {
+        if (eNotificationRequired())
+          eNotify(new ENotificationImpl(this, Notification.RESOLVE, StatemachinePackage.COMMAND__SIGNAL, oldSignal, signal));
+      }
+    }
+    return signal;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Signal basicGetSignal()
+  {
+    return signal;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setSignal(Signal newSignal)
+  {
+    Signal oldSignal = signal;
+    signal = newSignal;
+    if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.COMMAND__SIGNAL, oldSignal, signal));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public boolean isNewValue()
+  {
+    return newValue;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setNewValue(boolean newNewValue)
+  {
+    boolean oldNewValue = newValue;
+    newValue = newNewValue;
+    if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.COMMAND__NEW_VALUE, oldNewValue, newValue));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public Object eGet(int featureID, boolean resolve, boolean coreType)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.COMMAND__SIGNAL:
+        if (resolve) return getSignal();
+        return basicGetSignal();
+      case StatemachinePackage.COMMAND__NEW_VALUE:
+        return isNewValue();
+    }
+    return super.eGet(featureID, resolve, coreType);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eSet(int featureID, Object newValue)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.COMMAND__SIGNAL:
+        setSignal((Signal)newValue);
+        return;
+      case StatemachinePackage.COMMAND__NEW_VALUE:
+        setNewValue((Boolean)newValue);
+        return;
+    }
+    super.eSet(featureID, newValue);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eUnset(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.COMMAND__SIGNAL:
+        setSignal((Signal)null);
+        return;
+      case StatemachinePackage.COMMAND__NEW_VALUE:
+        setNewValue(NEW_VALUE_EDEFAULT);
+        return;
+    }
+    super.eUnset(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public boolean eIsSet(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.COMMAND__SIGNAL:
+        return signal != null;
+      case StatemachinePackage.COMMAND__NEW_VALUE:
+        return newValue != NEW_VALUE_EDEFAULT;
+    }
+    return super.eIsSet(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public String toString()
+  {
+    if (eIsProxy()) return super.toString();
+
+    StringBuffer result = new StringBuffer(super.toString());
+    result.append(" (newValue: ");
+    result.append(newValue);
+    result.append(')');
+    return result.toString();
+  }
+
+} //CommandImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/ConditionImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/ConditionImpl.java
new file mode 100644
index 0000000..299f20d
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/ConditionImpl.java
@@ -0,0 +1,167 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import java.util.Collection;
+
+import org.eclipse.emf.common.notify.NotificationChain;
+
+import org.eclipse.emf.common.util.EList;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
+import org.eclipse.emf.ecore.util.EObjectContainmentEList;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Condition;
+import org.eclipse.fx.xtext.statemachine.statemachine.Event;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Condition</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.ConditionImpl#getEvents <em>Events</em>}</li>
+ * </ul>
+ *
+ * @generated
+ */
+public class ConditionImpl extends MinimalEObjectImpl.Container implements Condition
+{
+  /**
+   * The cached value of the '{@link #getEvents() <em>Events</em>}' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getEvents()
+   * @generated
+   * @ordered
+   */
+  protected EList<Event> events;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected ConditionImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.CONDITION;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EList<Event> getEvents()
+  {
+    if (events == null)
+    {
+      events = new EObjectContainmentEList<Event>(Event.class, this, StatemachinePackage.CONDITION__EVENTS);
+    }
+    return events;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.CONDITION__EVENTS:
+        return ((InternalEList<?>)getEvents()).basicRemove(otherEnd, msgs);
+    }
+    return super.eInverseRemove(otherEnd, featureID, msgs);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public Object eGet(int featureID, boolean resolve, boolean coreType)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.CONDITION__EVENTS:
+        return getEvents();
+    }
+    return super.eGet(featureID, resolve, coreType);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  public void eSet(int featureID, Object newValue)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.CONDITION__EVENTS:
+        getEvents().clear();
+        getEvents().addAll((Collection<? extends Event>)newValue);
+        return;
+    }
+    super.eSet(featureID, newValue);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eUnset(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.CONDITION__EVENTS:
+        getEvents().clear();
+        return;
+    }
+    super.eUnset(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public boolean eIsSet(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.CONDITION__EVENTS:
+        return events != null && !events.isEmpty();
+    }
+    return super.eIsSet(featureID);
+  }
+
+} //ConditionImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/EventImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/EventImpl.java
new file mode 100644
index 0000000..098a6cd
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/EventImpl.java
@@ -0,0 +1,244 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.common.notify.Notification;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Event;
+import org.eclipse.fx.xtext.statemachine.statemachine.Signal;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Event</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.EventImpl#getSignal <em>Signal</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.EventImpl#isValue <em>Value</em>}</li>
+ * </ul>
+ *
+ * @generated
+ */
+public class EventImpl extends MinimalEObjectImpl.Container implements Event
+{
+  /**
+   * The cached value of the '{@link #getSignal() <em>Signal</em>}' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getSignal()
+   * @generated
+   * @ordered
+   */
+  protected Signal signal;
+
+  /**
+   * The default value of the '{@link #isValue() <em>Value</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #isValue()
+   * @generated
+   * @ordered
+   */
+  protected static final boolean VALUE_EDEFAULT = false;
+
+  /**
+   * The cached value of the '{@link #isValue() <em>Value</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #isValue()
+   * @generated
+   * @ordered
+   */
+  protected boolean value = VALUE_EDEFAULT;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected EventImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.EVENT;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Signal getSignal()
+  {
+    if (signal != null && signal.eIsProxy())
+    {
+      InternalEObject oldSignal = (InternalEObject)signal;
+      signal = (Signal)eResolveProxy(oldSignal);
+      if (signal != oldSignal)
+      {
+        if (eNotificationRequired())
+          eNotify(new ENotificationImpl(this, Notification.RESOLVE, StatemachinePackage.EVENT__SIGNAL, oldSignal, signal));
+      }
+    }
+    return signal;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Signal basicGetSignal()
+  {
+    return signal;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setSignal(Signal newSignal)
+  {
+    Signal oldSignal = signal;
+    signal = newSignal;
+    if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.EVENT__SIGNAL, oldSignal, signal));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public boolean isValue()
+  {
+    return value;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setValue(boolean newValue)
+  {
+    boolean oldValue = value;
+    value = newValue;
+    if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.EVENT__VALUE, oldValue, value));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public Object eGet(int featureID, boolean resolve, boolean coreType)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.EVENT__SIGNAL:
+        if (resolve) return getSignal();
+        return basicGetSignal();
+      case StatemachinePackage.EVENT__VALUE:
+        return isValue();
+    }
+    return super.eGet(featureID, resolve, coreType);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eSet(int featureID, Object newValue)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.EVENT__SIGNAL:
+        setSignal((Signal)newValue);
+        return;
+      case StatemachinePackage.EVENT__VALUE:
+        setValue((Boolean)newValue);
+        return;
+    }
+    super.eSet(featureID, newValue);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eUnset(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.EVENT__SIGNAL:
+        setSignal((Signal)null);
+        return;
+      case StatemachinePackage.EVENT__VALUE:
+        setValue(VALUE_EDEFAULT);
+        return;
+    }
+    super.eUnset(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public boolean eIsSet(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.EVENT__SIGNAL:
+        return signal != null;
+      case StatemachinePackage.EVENT__VALUE:
+        return value != VALUE_EDEFAULT;
+    }
+    return super.eIsSet(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public String toString()
+  {
+    if (eIsProxy()) return super.toString();
+
+    StringBuffer result = new StringBuffer(super.toString());
+    result.append(" (value: ");
+    result.append(value);
+    result.append(')');
+    return result.toString();
+  }
+
+} //EventImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/InputSignalImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/InputSignalImpl.java
new file mode 100644
index 0000000..80ca3e6
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/InputSignalImpl.java
@@ -0,0 +1,40 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.ecore.EClass;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.InputSignal;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Input Signal</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * @generated
+ */
+public class InputSignalImpl extends SignalImpl implements InputSignal
+{
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected InputSignalImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.INPUT_SIGNAL;
+  }
+
+} //InputSignalImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/OutputSignalImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/OutputSignalImpl.java
new file mode 100644
index 0000000..d399494
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/OutputSignalImpl.java
@@ -0,0 +1,40 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.ecore.EClass;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.OutputSignal;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Output Signal</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * @generated
+ */
+public class OutputSignalImpl extends SignalImpl implements OutputSignal
+{
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected OutputSignalImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.OUTPUT_SIGNAL;
+  }
+
+} //OutputSignalImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/SignalImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/SignalImpl.java
new file mode 100644
index 0000000..88087c9
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/SignalImpl.java
@@ -0,0 +1,177 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.common.notify.Notification;
+
+import org.eclipse.emf.ecore.EClass;
+
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Signal;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Signal</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.SignalImpl#getName <em>Name</em>}</li>
+ * </ul>
+ *
+ * @generated
+ */
+public class SignalImpl extends MinimalEObjectImpl.Container implements Signal
+{
+  /**
+   * The default value of the '{@link #getName() <em>Name</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getName()
+   * @generated
+   * @ordered
+   */
+  protected static final String NAME_EDEFAULT = null;
+
+  /**
+   * The cached value of the '{@link #getName() <em>Name</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getName()
+   * @generated
+   * @ordered
+   */
+  protected String name = NAME_EDEFAULT;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected SignalImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.SIGNAL;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setName(String newName)
+  {
+    String oldName = name;
+    name = newName;
+    if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.SIGNAL__NAME, oldName, name));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public Object eGet(int featureID, boolean resolve, boolean coreType)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.SIGNAL__NAME:
+        return getName();
+    }
+    return super.eGet(featureID, resolve, coreType);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eSet(int featureID, Object newValue)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.SIGNAL__NAME:
+        setName((String)newValue);
+        return;
+    }
+    super.eSet(featureID, newValue);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eUnset(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.SIGNAL__NAME:
+        setName(NAME_EDEFAULT);
+        return;
+    }
+    super.eUnset(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public boolean eIsSet(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.SIGNAL__NAME:
+        return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
+    }
+    return super.eIsSet(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public String toString()
+  {
+    if (eIsProxy()) return super.toString();
+
+    StringBuffer result = new StringBuffer(super.toString());
+    result.append(" (name: ");
+    result.append(name);
+    result.append(')');
+    return result.toString();
+  }
+
+} //SignalImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StateImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StateImpl.java
new file mode 100644
index 0000000..7c1b4ce
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StateImpl.java
@@ -0,0 +1,279 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import java.util.Collection;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.NotificationChain;
+
+import org.eclipse.emf.common.util.EList;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
+import org.eclipse.emf.ecore.util.EObjectContainmentEList;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Command;
+import org.eclipse.fx.xtext.statemachine.statemachine.State;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+import org.eclipse.fx.xtext.statemachine.statemachine.Transition;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>State</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StateImpl#getName <em>Name</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StateImpl#getCommands <em>Commands</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StateImpl#getTransitions <em>Transitions</em>}</li>
+ * </ul>
+ *
+ * @generated
+ */
+public class StateImpl extends MinimalEObjectImpl.Container implements State
+{
+  /**
+   * The default value of the '{@link #getName() <em>Name</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getName()
+   * @generated
+   * @ordered
+   */
+  protected static final String NAME_EDEFAULT = null;
+
+  /**
+   * The cached value of the '{@link #getName() <em>Name</em>}' attribute.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getName()
+   * @generated
+   * @ordered
+   */
+  protected String name = NAME_EDEFAULT;
+
+  /**
+   * The cached value of the '{@link #getCommands() <em>Commands</em>}' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getCommands()
+   * @generated
+   * @ordered
+   */
+  protected EList<Command> commands;
+
+  /**
+   * The cached value of the '{@link #getTransitions() <em>Transitions</em>}' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getTransitions()
+   * @generated
+   * @ordered
+   */
+  protected EList<Transition> transitions;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected StateImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.STATE;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setName(String newName)
+  {
+    String oldName = name;
+    name = newName;
+    if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.STATE__NAME, oldName, name));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EList<Command> getCommands()
+  {
+    if (commands == null)
+    {
+      commands = new EObjectContainmentEList<Command>(Command.class, this, StatemachinePackage.STATE__COMMANDS);
+    }
+    return commands;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EList<Transition> getTransitions()
+  {
+    if (transitions == null)
+    {
+      transitions = new EObjectContainmentEList<Transition>(Transition.class, this, StatemachinePackage.STATE__TRANSITIONS);
+    }
+    return transitions;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATE__COMMANDS:
+        return ((InternalEList<?>)getCommands()).basicRemove(otherEnd, msgs);
+      case StatemachinePackage.STATE__TRANSITIONS:
+        return ((InternalEList<?>)getTransitions()).basicRemove(otherEnd, msgs);
+    }
+    return super.eInverseRemove(otherEnd, featureID, msgs);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public Object eGet(int featureID, boolean resolve, boolean coreType)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATE__NAME:
+        return getName();
+      case StatemachinePackage.STATE__COMMANDS:
+        return getCommands();
+      case StatemachinePackage.STATE__TRANSITIONS:
+        return getTransitions();
+    }
+    return super.eGet(featureID, resolve, coreType);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  public void eSet(int featureID, Object newValue)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATE__NAME:
+        setName((String)newValue);
+        return;
+      case StatemachinePackage.STATE__COMMANDS:
+        getCommands().clear();
+        getCommands().addAll((Collection<? extends Command>)newValue);
+        return;
+      case StatemachinePackage.STATE__TRANSITIONS:
+        getTransitions().clear();
+        getTransitions().addAll((Collection<? extends Transition>)newValue);
+        return;
+    }
+    super.eSet(featureID, newValue);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eUnset(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATE__NAME:
+        setName(NAME_EDEFAULT);
+        return;
+      case StatemachinePackage.STATE__COMMANDS:
+        getCommands().clear();
+        return;
+      case StatemachinePackage.STATE__TRANSITIONS:
+        getTransitions().clear();
+        return;
+    }
+    super.eUnset(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public boolean eIsSet(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATE__NAME:
+        return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
+      case StatemachinePackage.STATE__COMMANDS:
+        return commands != null && !commands.isEmpty();
+      case StatemachinePackage.STATE__TRANSITIONS:
+        return transitions != null && !transitions.isEmpty();
+    }
+    return super.eIsSet(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public String toString()
+  {
+    if (eIsProxy()) return super.toString();
+
+    StringBuffer result = new StringBuffer(super.toString());
+    result.append(" (name: ");
+    result.append(name);
+    result.append(')');
+    return result.toString();
+  }
+
+} //StateImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineFactoryImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineFactoryImpl.java
new file mode 100644
index 0000000..afc8041
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineFactoryImpl.java
@@ -0,0 +1,202 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+
+import org.eclipse.emf.ecore.impl.EFactoryImpl;
+
+import org.eclipse.emf.ecore.plugin.EcorePlugin;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.*;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model <b>Factory</b>.
+ * <!-- end-user-doc -->
+ * @generated
+ */
+public class StatemachineFactoryImpl extends EFactoryImpl implements StatemachineFactory
+{
+  /**
+   * Creates the default factory implementation.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public static StatemachineFactory init()
+  {
+    try
+    {
+      StatemachineFactory theStatemachineFactory = (StatemachineFactory)EPackage.Registry.INSTANCE.getEFactory(StatemachinePackage.eNS_URI);
+      if (theStatemachineFactory != null)
+      {
+        return theStatemachineFactory;
+      }
+    }
+    catch (Exception exception)
+    {
+      EcorePlugin.INSTANCE.log(exception);
+    }
+    return new StatemachineFactoryImpl();
+  }
+
+  /**
+   * Creates an instance of the factory.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public StatemachineFactoryImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public EObject create(EClass eClass)
+  {
+    switch (eClass.getClassifierID())
+    {
+      case StatemachinePackage.STATEMACHINE: return createStatemachine();
+      case StatemachinePackage.SIGNAL: return createSignal();
+      case StatemachinePackage.INPUT_SIGNAL: return createInputSignal();
+      case StatemachinePackage.OUTPUT_SIGNAL: return createOutputSignal();
+      case StatemachinePackage.STATE: return createState();
+      case StatemachinePackage.TRANSITION: return createTransition();
+      case StatemachinePackage.CONDITION: return createCondition();
+      case StatemachinePackage.EVENT: return createEvent();
+      case StatemachinePackage.COMMAND: return createCommand();
+      default:
+        throw new IllegalArgumentException("The class '" + eClass.getName() + "' is not a valid classifier");
+    }
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Statemachine createStatemachine()
+  {
+    StatemachineImpl statemachine = new StatemachineImpl();
+    return statemachine;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Signal createSignal()
+  {
+    SignalImpl signal = new SignalImpl();
+    return signal;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public InputSignal createInputSignal()
+  {
+    InputSignalImpl inputSignal = new InputSignalImpl();
+    return inputSignal;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public OutputSignal createOutputSignal()
+  {
+    OutputSignalImpl outputSignal = new OutputSignalImpl();
+    return outputSignal;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public State createState()
+  {
+    StateImpl state = new StateImpl();
+    return state;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Transition createTransition()
+  {
+    TransitionImpl transition = new TransitionImpl();
+    return transition;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Condition createCondition()
+  {
+    ConditionImpl condition = new ConditionImpl();
+    return condition;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Event createEvent()
+  {
+    EventImpl event = new EventImpl();
+    return event;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Command createCommand()
+  {
+    CommandImpl command = new CommandImpl();
+    return command;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public StatemachinePackage getStatemachinePackage()
+  {
+    return (StatemachinePackage)getEPackage();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @deprecated
+   * @generated
+   */
+  @Deprecated
+  public static StatemachinePackage getPackage()
+  {
+    return StatemachinePackage.eINSTANCE;
+  }
+
+} //StatemachineFactoryImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineImpl.java
new file mode 100644
index 0000000..e5ee70e
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineImpl.java
@@ -0,0 +1,206 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import java.util.Collection;
+
+import org.eclipse.emf.common.notify.NotificationChain;
+
+import org.eclipse.emf.common.util.EList;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
+import org.eclipse.emf.ecore.util.EObjectContainmentEList;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Signal;
+import org.eclipse.fx.xtext.statemachine.statemachine.State;
+import org.eclipse.fx.xtext.statemachine.statemachine.Statemachine;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Statemachine</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachineImpl#getSignals <em>Signals</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.StatemachineImpl#getStates <em>States</em>}</li>
+ * </ul>
+ *
+ * @generated
+ */
+public class StatemachineImpl extends MinimalEObjectImpl.Container implements Statemachine
+{
+  /**
+   * The cached value of the '{@link #getSignals() <em>Signals</em>}' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getSignals()
+   * @generated
+   * @ordered
+   */
+  protected EList<Signal> signals;
+
+  /**
+   * The cached value of the '{@link #getStates() <em>States</em>}' containment reference list.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getStates()
+   * @generated
+   * @ordered
+   */
+  protected EList<State> states;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected StatemachineImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.STATEMACHINE;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EList<Signal> getSignals()
+  {
+    if (signals == null)
+    {
+      signals = new EObjectContainmentEList<Signal>(Signal.class, this, StatemachinePackage.STATEMACHINE__SIGNALS);
+    }
+    return signals;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EList<State> getStates()
+  {
+    if (states == null)
+    {
+      states = new EObjectContainmentEList<State>(State.class, this, StatemachinePackage.STATEMACHINE__STATES);
+    }
+    return states;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATEMACHINE__SIGNALS:
+        return ((InternalEList<?>)getSignals()).basicRemove(otherEnd, msgs);
+      case StatemachinePackage.STATEMACHINE__STATES:
+        return ((InternalEList<?>)getStates()).basicRemove(otherEnd, msgs);
+    }
+    return super.eInverseRemove(otherEnd, featureID, msgs);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public Object eGet(int featureID, boolean resolve, boolean coreType)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATEMACHINE__SIGNALS:
+        return getSignals();
+      case StatemachinePackage.STATEMACHINE__STATES:
+        return getStates();
+    }
+    return super.eGet(featureID, resolve, coreType);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  public void eSet(int featureID, Object newValue)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATEMACHINE__SIGNALS:
+        getSignals().clear();
+        getSignals().addAll((Collection<? extends Signal>)newValue);
+        return;
+      case StatemachinePackage.STATEMACHINE__STATES:
+        getStates().clear();
+        getStates().addAll((Collection<? extends State>)newValue);
+        return;
+    }
+    super.eSet(featureID, newValue);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eUnset(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATEMACHINE__SIGNALS:
+        getSignals().clear();
+        return;
+      case StatemachinePackage.STATEMACHINE__STATES:
+        getStates().clear();
+        return;
+    }
+    super.eUnset(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public boolean eIsSet(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.STATEMACHINE__SIGNALS:
+        return signals != null && !signals.isEmpty();
+      case StatemachinePackage.STATEMACHINE__STATES:
+        return states != null && !states.isEmpty();
+    }
+    return super.eIsSet(featureID);
+  }
+
+} //StatemachineImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachinePackageImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachinePackageImpl.java
new file mode 100644
index 0000000..1035e90
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachinePackageImpl.java
@@ -0,0 +1,508 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+
+import org.eclipse.emf.ecore.impl.EPackageImpl;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Command;
+import org.eclipse.fx.xtext.statemachine.statemachine.Condition;
+import org.eclipse.fx.xtext.statemachine.statemachine.Event;
+import org.eclipse.fx.xtext.statemachine.statemachine.InputSignal;
+import org.eclipse.fx.xtext.statemachine.statemachine.OutputSignal;
+import org.eclipse.fx.xtext.statemachine.statemachine.Signal;
+import org.eclipse.fx.xtext.statemachine.statemachine.State;
+import org.eclipse.fx.xtext.statemachine.statemachine.Statemachine;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachineFactory;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+import org.eclipse.fx.xtext.statemachine.statemachine.Transition;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model <b>Package</b>.
+ * <!-- end-user-doc -->
+ * @generated
+ */
+public class StatemachinePackageImpl extends EPackageImpl implements StatemachinePackage
+{
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass statemachineEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass signalEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass inputSignalEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass outputSignalEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass stateEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass transitionEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass conditionEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass eventEClass = null;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private EClass commandEClass = null;
+
+  /**
+   * Creates an instance of the model <b>Package</b>, registered with
+   * {@link org.eclipse.emf.ecore.EPackage.Registry EPackage.Registry} by the package
+   * package URI value.
+   * <p>Note: the correct way to create the package is via the static
+   * factory method {@link #init init()}, which also performs
+   * initialization of the package, or returns the registered package,
+   * if one already exists.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see org.eclipse.emf.ecore.EPackage.Registry
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage#eNS_URI
+   * @see #init()
+   * @generated
+   */
+  private StatemachinePackageImpl()
+  {
+    super(eNS_URI, StatemachineFactory.eINSTANCE);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private static boolean isInited = false;
+
+  /**
+   * Creates, registers, and initializes the <b>Package</b> for this model, and for any others upon which it depends.
+   * 
+   * <p>This method is used to initialize {@link StatemachinePackage#eINSTANCE} when that field is accessed.
+   * Clients should not invoke it directly. Instead, they should simply access that field to obtain the package.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #eNS_URI
+   * @see #createPackageContents()
+   * @see #initializePackageContents()
+   * @generated
+   */
+  public static StatemachinePackage init()
+  {
+    if (isInited) return (StatemachinePackage)EPackage.Registry.INSTANCE.getEPackage(StatemachinePackage.eNS_URI);
+
+    // Obtain or create and register package
+    StatemachinePackageImpl theStatemachinePackage = (StatemachinePackageImpl)(EPackage.Registry.INSTANCE.get(eNS_URI) instanceof StatemachinePackageImpl ? EPackage.Registry.INSTANCE.get(eNS_URI) : new StatemachinePackageImpl());
+
+    isInited = true;
+
+    // Create package meta-data objects
+    theStatemachinePackage.createPackageContents();
+
+    // Initialize created meta-data
+    theStatemachinePackage.initializePackageContents();
+
+    // Mark meta-data to indicate it can't be changed
+    theStatemachinePackage.freeze();
+
+  
+    // Update the registry and return the package
+    EPackage.Registry.INSTANCE.put(StatemachinePackage.eNS_URI, theStatemachinePackage);
+    return theStatemachinePackage;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getStatemachine()
+  {
+    return statemachineEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getStatemachine_Signals()
+  {
+    return (EReference)statemachineEClass.getEStructuralFeatures().get(0);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getStatemachine_States()
+  {
+    return (EReference)statemachineEClass.getEStructuralFeatures().get(1);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getSignal()
+  {
+    return signalEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EAttribute getSignal_Name()
+  {
+    return (EAttribute)signalEClass.getEStructuralFeatures().get(0);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getInputSignal()
+  {
+    return inputSignalEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getOutputSignal()
+  {
+    return outputSignalEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getState()
+  {
+    return stateEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EAttribute getState_Name()
+  {
+    return (EAttribute)stateEClass.getEStructuralFeatures().get(0);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getState_Commands()
+  {
+    return (EReference)stateEClass.getEStructuralFeatures().get(1);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getState_Transitions()
+  {
+    return (EReference)stateEClass.getEStructuralFeatures().get(2);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getTransition()
+  {
+    return transitionEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getTransition_Condition()
+  {
+    return (EReference)transitionEClass.getEStructuralFeatures().get(0);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getTransition_State()
+  {
+    return (EReference)transitionEClass.getEStructuralFeatures().get(1);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getCondition()
+  {
+    return conditionEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getCondition_Events()
+  {
+    return (EReference)conditionEClass.getEStructuralFeatures().get(0);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getEvent()
+  {
+    return eventEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getEvent_Signal()
+  {
+    return (EReference)eventEClass.getEStructuralFeatures().get(0);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EAttribute getEvent_Value()
+  {
+    return (EAttribute)eventEClass.getEStructuralFeatures().get(1);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EClass getCommand()
+  {
+    return commandEClass;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EReference getCommand_Signal()
+  {
+    return (EReference)commandEClass.getEStructuralFeatures().get(0);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public EAttribute getCommand_NewValue()
+  {
+    return (EAttribute)commandEClass.getEStructuralFeatures().get(1);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public StatemachineFactory getStatemachineFactory()
+  {
+    return (StatemachineFactory)getEFactoryInstance();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private boolean isCreated = false;
+
+  /**
+   * Creates the meta-model objects for the package.  This method is
+   * guarded to have no affect on any invocation but its first.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void createPackageContents()
+  {
+    if (isCreated) return;
+    isCreated = true;
+
+    // Create classes and their features
+    statemachineEClass = createEClass(STATEMACHINE);
+    createEReference(statemachineEClass, STATEMACHINE__SIGNALS);
+    createEReference(statemachineEClass, STATEMACHINE__STATES);
+
+    signalEClass = createEClass(SIGNAL);
+    createEAttribute(signalEClass, SIGNAL__NAME);
+
+    inputSignalEClass = createEClass(INPUT_SIGNAL);
+
+    outputSignalEClass = createEClass(OUTPUT_SIGNAL);
+
+    stateEClass = createEClass(STATE);
+    createEAttribute(stateEClass, STATE__NAME);
+    createEReference(stateEClass, STATE__COMMANDS);
+    createEReference(stateEClass, STATE__TRANSITIONS);
+
+    transitionEClass = createEClass(TRANSITION);
+    createEReference(transitionEClass, TRANSITION__CONDITION);
+    createEReference(transitionEClass, TRANSITION__STATE);
+
+    conditionEClass = createEClass(CONDITION);
+    createEReference(conditionEClass, CONDITION__EVENTS);
+
+    eventEClass = createEClass(EVENT);
+    createEReference(eventEClass, EVENT__SIGNAL);
+    createEAttribute(eventEClass, EVENT__VALUE);
+
+    commandEClass = createEClass(COMMAND);
+    createEReference(commandEClass, COMMAND__SIGNAL);
+    createEAttribute(commandEClass, COMMAND__NEW_VALUE);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  private boolean isInitialized = false;
+
+  /**
+   * Complete the initialization of the package and its meta-model.  This
+   * method is guarded to have no affect on any invocation but its first.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void initializePackageContents()
+  {
+    if (isInitialized) return;
+    isInitialized = true;
+
+    // Initialize package
+    setName(eNAME);
+    setNsPrefix(eNS_PREFIX);
+    setNsURI(eNS_URI);
+
+    // Create type parameters
+
+    // Set bounds for type parameters
+
+    // Add supertypes to classes
+    inputSignalEClass.getESuperTypes().add(this.getSignal());
+    outputSignalEClass.getESuperTypes().add(this.getSignal());
+
+    // Initialize classes and features; add operations and parameters
+    initEClass(statemachineEClass, Statemachine.class, "Statemachine", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+    initEReference(getStatemachine_Signals(), this.getSignal(), null, "signals", null, 0, -1, Statemachine.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+    initEReference(getStatemachine_States(), this.getState(), null, "states", null, 0, -1, Statemachine.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+    initEClass(signalEClass, Signal.class, "Signal", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+    initEAttribute(getSignal_Name(), ecorePackage.getEString(), "name", null, 0, 1, Signal.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+    initEClass(inputSignalEClass, InputSignal.class, "InputSignal", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+
+    initEClass(outputSignalEClass, OutputSignal.class, "OutputSignal", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+
+    initEClass(stateEClass, State.class, "State", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+    initEAttribute(getState_Name(), ecorePackage.getEString(), "name", null, 0, 1, State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+    initEReference(getState_Commands(), this.getCommand(), null, "commands", null, 0, -1, State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+    initEReference(getState_Transitions(), this.getTransition(), null, "transitions", null, 0, -1, State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+    initEClass(transitionEClass, Transition.class, "Transition", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+    initEReference(getTransition_Condition(), this.getCondition(), null, "condition", null, 0, 1, Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+    initEReference(getTransition_State(), this.getState(), null, "state", null, 0, 1, Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+    initEClass(conditionEClass, Condition.class, "Condition", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+    initEReference(getCondition_Events(), this.getEvent(), null, "events", null, 0, -1, Condition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+    initEClass(eventEClass, Event.class, "Event", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+    initEReference(getEvent_Signal(), this.getSignal(), null, "signal", null, 0, 1, Event.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+    initEAttribute(getEvent_Value(), ecorePackage.getEBoolean(), "value", null, 0, 1, Event.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+    initEClass(commandEClass, Command.class, "Command", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+    initEReference(getCommand_Signal(), this.getSignal(), null, "signal", null, 0, 1, Command.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+    initEAttribute(getCommand_NewValue(), ecorePackage.getEBoolean(), "newValue", null, 0, 1, Command.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+    // Create resource
+    createResource(eNS_URI);
+  }
+
+} //StatemachinePackageImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/TransitionImpl.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/TransitionImpl.java
new file mode 100644
index 0000000..7f990e2
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/TransitionImpl.java
@@ -0,0 +1,260 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.impl;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.NotificationChain;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.Condition;
+import org.eclipse.fx.xtext.statemachine.statemachine.State;
+import org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage;
+import org.eclipse.fx.xtext.statemachine.statemachine.Transition;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Transition</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * </p>
+ * <ul>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.TransitionImpl#getCondition <em>Condition</em>}</li>
+ *   <li>{@link org.eclipse.fx.xtext.statemachine.statemachine.impl.TransitionImpl#getState <em>State</em>}</li>
+ * </ul>
+ *
+ * @generated
+ */
+public class TransitionImpl extends MinimalEObjectImpl.Container implements Transition
+{
+  /**
+   * The cached value of the '{@link #getCondition() <em>Condition</em>}' containment reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getCondition()
+   * @generated
+   * @ordered
+   */
+  protected Condition condition;
+
+  /**
+   * The cached value of the '{@link #getState() <em>State</em>}' reference.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @see #getState()
+   * @generated
+   * @ordered
+   */
+  protected State state;
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected TransitionImpl()
+  {
+    super();
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  protected EClass eStaticClass()
+  {
+    return StatemachinePackage.Literals.TRANSITION;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public Condition getCondition()
+  {
+    return condition;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public NotificationChain basicSetCondition(Condition newCondition, NotificationChain msgs)
+  {
+    Condition oldCondition = condition;
+    condition = newCondition;
+    if (eNotificationRequired())
+    {
+      ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, StatemachinePackage.TRANSITION__CONDITION, oldCondition, newCondition);
+      if (msgs == null) msgs = notification; else msgs.add(notification);
+    }
+    return msgs;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setCondition(Condition newCondition)
+  {
+    if (newCondition != condition)
+    {
+      NotificationChain msgs = null;
+      if (condition != null)
+        msgs = ((InternalEObject)condition).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - StatemachinePackage.TRANSITION__CONDITION, null, msgs);
+      if (newCondition != null)
+        msgs = ((InternalEObject)newCondition).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - StatemachinePackage.TRANSITION__CONDITION, null, msgs);
+      msgs = basicSetCondition(newCondition, msgs);
+      if (msgs != null) msgs.dispatch();
+    }
+    else if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.TRANSITION__CONDITION, newCondition, newCondition));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public State getState()
+  {
+    if (state != null && state.eIsProxy())
+    {
+      InternalEObject oldState = (InternalEObject)state;
+      state = (State)eResolveProxy(oldState);
+      if (state != oldState)
+      {
+        if (eNotificationRequired())
+          eNotify(new ENotificationImpl(this, Notification.RESOLVE, StatemachinePackage.TRANSITION__STATE, oldState, state));
+      }
+    }
+    return state;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public State basicGetState()
+  {
+    return state;
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public void setState(State newState)
+  {
+    State oldState = state;
+    state = newState;
+    if (eNotificationRequired())
+      eNotify(new ENotificationImpl(this, Notification.SET, StatemachinePackage.TRANSITION__STATE, oldState, state));
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.TRANSITION__CONDITION:
+        return basicSetCondition(null, msgs);
+    }
+    return super.eInverseRemove(otherEnd, featureID, msgs);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public Object eGet(int featureID, boolean resolve, boolean coreType)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.TRANSITION__CONDITION:
+        return getCondition();
+      case StatemachinePackage.TRANSITION__STATE:
+        if (resolve) return getState();
+        return basicGetState();
+    }
+    return super.eGet(featureID, resolve, coreType);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eSet(int featureID, Object newValue)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.TRANSITION__CONDITION:
+        setCondition((Condition)newValue);
+        return;
+      case StatemachinePackage.TRANSITION__STATE:
+        setState((State)newValue);
+        return;
+    }
+    super.eSet(featureID, newValue);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public void eUnset(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.TRANSITION__CONDITION:
+        setCondition((Condition)null);
+        return;
+      case StatemachinePackage.TRANSITION__STATE:
+        setState((State)null);
+        return;
+    }
+    super.eUnset(featureID);
+  }
+
+  /**
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  @Override
+  public boolean eIsSet(int featureID)
+  {
+    switch (featureID)
+    {
+      case StatemachinePackage.TRANSITION__CONDITION:
+        return condition != null;
+      case StatemachinePackage.TRANSITION__STATE:
+        return state != null;
+    }
+    return super.eIsSet(featureID);
+  }
+
+} //TransitionImpl
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineAdapterFactory.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineAdapterFactory.java
new file mode 100644
index 0000000..9550830
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineAdapterFactory.java
@@ -0,0 +1,292 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.util;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notifier;
+
+import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.*;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Adapter Factory</b> for the model.
+ * It provides an adapter <code>createXXX</code> method for each class of the model.
+ * <!-- end-user-doc -->
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage
+ * @generated
+ */
+public class StatemachineAdapterFactory extends AdapterFactoryImpl
+{
+  /**
+   * The cached model package.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected static StatemachinePackage modelPackage;
+
+  /**
+   * Creates an instance of the adapter factory.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public StatemachineAdapterFactory()
+  {
+    if (modelPackage == null)
+    {
+      modelPackage = StatemachinePackage.eINSTANCE;
+    }
+  }
+
+  /**
+   * Returns whether this factory is applicable for the type of the object.
+   * <!-- begin-user-doc -->
+   * This implementation returns <code>true</code> if the object is either the model's package or is an instance object of the model.
+   * <!-- end-user-doc -->
+   * @return whether this factory is applicable for the type of the object.
+   * @generated
+   */
+  @Override
+  public boolean isFactoryForType(Object object)
+  {
+    if (object == modelPackage)
+    {
+      return true;
+    }
+    if (object instanceof EObject)
+    {
+      return ((EObject)object).eClass().getEPackage() == modelPackage;
+    }
+    return false;
+  }
+
+  /**
+   * The switch that delegates to the <code>createXXX</code> methods.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected StatemachineSwitch<Adapter> modelSwitch =
+    new StatemachineSwitch<Adapter>()
+    {
+      @Override
+      public Adapter caseStatemachine(Statemachine object)
+      {
+        return createStatemachineAdapter();
+      }
+      @Override
+      public Adapter caseSignal(Signal object)
+      {
+        return createSignalAdapter();
+      }
+      @Override
+      public Adapter caseInputSignal(InputSignal object)
+      {
+        return createInputSignalAdapter();
+      }
+      @Override
+      public Adapter caseOutputSignal(OutputSignal object)
+      {
+        return createOutputSignalAdapter();
+      }
+      @Override
+      public Adapter caseState(State object)
+      {
+        return createStateAdapter();
+      }
+      @Override
+      public Adapter caseTransition(Transition object)
+      {
+        return createTransitionAdapter();
+      }
+      @Override
+      public Adapter caseCondition(Condition object)
+      {
+        return createConditionAdapter();
+      }
+      @Override
+      public Adapter caseEvent(Event object)
+      {
+        return createEventAdapter();
+      }
+      @Override
+      public Adapter caseCommand(Command object)
+      {
+        return createCommandAdapter();
+      }
+      @Override
+      public Adapter defaultCase(EObject object)
+      {
+        return createEObjectAdapter();
+      }
+    };
+
+  /**
+   * Creates an adapter for the <code>target</code>.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param target the object to adapt.
+   * @return the adapter for the <code>target</code>.
+   * @generated
+   */
+  @Override
+  public Adapter createAdapter(Notifier target)
+  {
+    return modelSwitch.doSwitch((EObject)target);
+  }
+
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Statemachine <em>Statemachine</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Statemachine
+   * @generated
+   */
+  public Adapter createStatemachineAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Signal <em>Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Signal
+   * @generated
+   */
+  public Adapter createSignalAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.InputSignal <em>Input Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.InputSignal
+   * @generated
+   */
+  public Adapter createInputSignalAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.OutputSignal <em>Output Signal</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.OutputSignal
+   * @generated
+   */
+  public Adapter createOutputSignalAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.State <em>State</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.State
+   * @generated
+   */
+  public Adapter createStateAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Transition <em>Transition</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Transition
+   * @generated
+   */
+  public Adapter createTransitionAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Condition <em>Condition</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Condition
+   * @generated
+   */
+  public Adapter createConditionAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Event <em>Event</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Event
+   * @generated
+   */
+  public Adapter createEventAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for an object of class '{@link org.eclipse.fx.xtext.statemachine.statemachine.Command <em>Command</em>}'.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null so that we can easily ignore cases;
+   * it's useful to ignore a case when inheritance will catch all the cases anyway.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @see org.eclipse.fx.xtext.statemachine.statemachine.Command
+   * @generated
+   */
+  public Adapter createCommandAdapter()
+  {
+    return null;
+  }
+
+  /**
+   * Creates a new adapter for the default case.
+   * <!-- begin-user-doc -->
+   * This default implementation returns null.
+   * <!-- end-user-doc -->
+   * @return the new adapter.
+   * @generated
+   */
+  public Adapter createEObjectAdapter()
+  {
+    return null;
+  }
+
+} //StatemachineAdapterFactory
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineSwitch.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineSwitch.java
new file mode 100644
index 0000000..1fa85b8
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineSwitch.java
@@ -0,0 +1,305 @@
+/**
+ */
+package org.eclipse.fx.xtext.statemachine.statemachine.util;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+
+import org.eclipse.emf.ecore.util.Switch;
+
+import org.eclipse.fx.xtext.statemachine.statemachine.*;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Switch</b> for the model's inheritance hierarchy.
+ * It supports the call {@link #doSwitch(EObject) doSwitch(object)}
+ * to invoke the <code>caseXXX</code> method for each class of the model,
+ * starting with the actual class of the object
+ * and proceeding up the inheritance hierarchy
+ * until a non-null result is returned,
+ * which is the result of the switch.
+ * <!-- end-user-doc -->
+ * @see org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage
+ * @generated
+ */
+public class StatemachineSwitch<T> extends Switch<T>
+{
+  /**
+   * The cached model package
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  protected static StatemachinePackage modelPackage;
+
+  /**
+   * Creates an instance of the switch.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @generated
+   */
+  public StatemachineSwitch()
+  {
+    if (modelPackage == null)
+    {
+      modelPackage = StatemachinePackage.eINSTANCE;
+    }
+  }
+
+  /**
+   * Checks whether this is a switch for the given package.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @param ePackage the package in question.
+   * @return whether this is a switch for the given package.
+   * @generated
+   */
+  @Override
+  protected boolean isSwitchFor(EPackage ePackage)
+  {
+    return ePackage == modelPackage;
+  }
+
+  /**
+   * Calls <code>caseXXX</code> for each class of the model until one returns a non null result; it yields that result.
+   * <!-- begin-user-doc -->
+   * <!-- end-user-doc -->
+   * @return the first non-null result returned by a <code>caseXXX</code> call.
+   * @generated
+   */
+  @Override
+  protected T doSwitch(int classifierID, EObject theEObject)
+  {
+    switch (classifierID)
+    {
+      case StatemachinePackage.STATEMACHINE:
+      {
+        Statemachine statemachine = (Statemachine)theEObject;
+        T result = caseStatemachine(statemachine);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.SIGNAL:
+      {
+        Signal signal = (Signal)theEObject;
+        T result = caseSignal(signal);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.INPUT_SIGNAL:
+      {
+        InputSignal inputSignal = (InputSignal)theEObject;
+        T result = caseInputSignal(inputSignal);
+        if (result == null) result = caseSignal(inputSignal);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.OUTPUT_SIGNAL:
+      {
+        OutputSignal outputSignal = (OutputSignal)theEObject;
+        T result = caseOutputSignal(outputSignal);
+        if (result == null) result = caseSignal(outputSignal);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.STATE:
+      {
+        State state = (State)theEObject;
+        T result = caseState(state);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.TRANSITION:
+      {
+        Transition transition = (Transition)theEObject;
+        T result = caseTransition(transition);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.CONDITION:
+      {
+        Condition condition = (Condition)theEObject;
+        T result = caseCondition(condition);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.EVENT:
+      {
+        Event event = (Event)theEObject;
+        T result = caseEvent(event);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      case StatemachinePackage.COMMAND:
+      {
+        Command command = (Command)theEObject;
+        T result = caseCommand(command);
+        if (result == null) result = defaultCase(theEObject);
+        return result;
+      }
+      default: return defaultCase(theEObject);
+    }
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Statemachine</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Statemachine</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseStatemachine(Statemachine object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Signal</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Signal</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseSignal(Signal object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Input Signal</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Input Signal</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseInputSignal(InputSignal object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Output Signal</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Output Signal</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseOutputSignal(OutputSignal object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>State</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>State</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseState(State object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Transition</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Transition</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseTransition(Transition object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Condition</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Condition</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseCondition(Condition object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Event</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Event</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseEvent(Event object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>Command</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>Command</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+   * @generated
+   */
+  public T caseCommand(Command object)
+  {
+    return null;
+  }
+
+  /**
+   * Returns the result of interpreting the object as an instance of '<em>EObject</em>'.
+   * <!-- begin-user-doc -->
+   * This implementation returns null;
+   * returning a non-null result will terminate the switch, but this is the last case anyway.
+   * <!-- end-user-doc -->
+   * @param object the target of the switch.
+   * @return the result of interpreting the object as an instance of '<em>EObject</em>'.
+   * @see #doSwitch(org.eclipse.emf.ecore.EObject)
+   * @generated
+   */
+  @Override
+  public T defaultCase(EObject object)
+  {
+    return null;
+  }
+
+} //StatemachineSwitch
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/validation/AbstractStatemachineValidator.java b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/validation/AbstractStatemachineValidator.java
new file mode 100644
index 0000000..dbd4b4a
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/validation/AbstractStatemachineValidator.java
@@ -0,0 +1,18 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.emf.ecore.EPackage;
+
+public class AbstractStatemachineValidator extends org.eclipse.xtext.validation.AbstractDeclarativeValidator {
+
+	@Override
+	protected List<EPackage> getEPackages() {
+	    List<EPackage> result = new ArrayList<EPackage>();
+	    result.add(org.eclipse.fx.xtext.statemachine.statemachine.StatemachinePackage.eINSTANCE);
+		return result;
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/GenerateStatemachine.mwe2 b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/GenerateStatemachine.mwe2
new file mode 100644
index 0000000..de5f8c6
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/GenerateStatemachine.mwe2
@@ -0,0 +1,95 @@
+module org.eclipse.fx.xtext.statemachine.GenerateStatemachine
+
+import org.eclipse.emf.mwe.utils.*
+import org.eclipse.xtext.generator.*
+import org.eclipse.xtext.ui.generator.*
+
+var grammarURI = "classpath:/org/eclipse/fx/xtext/statemachine/Statemachine.xtext"
+var fileExtensions = "state"
+var projectName = "org.eclipse.fx.xtext.statemachine"
+var runtimeProject = "../${projectName}"
+var generateXtendStub = true
+var encoding = "UTF-8"
+var fileHeader = "/*\n * generated by Xtext \${version}\n */"
+Workflow {
+    bean = StandaloneSetup {
+		scanClassPath = true
+		platformUri = "${runtimeProject}/.."
+		// The following two lines can be removed, if Xbase is not used.
+		registerGeneratedEPackage = "org.eclipse.xtext.xbase.XbasePackage"
+		registerGenModelFile = "platform:/resource/org.eclipse.xtext.xbase/model/Xbase.genmodel"
+	}
+	
+	component = DirectoryCleaner {
+		directory = "${runtimeProject}/src-gen"
+	}
+	
+	component = DirectoryCleaner {
+		directory = "${runtimeProject}/model/generated"
+	}
+	
+	
+	component = DirectoryCleaner {
+		directory = "${runtimeProject}.ide/src-gen"
+	}
+	
+	component = Generator auto-inject {
+		pathRtProject = runtimeProject
+		projectNameRt = projectName
+		pathIdeProject = "${runtimeProject}.ide"
+		projectNameIde = "${projectName}.ide"
+		language = auto-inject {
+			uri = grammarURI
+
+			// Java API to access grammar elements (required by several other fragments)
+			fragment = grammarAccess.GrammarAccessFragment auto-inject {}
+
+			// generates Java API for the generated EPackages
+			fragment = ecore.EMFGeneratorFragment auto-inject {}
+
+			fragment = serializer.SerializerFragment auto-inject {
+				generateStub = false
+			}
+
+			// a custom ResourceFactory for use with EMF
+			fragment = resourceFactory.ResourceFactoryFragment auto-inject {}
+
+			// The antlr parser generator fragment.
+			fragment = parser.antlr.XtextAntlrGeneratorFragment auto-inject {
+			//  options = {
+			//      backtrack = true
+			//  }
+			}
+
+			// Xtend-based API for validation
+			fragment = validation.ValidatorFragment auto-inject {
+			//    composedCheck = "org.eclipse.xtext.validation.ImportUriValidator"
+			//    composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
+			}
+
+			// scoping and exporting API
+			fragment = scoping.ImportNamespacesScopingFragment auto-inject {}
+			fragment = exporting.QualifiedNamesFragment auto-inject {}
+
+			// generator API
+			fragment = generator.GeneratorFragment auto-inject {}
+
+			// formatter API
+			fragment = formatting.FormatterFragment auto-inject {}
+			
+			
+			// generates a more lightweight Antlr parser and lexer tailored for content assist
+			fragment = parser.antlr.XtextAntlrUiGeneratorFragment auto-inject {}
+			// provides the necessary bindings for java types integration
+			fragment = types.TypesGeneratorFragment auto-inject {}
+
+			// generates the required bindings only if the grammar inherits from Xbase
+			fragment = xbase.XbaseGeneratorFragment auto-inject {}
+
+			// generates the required bindings only if the grammar inherits from Xtype
+			fragment = xbase.XtypeGeneratorFragment auto-inject {}
+
+
+		}
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/Statemachine.xtext b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/Statemachine.xtext
new file mode 100644
index 0000000..6d61b88
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/Statemachine.xtext
@@ -0,0 +1,41 @@
+grammar org.eclipse.fx.xtext.statemachine.Statemachine with org.eclipse.xtext.common.Terminals
+
+import "http://www.eclipse.org/emf/2002/Ecore" as ecore
+generate statemachine "http://www.eclipse.org/fx/xtext/statemachine/Statemachine"
+
+Statemachine :
+	{Statemachine}
+	signals+=Signal*
+	states+=State*;
+
+Signal:
+	(InputSignal | OutputSignal) 'signal' name=ID;
+
+InputSignal:
+	{InputSignal}
+	'input';
+
+OutputSignal:
+	{OutputSignal}
+	'output';
+
+State:
+	'state' name=ID
+		commands+=Command*
+		transitions+=Transition*
+	'end';
+
+Transition:
+	'if' condition=Condition 'goto' state=[State];
+
+Condition:
+	events+=Event ('and' events+=Event)*;
+
+Event:
+	signal=[Signal] '==' value=BOOLEAN;
+
+Command:
+	'set' signal=[Signal] '=' newValue=BOOLEAN;
+
+terminal BOOLEAN returns ecore::EBoolean:
+	'true' | 'false';
\ No newline at end of file
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineRuntimeModule.java b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineRuntimeModule.java
new file mode 100644
index 0000000..56a69d3
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineRuntimeModule.java
@@ -0,0 +1,11 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine;
+
+/**
+ * Use this class to register components to be used at runtime / without the Equinox extension registry.
+ */
+public class StatemachineRuntimeModule extends org.eclipse.fx.xtext.statemachine.AbstractStatemachineRuntimeModule {
+
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetup.java b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetup.java
new file mode 100644
index 0000000..9ce8fb4
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetup.java
@@ -0,0 +1,16 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine;
+
+/**
+ * Initialization support for running Xtext languages 
+ * without equinox extension registry
+ */
+public class StatemachineStandaloneSetup extends StatemachineStandaloneSetupGenerated{
+
+	public static void doSetup() {
+		new StatemachineStandaloneSetup().createInjectorAndDoEMFRegistration();
+	}
+}
+
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/formatting/StatemachineFormatter.xtend b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/formatting/StatemachineFormatter.xtend
new file mode 100644
index 0000000..dc17e74
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/formatting/StatemachineFormatter.xtend
@@ -0,0 +1,30 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.formatting
+
+import org.eclipse.xtext.formatting.impl.AbstractDeclarativeFormatter
+import org.eclipse.xtext.formatting.impl.FormattingConfig
+// import com.google.inject.Inject;
+// import org.eclipse.fx.xtext.statemachine.services.StatemachineGrammarAccess
+
+/**
+ * This class contains custom formatting declarations.
+ * 
+ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#formatting
+ * on how and when to use it.
+ * 
+ * Also see {@link org.eclipse.xtext.xtext.XtextFormattingTokenSerializer} as an example
+ */
+class StatemachineFormatter extends AbstractDeclarativeFormatter {
+
+//	@Inject extension StatemachineGrammarAccess
+	
+	override protected void configureFormatting(FormattingConfig c) {
+// It's usually a good idea to activate the following three statements.
+// They will add and preserve newlines around comments
+//		c.setLinewrap(0, 1, 2).before(SL_COMMENTRule)
+//		c.setLinewrap(0, 1, 2).before(ML_COMMENTRule)
+//		c.setLinewrap(0, 1, 1).after(ML_COMMENTRule)
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/generator/StatemachineGenerator.xtend b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/generator/StatemachineGenerator.xtend
new file mode 100644
index 0000000..fe3df30
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/generator/StatemachineGenerator.xtend
@@ -0,0 +1,24 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.generator
+
+import org.eclipse.emf.ecore.resource.Resource
+import org.eclipse.xtext.generator.IGenerator
+import org.eclipse.xtext.generator.IFileSystemAccess
+
+/**
+ * Generates code from your model files on save.
+ * 
+ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
+ */
+class StatemachineGenerator implements IGenerator {
+	
+	override void doGenerate(Resource resource, IFileSystemAccess fsa) {
+//		fsa.generateFile('greetings.txt', 'People to greet: ' + 
+//			resource.allContents
+//				.filter(typeof(Greeting))
+//				.map[name]
+//				.join(', '))
+	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/scoping/StatemachineScopeProvider.xtend b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/scoping/StatemachineScopeProvider.xtend
new file mode 100644
index 0000000..f1093f5
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/scoping/StatemachineScopeProvider.xtend
@@ -0,0 +1,15 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.scoping
+
+/**
+ * This class contains custom scoping description.
+ * 
+ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#scoping
+ * on how and when to use it.
+ *
+ */
+class StatemachineScopeProvider extends org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider {
+
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/validation/StatemachineValidator.xtend b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/validation/StatemachineValidator.xtend
new file mode 100644
index 0000000..0498779
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/validation/StatemachineValidator.xtend
@@ -0,0 +1,25 @@
+/*
+ * generated by Xtext 2.9.0.v201505180813
+ */
+package org.eclipse.fx.xtext.statemachine.validation
+
+//import org.eclipse.xtext.validation.Check
+
+/**
+ * This class contains custom validation rules. 
+ *
+ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation
+ */
+class StatemachineValidator extends AbstractStatemachineValidator {
+
+//  public static val INVALID_NAME = 'invalidName'
+//
+//	@Check
+//	def checkGreetingStartsWithCapital(Greeting greeting) {
+//		if (!Character.isUpperCase(greeting.name.charAt(0))) {
+//			warning('Name should start with a capital', 
+//					MyDslPackage.Literals.GREETING__NAME,
+//					INVALID_NAME)
+//		}
+//	}
+}
diff --git a/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/formatting/.gitignore b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/formatting/.gitignore
new file mode 100644
index 0000000..ce736cc
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/formatting/.gitignore
@@ -0,0 +1,3 @@
+/.StatemachineFormatter.java._trace
+/.StatemachineFormatter.xtendbin
+/StatemachineFormatter.java
diff --git a/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/generator/.gitignore b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/generator/.gitignore
new file mode 100644
index 0000000..d68d8ef
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/generator/.gitignore
@@ -0,0 +1,3 @@
+/.StatemachineGenerator.java._trace
+/.StatemachineGenerator.xtendbin
+/StatemachineGenerator.java
diff --git a/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/scoping/.gitignore b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/scoping/.gitignore
new file mode 100644
index 0000000..00297a1
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/scoping/.gitignore
@@ -0,0 +1,3 @@
+/.StatemachineScopeProvider.java._trace
+/.StatemachineScopeProvider.xtendbin
+/StatemachineScopeProvider.java
diff --git a/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/validation/.gitignore b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/validation/.gitignore
new file mode 100644
index 0000000..68857c2
--- /dev/null
+++ b/demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/validation/.gitignore
@@ -0,0 +1,3 @@
+/.StatemachineValidator.java._trace
+/.StatemachineValidator.xtendbin
+/StatemachineValidator.java