Skip to main content
summaryrefslogtreecommitdiffstats
path: root/demos
diff options
context:
space:
mode:
authorTom Schindl2015-05-20 06:11:17 -0400
committerTom Schindl2015-05-20 06:11:17 -0400
commit21f50985306d1f16673414d8c9a87677b481928f (patch)
tree5be703048498f29ce2b6295eddd845640e913da1 /demos
parent01ba377da930879f137ad68dfdaa91eab99b5190 (diff)
downloadorg.eclipse.efxclipse-21f50985306d1f16673414d8c9a87677b481928f.tar.gz
org.eclipse.efxclipse-21f50985306d1f16673414d8c9a87677b481928f.tar.xz
org.eclipse.efxclipse-21f50985306d1f16673414d8c9a87677b481928f.zip
sample to write (xtext) editors with javafx!
Diffstat (limited to 'demos')
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/.classpath7
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/.gitignore1
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/.project34
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/META-INF/MANIFEST.MF10
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/build.properties4
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/Sample.txt7
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/Sample_big.txt9871
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/StateSample.state13
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/Util.java25
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/SampleJavaCode.java88
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/bright.css78
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/dark.css100
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/AbstractJavaScanner.java74
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/FastJavaPartitionScanner.java534
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaColorConstants.java189
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/IJavaPartitions.java49
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCodeScanner.java406
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaCommentScanner.java188
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaDocScanner.java155
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaSourceConfiguration.java237
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWhitespaceDetector.java25
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/JavaWordDetector.java34
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/java/text/SingleTokenJavaScanner.java32
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/SampleStatemachineCode.java73
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/bright.css42
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/statemachine/dark.css66
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/MySample.java10
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleLabel.java26
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledLabel.java34
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledString.java33
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleStyledTextArea.java36
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextArea.java30
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextField.java25
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextFlow.java37
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/SampleTextNode.java25
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-string.css8
-rw-r--r--demos/org.eclipse.fx.xtext.sample.editor/src/org/eclipse/fx/xtext/sample/editor/text/styled-text.css4
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/.classpath8
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/.gitignore1
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/.project34
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/META-INF/MANIFEST.MF20
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/build.properties4
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/ContentAssistProvider.java143
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/contentassist/field_public_obj.pngbin0 -> 330 bytes
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/internal/StatemachineFXModule.xtend39
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/IStatemachinePartitions.java5
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineCodeScanner.java49
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineDocScanner.java11
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachinePartitionScanner.java15
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/src/org/eclipse/fx/xtext/statemachine/fx/text/StatemachineSourceConfiguration.java83
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.fx/xtend-gen/org/eclipse/fx/xtext/statemachine/fx/internal/.gitignore4
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/.classpath8
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/.gitignore1
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/.project34
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.core.resources.prefs2
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/META-INF/MANIFEST.MF13
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/build.properties5
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/StatemachineParser.java94
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.g1524
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachine.tokens30
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineLexer.java1168
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine.ide/src-gen/org/eclipse/fx/xtext/statemachine/ide/contentassist/antlr/internal/InternalStatemachineParser.java4002
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/.antlr-generator-3.2.0-patch.jarbin0 -> 1484649 bytes
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/.classpath9
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/.gitignore1
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/.launch/Generate Statemachine (state) Language Infrastructure.launch18
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/.project34
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.core.resources.prefs2
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/META-INF/MANIFEST.MF31
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/build.properties15
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.ecore40
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/model/generated/Statemachine.genmodel40
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/plugin.xml15
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/AbstractStatemachineRuntimeModule.java136
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/Statemachine.xtextbinbin0 -> 2773 bytes
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetupGenerated.java53
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineAntlrTokenFileProvider.java16
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/StatemachineParser.java39
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.g589
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachine.tokens30
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineLexer.java1168
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/parser/antlr/internal/InternalStatemachineParser.java1423
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSemanticSequencer.java213
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/serializer/StatemachineSyntacticSequencer.java43
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/services/StatemachineGrammarAccess.java523
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Command.java78
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Condition.java43
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Event.java78
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/InputSignal.java18
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/OutputSignal.java18
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Signal.java51
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/State.java87
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Statemachine.java60
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachineFactory.java115
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/StatemachinePackage.java818
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/Transition.java78
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/CommandImpl.java244
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/ConditionImpl.java167
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/EventImpl.java244
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/InputSignalImpl.java40
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/OutputSignalImpl.java40
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/SignalImpl.java177
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StateImpl.java279
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineFactoryImpl.java202
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachineImpl.java206
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/StatemachinePackageImpl.java508
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/impl/TransitionImpl.java260
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineAdapterFactory.java292
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/statemachine/util/StatemachineSwitch.java305
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src-gen/org/eclipse/fx/xtext/statemachine/validation/AbstractStatemachineValidator.java18
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/GenerateStatemachine.mwe295
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/Statemachine.xtext41
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineRuntimeModule.java11
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/StatemachineStandaloneSetup.java16
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/formatting/StatemachineFormatter.xtend30
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/generator/StatemachineGenerator.xtend24
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/scoping/StatemachineScopeProvider.xtend15
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/src/org/eclipse/fx/xtext/statemachine/validation/StatemachineValidator.xtend25
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/formatting/.gitignore3
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/generator/.gitignore3
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/scoping/.gitignore3
-rw-r--r--demos/org.eclipse.fx.xtext.statemachine/xtend-gen/org/eclipse/fx/xtext/statemachine/validation/.gitignore3
126 files changed, 29068 insertions, 0 deletions
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 000000000..eca7bdba8
--- /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 000000000..ae3c17260
--- /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 000000000..7b81c606d
--- /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 000000000..0c68a61dc
--- /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 000000000..a010cd7a8
--- /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 000000000..34d2e4d2d
--- /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 000000000..7fb70f8dc
--- /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 000000000..c74612b51
--- /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 000000000..051a75c29
--- /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 000000000..85a3f8660
--- /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 000000000..7e28c2061
--- /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 000000000..881d8a484
--- /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 000000000..0eef5bb50
--- /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 000000000..f56cb2ab9
--- /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 000000000..203352b74
--- /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 000000000..c16bf6110
--- /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 000000000..d82ff303c
--- /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 000000000..94f519cc3
--- /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 000000000..6bb280f77
--- /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 000000000..a323eb37b
--- /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 000000000..6da169b46
--- /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 000000000..65c8bdb9d
--- /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 000000000..54e63f64d
--- /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 000000000..87ca70053
--- /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 000000000..1888b0de5
--- /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 000000000..a4130dc2b
--- /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 000000000..121302721
--- /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 000000000..2ebd726bc
--- /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 000000000..b21a1cead
--- /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 000000000..90a0bc933
--- /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 000000000..7f0e5f10e
--- /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 000000000..bfecfb5ea
--- /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 000000000..6c1b355ca
--- /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 000000000..3b22d09e0
--- /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 000000000..3dae50660
--- /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 000000000..c69f06aa9
--- /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 000000000..2c38ecb37
--- /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 000000000..cb8036ec5
--- /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 000000000..0805795ce
--- /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 000000000..ae3c17260
--- /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 000000000..a73c6d01c
--- /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 000000000..0c68a61dc
--- /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 000000000..00f51abff
--- /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 000000000..34d2e4d2d
--- /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 000000000..37416636e
--- /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 000000000..56b3e59bd
--- /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 000000000..da7d9ccd4
--- /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 000000000..565a6260c
--- /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 000000000..892bbb082
--- /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 000000000..95850a540
--- /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 000000000..73a3dd2db
--- /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 000000000..a3d08cf51
--- /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 000000000..eb2eb7044
--- /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 000000000..2534a1484
--- /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 000000000..ae3c17260
--- /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 000000000..38e13d8b1
--- /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 000000000..99f26c020
--- /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 000000000..0c68a61dc
--- /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 000000000..8129130ce
--- /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 000000000..43a929256
--- /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 000000000..eed6a62ce
--- /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 000000000..58b680b99
--- /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 000000000..4cf407101
--- /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 000000000..304c9bc23
--- /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 000000000..62a51fd4c
--- /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/Inter