summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/android/.classpath7
-rw-r--r--src/ui/android/.project33
-rw-r--r--src/ui/android/AndroidManifest.xml18
-rw-r--r--src/ui/android/default.properties13
-rw-r--r--src/ui/android/res/drawable/brushed_metal.pngbin0 -> 36233 bytes
-rw-r--r--src/ui/android/res/drawable/icon.pngbin0 -> 2574 bytes
-rw-r--r--src/ui/android/res/layout/main.xml25
-rw-r--r--src/ui/android/res/values/strings.xml5
-rw-r--r--src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java151
-rw-r--r--src/ui/android/src/se/fnord/android/layout/PredicateLayout.java134
-rw-r--r--src/ui/gwt/.classpath7
-rw-r--r--src/ui/gwt/.project28
-rw-r--r--src/ui/gwt/Editor-compile22
-rw-r--r--src/ui/gwt/Fridge-compile22
-rw-r--r--src/ui/gwt/Fridge-compile-fast19
-rw-r--r--src/ui/gwt/Fridge-compile.bat9
-rw-r--r--src/ui/gwt/Fridge-shell-external19
-rw-r--r--src/ui/gwt/FridgeApp.launch21
-rw-r--r--src/ui/gwt/Morpho-compile19
-rw-r--r--src/ui/gwt/Translate-compile21
-rw-r--r--src/ui/gwt/Translate-compile.bat9
-rw-r--r--src/ui/gwt/Translate-shell-external19
-rw-r--r--src/ui/gwt/TranslateApp.launch21
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml25
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp.gwt.xml25
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp_IE6.gwt.xml5
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/MorphoApp.gwt.xml24
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/PGF.gwt.xml9
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/TranslateApp.gwt.xml25
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/AbstractSyntaxController.java209
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/BrowsePanel.java153
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/CompletionOracle.java144
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java125
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeApp.java268
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java115
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeTextPanel.java113
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/IterableJsArray.java39
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONCallback.java8
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequest.java19
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java79
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/Magnet.java19
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MagnetFactory.java31
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MorphoApp.java63
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MyListBox.java40
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java194
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java323
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SettingsPanel.java111
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/StatusPopup.java36
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SubList.java37
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SuggestPanel.java102
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TranslateApp.java386
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css102
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Fridge.css89
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Translate.css121
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/align-btn.pngbin0 -> 138 bytes
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/brushed-metal.pngbin0 -> 36233 bytes
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/delete-last.pngbin0 -> 395 bytes
-rw-r--r--src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/tree-btn.pngbin0 -> 149 bytes
-rw-r--r--src/ui/gwt/www/editor/index.html36
-rw-r--r--src/ui/gwt/www/fridge/index.html36
-rw-r--r--src/ui/gwt/www/morpho/index.html36
-rw-r--r--src/ui/gwt/www/morpho/morpho.fcgi1
-rw-r--r--src/ui/gwt/www/translate/index.html36
63 files changed, 3806 insertions, 0 deletions
diff --git a/src/ui/android/.classpath b/src/ui/android/.classpath
new file mode 100644
index 000000000..6e9239ff0
--- /dev/null
+++ b/src/ui/android/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/src/ui/android/.project b/src/ui/android/.project
new file mode 100644
index 000000000..c24012a32
--- /dev/null
+++ b/src/ui/android/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>GF-Android</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/src/ui/android/AndroidManifest.xml b/src/ui/android/AndroidManifest.xml
new file mode 100644
index 000000000..be36eaf2d
--- /dev/null
+++ b/src/ui/android/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.grammaticalframework.fridge"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:name=".FridgeMagnets"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+ <uses-sdk android:minSdkVersion="2" />
+
+</manifest> \ No newline at end of file
diff --git a/src/ui/android/default.properties b/src/ui/android/default.properties
new file mode 100644
index 000000000..19c96655d
--- /dev/null
+++ b/src/ui/android/default.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-4
diff --git a/src/ui/android/res/drawable/brushed_metal.png b/src/ui/android/res/drawable/brushed_metal.png
new file mode 100644
index 000000000..c2f03fe7d
--- /dev/null
+++ b/src/ui/android/res/drawable/brushed_metal.png
Binary files differ
diff --git a/src/ui/android/res/drawable/icon.png b/src/ui/android/res/drawable/icon.png
new file mode 100644
index 000000000..a07c69fa5
--- /dev/null
+++ b/src/ui/android/res/drawable/icon.png
Binary files differ
diff --git a/src/ui/android/res/layout/main.xml b/src/ui/android/res/layout/main.xml
new file mode 100644
index 000000000..67ce499fb
--- /dev/null
+++ b/src/ui/android/res/layout/main.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main_view"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/brushed_metal"
+ >
+ <se.fnord.android.layout.PredicateLayout
+ android:id="@+id/magnets_sentence"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="5dip"/>
+
+ <View
+ android:layout_height="8dip"
+ android:layout_width="fill_parent"
+ android:background="#FF909090"/>
+
+ <se.fnord.android.layout.PredicateLayout
+ android:id="@+id/magnets_bag"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="5dip"/>
+</LinearLayout>
diff --git a/src/ui/android/res/values/strings.xml b/src/ui/android/res/values/strings.xml
new file mode 100644
index 000000000..662c708c1
--- /dev/null
+++ b/src/ui/android/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello World, FridgeMagnets!</string>
+ <string name="app_name">Fridge Magnets</string>
+</resources>
diff --git a/src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java b/src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java
new file mode 100644
index 000000000..32c71ba0d
--- /dev/null
+++ b/src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java
@@ -0,0 +1,151 @@
+package org.grammaticalframework.fridge;
+
+import java.util.Arrays;
+
+import android.os.*;
+import android.app.*;
+import android.content.*;
+import android.text.*;
+import android.view.*;
+import android.view.inputmethod.*;
+import android.widget.*;
+import android.graphics.*;
+import se.fnord.android.layout.*;
+
+public class FridgeMagnets extends Activity {
+ /** Called when the activity is first created. */
+ String[] words = {"hello","buy","I","you","have","please","where",
+ "how","go","Gothenburg","London","rakia","wine",
+ "whisky","man","woman","boy","girl","to"};
+
+ private Controller controller = new Controller();
+ private EditText searchBox = null;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ Arrays.sort(words);
+
+ refreshBagOfWords(null);
+
+ View main = findViewById(R.id.main_view);
+ main.setFocusableInTouchMode(true);
+ main.setOnKeyListener(controller);
+ }
+
+ private void applyMagnetStyles(TextView view) {
+ view.setTextColor(Color.BLACK);
+ view.setBackgroundColor(Color.WHITE);
+ view.setSingleLine(true);
+ view.setPadding(2, 2, 2, 2);
+ view.setClickable(true);
+ }
+
+ private void refreshBagOfWords(String prefix) {
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_bag);
+
+ l.removeAllViews();
+
+ for (int i = 0; i < words.length; i++) {
+ if (prefix != null && !words[i].startsWith(prefix))
+ continue;
+
+ TextView t = new TextView(this);
+ t.setText(words[i]);
+ t.setOnTouchListener(controller);
+ applyMagnetStyles(t);
+ l.addView(t, new PredicateLayout.LayoutParams(3, 3));
+ }
+ }
+
+ private void addWord(String word) {
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_sentence);
+
+ TextView t = new TextView(this);
+ t.setText(word);
+ applyMagnetStyles(t);
+ l.addView(t, new PredicateLayout.LayoutParams(3, 3));
+ }
+
+ private void showSearchBox() {
+ if (searchBox != null)
+ return;
+
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_sentence);
+
+ EditText edit = new EditText(this);
+ edit.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+ edit.addTextChangedListener(controller);
+ edit.setOnKeyListener(controller);
+ applyMagnetStyles(edit);
+
+ l.addView(edit, new PredicateLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ 3, 3));
+ edit.requestFocus();
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(edit, 0);
+
+ searchBox = edit;
+ }
+
+ private void hideSearchBox() {
+ if (searchBox == null)
+ return;
+
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(searchBox.getWindowToken(), 0);
+
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_sentence);
+ l.removeView(searchBox);
+
+ refreshBagOfWords(null);
+
+ searchBox = null;
+ }
+
+ private class Controller implements View.OnKeyListener, View.OnTouchListener, TextWatcher {
+
+ @Override
+ public boolean onKey(View view, int keyCode, KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ if (searchBox == null && keyCode == KeyEvent.KEYCODE_SEARCH) {
+ showSearchBox();
+ return true;
+ } else if (searchBox != null && keyCode == KeyEvent.KEYCODE_SEARCH) {
+ hideSearchBox();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ hideSearchBox();
+ addWord(((TextView) view).getText().toString());
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence text, int arg1, int arg2, int arg3) {
+ refreshBagOfWords(text.toString());
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ui/android/src/se/fnord/android/layout/PredicateLayout.java b/src/ui/android/src/se/fnord/android/layout/PredicateLayout.java
new file mode 100644
index 000000000..4734d4618
--- /dev/null
+++ b/src/ui/android/src/se/fnord/android/layout/PredicateLayout.java
@@ -0,0 +1,134 @@
+package se.fnord.android.layout;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * ViewGroup that arranges child views in a similar way to text, with them laid
+ * out one line at a time and "wrapping" to the next line as needed.
+ *
+ * Code licensed under CC-by-SA
+ *
+ * @author Henrik Gustafsson
+ * @see http://stackoverflow.com/questions/549451/line-breaking-widget-layout-for-android
+ * @license http://creativecommons.org/licenses/by-sa/2.5/
+ *
+ */
+public class PredicateLayout extends ViewGroup {
+
+ private int line_height;
+
+ public static class LayoutParams extends ViewGroup.LayoutParams {
+ public final int horizontal_spacing;
+ public final int vertical_spacing;
+
+ /**
+ * @param horizontal_spacing Pixels between items, horizontally
+ * @param vertical_spacing Pixels between items, vertically
+ */
+ public LayoutParams(int horizontal_spacing, int vertical_spacing) {
+ this(0, 0, horizontal_spacing, vertical_spacing);
+ }
+
+ /**
+ * @param width
+ * @param height
+ * @param horizontal_spacing Pixels between items, horizontally
+ * @param vertical_spacing Pixels between items, vertically
+ */
+ public LayoutParams(int width, int height, int horizontal_spacing, int vertical_spacing) {
+ super(width, height);
+ this.horizontal_spacing = horizontal_spacing;
+ this.vertical_spacing = vertical_spacing;
+ }
+ }
+
+ public PredicateLayout(Context context) {
+ super(context);
+ }
+
+ public PredicateLayout(Context context, AttributeSet attrs){
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ assert(MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);
+
+ final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
+ int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
+ final int count = getChildCount();
+ int line_height = 0;
+
+ int xpos = getPaddingLeft();
+ int ypos = getPaddingTop();
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ child.measure(
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
+
+ final int childw = child.getMeasuredWidth();
+ line_height = Math.max(line_height, child.getMeasuredHeight() + lp.vertical_spacing);
+
+ if (xpos + childw > width) {
+ xpos = getPaddingLeft();
+ ypos += line_height;
+ }
+
+ xpos += childw + lp.horizontal_spacing;
+ }
+ }
+ this.line_height = line_height;
+
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED){
+ height = ypos + line_height;
+
+ } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST){
+ if (ypos + line_height < height){
+ height = ypos + line_height;
+ }
+ }
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(1, 1); // default of 1px spacing
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ if (p instanceof LayoutParams)
+ return true;
+ return false;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int count = getChildCount();
+ final int width = r - l;
+ int xpos = getPaddingLeft();
+ int ypos = getPaddingTop();
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ final int childw = child.getMeasuredWidth();
+ final int childh = child.getMeasuredHeight();
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (xpos + childw > width) {
+ xpos = getPaddingLeft();
+ ypos += line_height;
+ }
+ child.layout(xpos, ypos, xpos + childw, ypos + childh);
+ xpos += childw + lp.horizontal_spacing;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ui/gwt/.classpath b/src/ui/gwt/.classpath
new file mode 100644
index 000000000..781d7a2f8
--- /dev/null
+++ b/src/ui/gwt/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
+ <classpathentry kind="output" path="src"/>
+</classpath>
diff --git a/src/ui/gwt/.project b/src/ui/gwt/.project
new file mode 100644
index 000000000..dfd6dab3f
--- /dev/null
+++ b/src/ui/gwt/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>GF-GWT</name>
+ <comment>GF-GWT project</comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>com.google.gwt.eclipse.core.gwtNature</nature>
+ </natures>
+</projectDescription>
diff --git a/src/ui/gwt/Editor-compile b/src/ui/gwt/Editor-compile
new file mode 100644
index 000000000..89968b4ce
--- /dev/null
+++ b/src/ui/gwt/Editor-compile
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+APPDIR=`dirname $0`;
+
+GWT_DIR="/home/angelov/gwt-linux-1.5.3"
+GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-linux.jar"
+
+if [ -z "$GWT_CLASSPATH" ]; then
+ echo 'ERROR: $GWT_CLASSPATH is not set'
+ echo 'Set $GWT_CLASSPATH to point to the GWT JAR files. For example:'
+ echo 'export GWT_DIR="/Users/bringert/src/gwt-mac-1.5.2"'
+ echo 'export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-mac.jar"'
+ exit 1
+fi
+
+if [ `uname` = "Darwin" ]; then
+ GWT_JAVA_OPTS=-XstartOnFirstThread
+fi
+
+LIBS=$APPDIR/lib/gwt-dnd-2.5.6.jar
+
+java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$LIBS:$GWT_CLASSPATH" com.google.gwt.dev.GWTCompiler -out "$APPDIR/www/editor" "$@" se.chalmers.cs.gf.gwt.EditorApp;
diff --git a/src/ui/gwt/Fridge-compile b/src/ui/gwt/Fridge-compile
new file mode 100644
index 000000000..d8335ae5c
--- /dev/null
+++ b/src/ui/gwt/Fridge-compile
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+APPDIR=`dirname $0`;
+
+GWT_DIR="/home/angelov/gwt-linux-1.5.3"
+GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-linux.jar"
+
+if [ -z "$GWT_CLASSPATH" ]; then
+ echo 'ERROR: $GWT_CLASSPATH is not set'
+ echo 'Set $GWT_CLASSPATH to point to the GWT JAR files. For example:'
+ echo 'export GWT_DIR="/Users/bringert/src/gwt-mac-1.5.2"'
+ echo 'export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-mac.jar"'
+ exit 1
+fi
+
+if [ `uname` = "Darwin" ]; then
+ GWT_JAVA_OPTS=-XstartOnFirstThread
+fi
+
+LIBS=$APPDIR/lib/gwt-dnd-2.5.6.jar
+
+java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$LIBS:$GWT_CLASSPATH" com.google.gwt.dev.GWTCompiler -out "$APPDIR/www/fridge" "$@" se.chalmers.cs.gf.gwt.FridgeApp;
diff --git a/src/ui/gwt/Fridge-compile-fast b/src/ui/gwt/Fridge-compile-fast
new file mode 100644
index 000000000..1a7a4df03
--- /dev/null
+++ b/src/ui/gwt/Fridge-compile-fast
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+APPDIR=`dirname $0`;
+
+if [ -z "$GWT_CLASSPATH" ]; then
+ echo 'ERROR: $GWT_CLASSPATH is not set'
+ echo 'Set $GWT_CLASSPATH to point to the GWT JAR files. For example:'
+ echo 'export GWT_DIR="/Users/bringert/src/gwt-mac-1.5.2"'
+ echo 'export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-mac.jar"'
+ exit 1
+fi
+
+if [ `uname` = "Darwin" ]; then
+ GWT_JAVA_OPTS=-XstartOnFirstThread
+fi
+
+LIBS=$APPDIR/lib/gwt-dnd-2.5.6.jar
+
+java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$LIBS:$GWT_CLASSPATH" com.google.gwt.dev.GWTCompiler -out "$APPDIR/www" -style DETAILED "$@" se.chalmers.cs.gf.gwt.FridgeApp_IE6;
diff --git a/src/ui/gwt/Fridge-compile.bat b/src/ui/gwt/Fridge-compile.bat
new file mode 100644
index 000000000..8617d8528
--- /dev/null
+++ b/src/ui/gwt/Fridge-compile.bat
@@ -0,0 +1,9 @@
+@echo off
+
+set APPDIR=.
+set GWT_DIR=c:\gwt-windows-1.5.2
+set GWT_CLASSPATH="%GWT_DIR%\gwt-user.jar;%GWT_DIR%\gwt-dev-windows.jar"
+
+set LIBS=%APPDIR%\lib\gwt-dnd-2.5.6.jar
+
+java %GWT_JAVA_OPTS% -Xmx256M -cp "%APPDIR%\src;%APPDIR%\bin;%LIBS%;%GWT_CLASSPATH%" com.google.gwt.dev.GWTCompiler -out "%APPDIR%\www\fridge" se.chalmers.cs.gf.gwt.FridgeApp
diff --git a/src/ui/gwt/Fridge-shell-external b/src/ui/gwt/Fridge-shell-external
new file mode 100644
index 000000000..1209047ed
--- /dev/null
+++ b/src/ui/gwt/Fridge-shell-external
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+APPDIR=`dirname $0`;
+
+if [ -z "$GWT_CLASSPATH" ]; then
+ echo 'ERROR: $GWT_CLASSPATH is not set'
+ echo 'Set $GWT_CLASSPATH to point to the GWT JAR files. For example:'
+ echo 'export GWT_DIR="/Users/bringert/src/gwt-mac-1.5.2"'
+ echo 'export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-mac.jar"'
+ exit 1
+fi
+
+if [ `uname` = "Darwin" ]; then
+ GWT_JAVA_OPTS=-XstartOnFirstThread
+fi
+
+LIBS=$APPDIR/lib/gwt-dnd-2.5.6.jar
+
+java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$LIBS:$GWT_CLASSPATH" com.google.gwt.dev.GWTShell -out "$APPDIR/www" -noserver "$@" http://localhost:41296/fridge/;
diff --git a/src/ui/gwt/FridgeApp.launch b/src/ui/gwt/FridgeApp.launch
new file mode 100644
index 000000000..dc0d1fe68
--- /dev/null
+++ b/src/ui/gwt/FridgeApp.launch
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/GF-GWT"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
+<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER&quot; javaProject=&quot;GF-GWT&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/GF-GWT/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento project=&quot;GF-GWT&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;/Users/bringert/src/gwt-mac-1.5.3/gwt-dev-mac.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.GWTShell"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-out www -noserver http://localhost:41296/fridge/"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="GF-GWT"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx256M"/>
+</launchConfiguration>
diff --git a/src/ui/gwt/Morpho-compile b/src/ui/gwt/Morpho-compile
new file mode 100644
index 000000000..e3cb451ed
--- /dev/null
+++ b/src/ui/gwt/Morpho-compile
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+APPDIR=`dirname $0`;
+
+if [ -z "$GWT_CLASSPATH" ]; then
+ echo 'ERROR: $GWT_CLASSPATH is not set'
+ echo 'Set $GWT_CLASSPATH to point to the GWT JAR files. For example:'
+ echo 'export GWT_DIR="/Users/bringert/src/gwt-mac-1.5.2"'
+ echo 'export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-mac.jar"'
+ exit 1
+fi
+
+if [ `uname` = "Darwin" ]; then
+ GWT_JAVA_OPTS=-XstartOnFirstThread
+fi
+
+LIBS=$APPDIR/lib/gwt-dnd-2.5.6.jar
+
+java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$LIBS:$GWT_CLASSPATH" com.google.gwt.dev.GWTCompiler -out "$APPDIR/www/morpho" "$@" se.chalmers.cs.gf.gwt.MorphoApp;
diff --git a/src/ui/gwt/Translate-compile b/src/ui/gwt/Translate-compile
new file mode 100644
index 000000000..a2c6faaf0
--- /dev/null
+++ b/src/ui/gwt/Translate-compile
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+APPDIR=`dirname $0`;
+export GWT_DIR="/home/angelov/gwt-linux-1.5.3"
+export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-linux.jar"
+
+if [ -z "$GWT_CLASSPATH" ]; then
+ echo 'ERROR: $GWT_CLASSPATH is not set'
+ echo 'Set $GWT_CLASSPATH to point to the GWT JAR files. For example:'
+ echo 'export GWT_DIR="/Users/bringert/src/gwt-mac-1.5.2"'
+ echo 'export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-mac.jar"'
+ exit 1
+fi
+
+if [ `uname` = "Darwin" ]; then
+ GWT_JAVA_OPTS=-XstartOnFirstThread
+fi
+
+LIBS=$APPDIR/lib/gwt-dnd-2.5.6.jar
+
+java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$LIBS:$GWT_CLASSPATH" com.google.gwt.dev.GWTCompiler -out "$APPDIR/www/translate" "$@" se.chalmers.cs.gf.gwt.TranslateApp;
diff --git a/src/ui/gwt/Translate-compile.bat b/src/ui/gwt/Translate-compile.bat
new file mode 100644
index 000000000..df3ee9389
--- /dev/null
+++ b/src/ui/gwt/Translate-compile.bat
@@ -0,0 +1,9 @@
+@echo off
+
+set APPDIR=.
+set GWT_DIR=c:\gwt-windows-1.5.2
+set GWT_CLASSPATH="%GWT_DIR%\gwt-user.jar;%GWT_DIR%\gwt-dev-windows.jar"
+
+set LIBS=%APPDIR%\lib\gwt-dnd-2.5.6.jar
+
+java %GWT_JAVA_OPTS% -Xmx256M -cp "%APPDIR%\src;%APPDIR%\bin;%LIBS%;%GWT_CLASSPATH%" com.google.gwt.dev.GWTCompiler -out "%APPDIR%\www\translate" se.chalmers.cs.gf.gwt.TranslateApp
diff --git a/src/ui/gwt/Translate-shell-external b/src/ui/gwt/Translate-shell-external
new file mode 100644
index 000000000..b1e58f019
--- /dev/null
+++ b/src/ui/gwt/Translate-shell-external
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+APPDIR=`dirname $0`;
+
+if [ -z "$GWT_CLASSPATH" ]; then
+ echo 'ERROR: $GWT_CLASSPATH is not set'
+ echo 'Set $GWT_CLASSPATH to point to the GWT JAR files. For example:'
+ echo 'export GWT_DIR="/Users/bringert/src/gwt-mac-1.5.2"'
+ echo 'export GWT_CLASSPATH="$GWT_DIR/gwt-user.jar:$GWT_DIR/gwt-dev-mac.jar"'
+ exit 1
+fi
+
+if [ `uname` = "Darwin" ]; then
+ GWT_JAVA_OPTS=-XstartOnFirstThread
+fi
+
+LIBS=$APPDIR/lib/gwt-dnd-2.5.6.jar
+
+java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$LIBS:$GWT_CLASSPATH" com.google.gwt.dev.GWTShell -out "$APPDIR/www" -noserver "$@" http://localhost:41296/translate/;
diff --git a/src/ui/gwt/TranslateApp.launch b/src/ui/gwt/TranslateApp.launch
new file mode 100644
index 000000000..bde6c0643
--- /dev/null
+++ b/src/ui/gwt/TranslateApp.launch
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/GF-GWT"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
+<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER&quot; javaProject=&quot;GF-GWT&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/GF-GWT/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento project=&quot;GF-GWT&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;/Users/bringert/src/gwt-mac-1.5.3/gwt-dev-mac.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.GWTShell"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-out www -noserver http://localhost:41296/translate/"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="GF-GWT"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx256M"/>
+</launchConfiguration>
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml
new file mode 100644
index 000000000..ac5dae0b1
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml
@@ -0,0 +1,25 @@
+<module>
+
+ <!-- Inherit the core Web Toolkit stuff. -->
+ <inherits name="com.google.gwt.user.User" />
+ <inherits name="com.google.gwt.xml.XML" />
+
+ <inherits name="org.grammaticalframework.ui.gwt.PGF" />
+
+ <!-- Inherit the default GWT style sheet. You can change -->
+ <!-- the theme of your GWT application by uncommenting -->
+ <!-- any one of the following lines. -->
+ <inherits name="com.google.gwt.user.theme.standard.Standard"/>
+ <!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
+ <!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> -->
+
+ <!-- Other module inherits -->
+
+
+ <!-- Specify the app entry point class. -->
+ <entry-point class="se.chalmers.cs.gf.gwt.client.EditorApp" />
+
+ <!-- Specify the application specific style sheet. -->
+ <stylesheet src="Editor.css" />
+
+</module>
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp.gwt.xml b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp.gwt.xml
new file mode 100644
index 000000000..b041f9830
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp.gwt.xml
@@ -0,0 +1,25 @@
+<module>
+
+ <!-- Inherit the core Web Toolkit stuff. -->
+ <inherits name="com.google.gwt.user.User" />
+ <inherits name="com.google.gwt.xml.XML" />
+
+ <inherits name="org.grammaticalframework.ui.gwt.PGF" />
+
+ <!-- Inherit the default GWT style sheet. You can change -->
+ <!-- the theme of your GWT application by uncommenting -->
+ <!-- any one of the following lines. -->
+ <inherits name="com.google.gwt.user.theme.standard.Standard"/>
+ <!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
+ <!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> -->
+
+ <!-- Other module inherits -->
+
+
+ <!-- Specify the app entry point class. -->
+ <entry-point class="org.grammaticalframework.ui.gwt.client.FridgeApp" />
+
+ <!-- Specify the application specific style sheet. -->
+ <stylesheet src="Fridge.css" />
+
+</module>
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp_IE6.gwt.xml b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp_IE6.gwt.xml
new file mode 100644
index 000000000..c72067421
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/FridgeApp_IE6.gwt.xml
@@ -0,0 +1,5 @@
+<module rename-to="se.chalmers.cs.gf.gwt.FridgeApp">
+ <inherits name="se.chalmers.cs.gf.gwt.FridgeApp" />
+ <set-property name="user.agent" value="ie6" />
+ <set-property name="locale" value="default" />
+</module> \ No newline at end of file
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/MorphoApp.gwt.xml b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/MorphoApp.gwt.xml
new file mode 100644
index 000000000..3743667f7
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/MorphoApp.gwt.xml
@@ -0,0 +1,24 @@
+<module>
+
+ <!-- Inherit the core Web Toolkit stuff. -->
+ <inherits name="com.google.gwt.user.User" />
+ <inherits name="com.google.gwt.xml.XML" />
+
+ <!-- Inherit the default GWT style sheet. You can change -->
+ <!-- the theme of your GWT application by uncommenting -->
+ <!-- any one of the following lines. -->
+ <inherits name="com.google.gwt.user.theme.standard.Standard"/>
+ <!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
+ <!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> -->
+
+ <!-- Other module inherits -->
+ <inherits name='com.allen_sauer.gwt.dnd.gwt-dnd'/>
+
+
+ <!-- Specify the app entry point class. -->
+ <entry-point class="se.chalmers.cs.gf.gwt.client.MorphoApp" />
+
+ <!-- Specify the application specific style sheet. -->
+ <stylesheet src="Morpho.css" />
+
+</module>
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/PGF.gwt.xml b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/PGF.gwt.xml
new file mode 100644
index 000000000..549a16f0d
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/PGF.gwt.xml
@@ -0,0 +1,9 @@
+<module>
+
+ <!-- Inherit the core Web Toolkit stuff. -->
+ <inherits name="com.google.gwt.user.User" />
+ <inherits name="com.google.gwt.http.HTTP" />
+ <inherits name="com.google.gwt.json.JSON" />
+ <inherits name="com.google.gwt.xml.XML" />
+
+</module>
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/TranslateApp.gwt.xml b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/TranslateApp.gwt.xml
new file mode 100644
index 000000000..ef51227ec
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/TranslateApp.gwt.xml
@@ -0,0 +1,25 @@
+<module>
+
+ <!-- Inherit the core Web Toolkit stuff. -->
+ <inherits name="com.google.gwt.user.User" />
+ <inherits name="com.google.gwt.xml.XML" />
+
+ <inherits name="org.grammaticalframework.ui.gwt.PGF" />
+
+ <!-- Inherit the default GWT style sheet. You can change -->
+ <!-- the theme of your GWT application by uncommenting -->
+ <!-- any one of the following lines. -->
+ <inherits name="com.google.gwt.user.theme.standard.Standard"/>
+ <!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
+ <!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> -->
+
+ <!-- Other module inherits -->
+
+
+ <!-- Specify the app entry point class. -->
+ <entry-point class="org.grammaticalframework.ui.gwt.client.TranslateApp" />
+
+ <!-- Specify the application specific style sheet. -->
+ <stylesheet src="Translate.css" />
+
+</module>
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/AbstractSyntaxController.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/AbstractSyntaxController.java
new file mode 100644
index 000000000..85c44475d
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/AbstractSyntaxController.java
@@ -0,0 +1,209 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.*;
+
+import com.google.gwt.user.client.ui.*;
+
+
+public class AbstractSyntaxController {
+ private final Tree abstractTree;
+ private final FlowPanel textPanel;
+
+ private Map<Panel,TreeItem> panels;
+ private Map<TreeItem,List<Panel>> items;
+
+ private ClickListener labelClickListener;
+
+ private Panel focusPanel = null;
+ private Panel selectedPanel = null;
+ private TreeItem lastPanelItem = null;
+
+ public AbstractSyntaxController(final Tree abstractTree, final FlowPanel textPanel)
+ {
+ this.abstractTree = abstractTree;
+ this.textPanel = textPanel;
+
+ panels = new HashMap();
+ items = new HashMap();
+
+ abstractTree.addTreeListener(new TreeListener() {
+ public void onTreeItemSelected(TreeItem item)
+ {
+ focusPanel = selectedPanel;
+
+ for (Panel panel : panels.keySet())
+ {
+ panel.removeStyleDependentName("selected");
+ panel.removeStyleDependentName("focused");
+ }
+
+ List<Panel> panels = items.get(item);
+ if (panels != null)
+ {
+ for (Panel panel : panels)
+ {
+ String style = (panel == selectedPanel) ? "focused" : "selected";
+ panel.addStyleDependentName(style);
+ }
+ }
+ }
+
+ public void onTreeItemStateChanged(TreeItem item)
+ {
+ }
+ });
+
+ labelClickListener = new ClickListener() {
+ public void onClick(Widget sender) {
+ Panel panel = (Panel) (sender.getParent());
+
+ TreeItem item = panels.get(panel);
+ if (item != null)
+ {
+ selectedPanel = panel;
+ abstractTree.setSelectedItem(item);
+ abstractTree.ensureSelectedItemVisible();
+ selectedPanel = null;
+ }
+ }
+ };
+ }
+
+ public TreeItem addItem(String label)
+ {
+ TreeItem child = abstractTree.addItem(label);
+ addPanel(child, textPanel);
+ return child;
+ }
+
+ public TreeItem addItem(TreeItem parent, String label)
+ {
+ TreeItem child = parent.addItem(label);
+ addPanel(child, getPanel(parent));
+ return child;
+ }
+
+ private Panel addPanel(TreeItem item, Panel parentPanel)
+ {
+ FlowPanel wordsPanel = new FlowPanel();
+ wordsPanel.setStylePrimaryName("my-WordsPanel");
+ panels.put(wordsPanel,item);
+
+ List<Panel> others = items.get(item);
+ if (others == null)
+ {
+ others = new ArrayList();
+ items.put(item,others);
+ }
+ others.add(wordsPanel);
+
+ parentPanel.add(wordsPanel);
+
+ lastPanelItem = item;
+ return wordsPanel;
+ }
+
+ private Panel getPanel(TreeItem item)
+ {
+ TreeItem tmpItem;
+
+ LinkedList<TreeItem> curr = new LinkedList();
+ tmpItem = item;
+ while (tmpItem != null)
+ {
+ curr.addFirst(tmpItem);
+ tmpItem = tmpItem.getParentItem();
+ }
+
+ LinkedList<TreeItem> last = new LinkedList();
+ tmpItem = lastPanelItem;
+ while (tmpItem != null)
+ {
+ last.addFirst(tmpItem);
+ tmpItem = tmpItem.getParentItem();
+ }
+
+ int i = 0;
+ TreeItem parent = null;
+ while (i < curr.size() && i < last.size())
+ {
+ if (curr.get(i) != last.get(i))
+ break;
+
+ parent = curr.get(i);
+ i++;
+ }
+
+ List<Panel> others = items.get(parent);
+ if (others == null)
+ return null;
+ Panel panel = others.get(others.size()-1);
+
+ if (parent != item)
+ {
+ while (i < curr.size())
+ panel = addPanel(curr.get(i++), panel);
+ }
+
+ return panel;
+ }
+
+ public Label addWord(TreeItem item, String word)
+ {
+ Panel wordsPanel = getPanel(item);
+
+ Label wordLabel = new Label(word);
+ wordLabel.setStylePrimaryName("my-WordLabel");
+ wordLabel.addClickListener(labelClickListener);
+
+ wordsPanel.add(wordLabel);
+
+ return wordLabel;
+ }
+
+ public void edit()
+ {
+ if (focusPanel != null)
+ {
+ FlowPanel mainPanel = new FlowPanel();
+ mainPanel.add(new Magnet("fish","LangEng"));
+ mainPanel.add(new Magnet("beer","LangEng"));
+ mainPanel.add(new Magnet("cheese","LangEng"));
+ mainPanel.add(new Magnet("expensive","LangEng"));
+ mainPanel.add(new Magnet("delicious","LangEng"));
+
+ DecoratedPopupPanel completionPopup = new DecoratedPopupPanel(true);
+ completionPopup.addStyleName("my-FridgeBagPopup");
+ completionPopup.setWidget(mainPanel);
+ completionPopup.setPopupPosition(100, 100);
+ completionPopup.show();
+
+ final List<Widget> children = new ArrayList();
+ for (Widget widget : focusPanel)
+ {
+ children.add(widget);
+ }
+
+ TextBox textBox = new TextBox();
+ textBox.setStylePrimaryName("my-TextEdit");
+ textBox.addFocusListener(new FocusListener() {
+ public void onFocus(Widget sender)
+ {
+ }
+
+ public void onLostFocus(Widget sender)
+ {
+ focusPanel.clear();
+ for (Widget widget : children)
+ {
+ focusPanel.add(widget);
+ }
+ }
+ });
+
+ focusPanel.clear();
+ focusPanel.add(textBox);
+ textBox.setFocus(true);
+ }
+ }
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/BrowsePanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/BrowsePanel.java
new file mode 100644
index 000000000..5c628c6f0
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/BrowsePanel.java
@@ -0,0 +1,153 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.*;
+import com.google.gwt.user.client.ui.*;
+import com.google.gwt.http.client.*;
+
+public class BrowsePanel extends Composite {
+
+ private PGFWrapper pgf;
+ private HTML sourceView;
+ private SuggestBox searchBox;
+ private CompletionOracle oracle;
+ private List<String> identifiers = null;
+
+ public BrowsePanel(PGFWrapper pgf) {
+ this.pgf = pgf;
+
+ oracle = new CompletionOracle();
+
+ HorizontalPanel browsePanel = new HorizontalPanel();
+ browsePanel.add(createSearchPanel(oracle));
+ browsePanel.add(createSourcePanel());
+ browsePanel.setCellWidth(sourceView,"100%");
+
+ initWidget(browsePanel);
+ setStylePrimaryName("my-BrowsePanel");
+
+ pgf.addSettingsListener(new MySettingsListener(pgf));
+ }
+
+ public native void onActivate() /*-{
+ $doc.browsePanel = this;
+ $doc.callBrowse = @org.grammaticalframework.ui.gwt.client.BrowsePanel::callBrowse(Lorg/grammaticalframework/ui/gwt/client/BrowsePanel;Ljava/lang/String;);
+ }-*/;
+
+ protected Widget createSearchPanel(CompletionOracle oracle) {
+ searchBox = new SuggestBox(oracle);
+ searchBox.setLimit(10);
+ searchBox.addKeyboardListener(new KeyboardListenerAdapter() {
+ public void onKeyUp (Widget sender, char keyCode, int modifiers) {
+ if (keyCode == KEY_ENTER) {
+ browse(searchBox.getText());
+ }
+ }
+ });
+
+ DecoratorPanel decorator = new DecoratorPanel();
+ VerticalPanel vPanel = new VerticalPanel();
+ vPanel.add(new Label("Search"));
+ vPanel.add(searchBox);
+ decorator.add(vPanel);
+ return decorator;
+ }
+
+ private static void callBrowse(BrowsePanel panel, String id) {
+ panel.browse(id);
+ }
+
+ protected void browse(String id) {
+ pgf.browse(id, "javascript:document.callBrowse(document.browsePanel,'$ID')",
+ "my-identifierLink",
+ new RequestCallback() {
+ public void onResponseReceived(Request request, Response response) {
+ sourceView.setHTML(response.getText());
+ }
+
+ public void onError(Request request, java.lang.Throwable exception) {
+ // errorHandler.onError(e);
+ }
+ });
+ }
+
+ protected Widget createSourcePanel() {
+ sourceView = new HTML();
+ return sourceView;
+ }
+
+ protected class CompletionOracle extends SuggestOracle {
+
+ public CompletionOracle() {
+ }
+
+ public void requestSuggestions(SuggestOracle.Request request, SuggestOracle.Callback callback) {
+ List<CompletionSuggestion> list = new ArrayList();
+
+ int index = Collections.binarySearch(identifiers, request.getQuery());
+ index = (index >= 0) ? index : -(index+1);
+
+ for (; index < identifiers.size(); index++) {
+ String id = identifiers.get(index);
+
+ if (id.startsWith(request.getQuery())) {
+ list.add(new CompletionSuggestion(id));
+ }
+ else
+ break;
+
+ if (list.size() > request.getLimit())
+ break;
+ }
+
+ callback.onSuggestionsReady(request, new SuggestOracle.Response(list));
+ }
+ }
+
+ protected static class CompletionSuggestion implements SuggestOracle.Suggestion {
+ private String string;
+
+ public CompletionSuggestion(String string) {
+ this.string = string;
+ }
+
+ public String getDisplayString() {
+ return string;
+ }
+
+ public String getReplacementString() {
+ return string;
+ }
+ }
+
+ protected class MySettingsListener implements PGFWrapper.SettingsListener {
+
+ private PGFWrapper pgf;
+
+ public MySettingsListener(PGFWrapper pgf) {
+ this.pgf = pgf;
+ }
+
+ public void onAvailableGrammarsChanged() { }
+ public void onSelectedGrammarChanged()
+ {
+ List<String> ids = new ArrayList();
+
+ for (int i = 0; i < pgf.getCategories().length(); i++) {
+ ids.add(pgf.getCategories().get(i));
+ }
+ for (int i = 0; i < pgf.getFunctions().length(); i++) {
+ ids.add(pgf.getFunctions().get(i));
+ }
+
+ Collections.sort(ids);
+
+ identifiers = ids;
+ sourceView.setText("");
+ searchBox.setText("");
+ }
+ public void onInputLanguageChanged() { }
+ public void onOutputLanguageChanged() { }
+ public void onStartCategoryChanged() { }
+ public void onSettingsError(String msg, Throwable e) { }
+ }
+} \ No newline at end of file
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/CompletionOracle.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/CompletionOracle.java
new file mode 100644
index 000000000..0e78deb1b
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/CompletionOracle.java
@@ -0,0 +1,144 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.gwt.user.client.ui.SuggestOracle;
+
+public class CompletionOracle extends SuggestOracle {
+
+ private static final int LIMIT_SCALE_FACTOR = 4;
+
+ private PGFWrapper pgf;
+
+ private ErrorHandler errorHandler;
+
+ private JSONRequest jsonRequest = null;
+
+ private String oldQuery = null;
+
+ private List<CompletionSuggestion> oldSuggestions = Collections.emptyList();
+
+
+ public CompletionOracle (PGFWrapper pgf) {
+ this(pgf, null);
+ }
+
+ public CompletionOracle (PGFWrapper pgf, ErrorHandler errorHandler) {
+ this.pgf = pgf;
+ this.errorHandler = errorHandler;
+ pgf.addSettingsListener(new PGFWrapper.SettingsListener() {
+ public void onAvailableGrammarsChanged() { clearState(); }
+ public void onSelectedGrammarChanged() { clearState(); }
+ public void onInputLanguageChanged() { clearState(); }
+ public void onOutputLanguageChanged() { clearState(); }
+ public void onStartCategoryChanged() { clearState(); }
+ public void onSettingsError(String msg, Throwable e) { clearState(); }
+ });
+ }
+
+ private void clearState () {
+ this.oldQuery = null;
+ this.oldSuggestions = Collections.emptyList();
+ if (jsonRequest != null) {
+ jsonRequest.cancel();
+ jsonRequest = null;
+ }
+ }
+
+ public void setErrorHandler(ErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ public static interface ErrorHandler {
+ public void onError(Throwable e);
+ }
+
+ public static class CompletionSuggestion implements SuggestOracle.Suggestion {
+ private String string;
+ public CompletionSuggestion(String string) {
+ this.string = string;
+ }
+
+ public String getDisplayString() {
+ return string;
+ }
+
+ public String getReplacementString() {
+ return string;
+ }
+ }
+
+ public void requestSuggestions(SuggestOracle.Request request, SuggestOracle.Callback callback) {
+ // Only allow a single completion request at a time
+ if (jsonRequest != null) {
+ jsonRequest.cancel();
+ jsonRequest = null;
+ }
+
+ List<CompletionSuggestion> suggestions = filterOldSuggestions(request);
+ if (suggestions != null) {
+ suggestionsReady(request, callback, suggestions);
+ } else {
+ retrieveSuggestions(request, callback);
+ }
+ }
+
+ /** Filters old suggestions and checks if we still have enough suggestions. */
+ private List<CompletionSuggestion> filterOldSuggestions(SuggestOracle.Request request) {
+ String query = request.getQuery();
+ if (query.length() > 0 && oldQuery != null && query.startsWith(oldQuery)) {
+ // If the prefix had no completions, there is no way that the current input will.
+ if (oldSuggestions.isEmpty()) {
+ return Collections.emptyList();
+ }
+ // If the new input since the previous query ends in whitespace,
+ // always get completions from the server,
+ // since the old suggestions won't include the next word.
+ if (query.indexOf(' ', oldQuery.length()) != -1) {
+ return null;
+ }
+ List<CompletionSuggestion> suggestions = new ArrayList<CompletionSuggestion>();
+ for (CompletionSuggestion c : oldSuggestions) {
+ if (c.getReplacementString().startsWith(query)) {
+ suggestions.add(c);
+ }
+ }
+ if (suggestions.size() >= request.getLimit() || oldSuggestions.size() < request.getLimit()) {
+ return suggestions;
+ }
+ }
+ return null;
+ }
+
+ private void retrieveSuggestions(final SuggestOracle.Request request, final SuggestOracle.Callback callback) {
+ // hack: first report no completions, to hide suggestions until we get the new completions
+ callback.onSuggestionsReady(request, new SuggestOracle.Response(Collections.<CompletionSuggestion>emptyList()));
+
+ jsonRequest = pgf.complete(request.getQuery(), LIMIT_SCALE_FACTOR * request.getLimit(),
+ new PGF.CompleteCallback() {
+ public void onResult(PGF.Completions completions) {
+ jsonRequest = null;
+ List<CompletionSuggestion> suggestions = new ArrayList<CompletionSuggestion>();
+ for (PGF.Completion completion : completions.iterable()) {
+ suggestions.add(new CompletionSuggestion(completion.getText()));
+ }
+ suggestionsReady(request, callback, suggestions);
+ }
+
+ public void onError(Throwable e) {
+ errorHandler.onError(e);
+ }
+
+ });
+ }
+
+ private void suggestionsReady(SuggestOracle.Request request, SuggestOracle.Callback callback, List<CompletionSuggestion> suggestions) {
+ this.oldQuery = request.getQuery();
+ this.oldSuggestions = suggestions;
+ suggestions = suggestions.size() <= request.getLimit() ? suggestions : SubList.makeSubList(suggestions, 0, request.getLimit());
+ callback.onSuggestionsReady(request, new SuggestOracle.Response(suggestions));
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java
new file mode 100644
index 000000000..2fa43b619
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java
@@ -0,0 +1,125 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.core.client.*;
+import com.google.gwt.user.client.*;
+import com.google.gwt.user.client.ui.*;
+
+
+public class EditorApp implements EntryPoint {
+
+ private MenuBar createCommandsMenu(final AbstractSyntaxController absController)
+ {
+ // Create the commands menu
+ MenuBar menu = new MenuBar(true);
+ menu.addStyleName("my-CommandsMenu");
+ menu.setAutoOpen(true);
+ menu.setAnimationEnabled(true);
+
+ menu.addItem(new MenuItem("Undo", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Redo", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Cut", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Copy", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Paste", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Delete", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Refine", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Replace", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Wrap", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Parse", new Command() {
+ public void execute() {
+ absController.edit();
+ }
+ }));
+ menu.addItem(new MenuItem("Refine the node at random", new Command() {
+ public void execute() {
+ }
+ }));
+ menu.addItem(new MenuItem("Refine the tree at random", new Command() {
+ public void execute() {
+ }
+ }));
+
+ return menu;
+ }
+
+ private void populate(AbstractSyntaxController absController)
+ {
+ TreeItem sentenceItem = absController.addItem("Is : Phrase");
+ TreeItem item1 = absController.addItem(sentenceItem,"Det : ItemDet");
+ TreeItem item2 = absController.addItem(item1,"This : Item");
+ absController.addWord(item2,"this");
+ TreeItem item3 = absController.addItem(item1,"Cheese : Kind");
+ absController.addWord(item3,"cheese");
+ absController.addWord(item2,"and");
+ absController.addWord(item2,"only");
+ absController.addWord(item2,"this");
+ absController.addWord(sentenceItem,"is");
+ TreeItem item4 = absController.addItem(sentenceItem,"Expensive : Quality");
+ absController.addWord(item4,"expensive");
+ }
+
+ public void onModuleLoad() {
+ Tree abstractTree = new Tree();
+ abstractTree.addStyleName("my-AbstractTree");
+
+ FlowPanel textPanel = new FlowPanel();
+
+ ListBox choiceListBox = new ListBox();
+ choiceListBox.setVisibleItemCount(10);
+ choiceListBox.addStyleName("my-ChoiceListBox");
+
+ AbstractSyntaxController absController = new AbstractSyntaxController(abstractTree, textPanel);
+
+ VerticalSplitPanel vSplit = new VerticalSplitPanel();
+ vSplit.setSize("800px", "500px");
+ vSplit.setSplitPosition("52%");
+
+ HorizontalSplitPanel hSplit1 = new HorizontalSplitPanel();
+ hSplit1.setSplitPosition("22%");
+ hSplit1.setLeftWidget(new ScrollPanel(abstractTree));
+ hSplit1.setRightWidget(textPanel);
+ vSplit.setTopWidget(hSplit1);
+
+ HorizontalSplitPanel hSplit2 = new HorizontalSplitPanel();
+ hSplit2.setSplitPosition("22%");
+ hSplit2.setLeftWidget(createCommandsMenu(absController));
+ hSplit2.setRightWidget(choiceListBox);
+ vSplit.setBottomWidget(hSplit2);
+
+ populate(absController);
+
+ // Wrap the split panel in a decorator panel
+ DecoratorPanel decPanel = new DecoratorPanel();
+ decPanel.addStyleName("my-EditorPanel");
+ decPanel.setWidget(vSplit);
+
+ RootPanel.get().add(decPanel);
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeApp.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeApp.java
new file mode 100644
index 000000000..c54bb4ddb
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeApp.java
@@ -0,0 +1,268 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.List;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.client.*;
+import com.google.gwt.user.client.ui.*;
+
+
+public class FridgeApp implements EntryPoint {
+
+ protected static final String pgfBaseURL = "/grammars";
+
+ protected PGFWrapper pgf;
+
+ protected JSONRequest translateRequest = null;
+
+ private FridgeBagPanel bagPanel;
+ private FridgeTextPanel textPanel;
+ protected VerticalPanel outputPanel;
+ protected StatusPopup statusPopup;
+
+ private MagnetFactory magnetFactory;
+
+ //
+ // Text
+ //
+
+ protected void update () {
+ bagPanel.updateBag(getText());
+ translate();
+ }
+
+ //
+ // Translation
+ //
+
+ protected void translate() {
+ outputPanel.clear();
+ outputPanel.addStyleDependentName("working");
+ if (translateRequest != null) {
+ translateRequest.cancel();
+ }
+ translateRequest = pgf.translate(getText(),
+ new PGF.TranslateCallback() {
+ public void onResult (PGF.Translations translations) {
+ outputPanel.removeStyleDependentName("working");
+ for (PGF.TranslationResult tr : translations.iterable()) {
+ if (tr.getTranslations() != null)
+ for (PGF.Translation t : tr.getTranslations().iterable()) {
+ for (PGF.Linearization l : t.getLinearizations().iterable()) {
+ outputPanel.add(createTranslation(l.getTo(), l.getText()));
+ }
+ }
+
+ if (tr.getTypeErrors() != null)
+ for (String error : tr.getTypeErrors()) {
+ SimplePanel panel = new SimplePanel();
+ panel.addStyleName("my-typeError");
+ panel.add(new HTML("<pre>"+error+"</pre>"));
+ outputPanel.add(panel);
+ }
+ }
+ }
+ public void onError (Throwable e) {
+ showError("Translation failed", e);
+ }
+ });
+ }
+
+ protected ClickListener translationClickListener = new ClickListener () {
+ public void onClick(Widget widget) {
+ Magnet magnet = (Magnet)widget;
+ setInputLanguage(magnet.getLanguage()); // FIXME: this causes an unnecessary update()
+ setText(magnet.getText(), magnet.getLanguage());
+ }
+ };
+
+ protected Widget createTranslation(String language, String text) {
+ Magnet magnet = magnetFactory.createUsedMagnet(text, language);
+ magnet.addClickListener(translationClickListener);
+ String lang = pgf.getLanguageCode(language);
+ if (lang != null) {
+ magnet.getElement().setLang(lang);
+ }
+ return magnet;
+ }
+
+ //
+ // Current text
+ //
+
+ public String getText () {
+ return textPanel.getText();
+ }
+
+ public void setText(String text, String language) {
+ textPanel.setText(text, language);
+ }
+
+ private void clear() {
+ textPanel.clear();
+ }
+
+
+ //
+ // Status stuff
+ //
+
+ protected void setStatus(String msg) {
+ statusPopup.setStatus(msg);
+ }
+
+ protected void showError(String msg, Throwable e) {
+ statusPopup.showError(msg, e);
+ }
+
+ protected void clearStatus() {
+ statusPopup.clearStatus();
+ }
+
+ // GUI
+
+ protected Widget createUI() {
+ ClickListener magnetClickListener = new ClickListener () {
+ public void onClick(Widget widget) {
+ Magnet magnet = (Magnet)widget;
+ textPanel.addMagnet(magnet);
+ }
+ };
+ magnetFactory = new MagnetFactory(magnetClickListener);
+
+ textPanel = new FridgeTextPanel(magnetFactory);
+ textPanel.addChangeListener(new ChangeListener() {
+ public void onChange(Widget widget) {
+ update();
+ }
+ });
+ bagPanel = new FridgeBagPanel(pgf, magnetFactory);
+ outputPanel = new TranslationsPanel();
+ SettingsPanel settingsPanel = new SettingsPanel(pgf, true, false);
+
+ final DockPanel mainPanel = new DockPanel();
+ mainPanel.setStyleName("my-FridgeApp");
+ mainPanel.add(textPanel, DockPanel.NORTH);
+ mainPanel.add(settingsPanel, DockPanel.SOUTH);
+ mainPanel.add(bagPanel, DockPanel.CENTER);
+ mainPanel.add(outputPanel, DockPanel.EAST);
+
+ mainPanel.setCellHeight(bagPanel, "100%");
+ mainPanel.setCellWidth(bagPanel, "80%");
+ mainPanel.setCellHeight(outputPanel, "100%");
+ mainPanel.setCellWidth(outputPanel, "20%");
+ mainPanel.setCellVerticalAlignment(bagPanel, HasVerticalAlignment.ALIGN_TOP);
+ mainPanel.setCellHorizontalAlignment(outputPanel, HasHorizontalAlignment.ALIGN_RIGHT);
+ mainPanel.setCellWidth(settingsPanel, "100%");
+
+ Window.addWindowResizeListener(new WindowResizeListener() {
+ public void onWindowResized(int w, int h) {
+ mainPanel.setPixelSize(w, h);
+ }
+ });
+ int w = Window.getClientWidth();
+ int h = Window.getClientHeight();
+ mainPanel.setPixelSize(w, h);
+
+ return mainPanel;
+ }
+
+ private static class TranslationsPanel extends VerticalPanel {
+ public TranslationsPanel () {
+ setStylePrimaryName("my-TranslationsPanel");
+ addStyleDependentName("empty");
+ }
+
+ public void clear () {
+ super.clear();
+ addStyleDependentName("empty");
+ }
+
+ public void add(Widget w) {
+ removeStyleDependentName("empty");
+ super.add(w);
+ }
+
+ }
+
+
+ //
+ // History stuff
+ //
+
+ protected class MyHistoryListener implements HistoryListener {
+ public void onHistoryChanged(String historyToken) {
+ updateSettingsFromHistoryToken();
+ }
+ };
+
+ protected void updateSettingsFromHistoryToken() {
+ updateSettingsFromHistoryToken(History.getToken().split("/"));
+ }
+
+ protected void updateSettingsFromHistoryToken(String[] tokenParts) {
+ if (tokenParts.length >= 1 && tokenParts[0].length() > 0) {
+ setPGFName(tokenParts[0]);
+ }
+ if (tokenParts.length >= 2 && tokenParts[1].length() > 0) {
+ setInputLanguage(tokenParts[1]);
+ }
+ }
+
+ protected void setPGFName (String pgfName) {
+ if (pgfName != null && !pgfName.equals(pgf.getPGFName())) {
+ pgf.setPGFName(pgfName);
+ }
+ }
+
+ protected void setInputLanguage (String inputLanguage) {
+ if (inputLanguage != null && !inputLanguage.equals(pgf.getInputLanguage())) {
+ pgf.setInputLanguage(inputLanguage);
+ }
+ }
+
+ //
+ // Initialization
+ //
+
+ protected class MySettingsListener implements PGFWrapper.SettingsListener {
+ // Will only happen on load
+ public void onAvailableGrammarsChanged() {
+ if (pgf.getPGFName() == null) {
+ List<String> grammars = pgf.getGrammars();
+ if (!grammars.isEmpty()) {
+ pgf.setPGFName(grammars.get(0));
+ }
+ }
+ }
+ public void onSelectedGrammarChanged() {
+ if (pgf.getInputLanguage() == null) {
+ pgf.setInputLanguage(pgf.getUserLanguage());
+ }
+ }
+ public void onInputLanguageChanged() {
+ clear();
+ }
+ public void onOutputLanguageChanged() {
+ update();
+ }
+ public void onStartCategoryChanged() {
+ update();
+ }
+ public void onSettingsError(String msg, Throwable e) {
+ showError(msg,e);
+ }
+ }
+
+ public void onModuleLoad() {
+ statusPopup = new StatusPopup();
+
+ pgf = new PGFWrapper(pgfBaseURL);
+ RootPanel.get().add(createUI());
+ pgf.addSettingsListener(new MySettingsListener());
+ History.addHistoryListener(new MyHistoryListener());
+ updateSettingsFromHistoryToken();
+ pgf.updateAvailableGrammars();
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java
new file mode 100644
index 000000000..525bb968d
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java
@@ -0,0 +1,115 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.LinkedHashSet;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.*;
+
+public class FridgeBagPanel extends Composite {
+
+ private PGFWrapper pgf;
+
+ private MagnetFactory magnetFactory;
+
+ private JSONRequest completeRequest = null;
+
+ private FlowPanel prefixPanel;
+
+ private FlowPanel mainPanel;
+
+ private int maxMagnets = 100;
+
+ private LinkedHashSet<String> prefixes = new LinkedHashSet<String>();
+
+
+ public FridgeBagPanel (PGFWrapper pgf, MagnetFactory magnetFactory) {
+ this.pgf = pgf;
+ this.magnetFactory = magnetFactory;
+ prefixPanel = new FlowPanel();
+ prefixPanel.setStylePrimaryName("my-PrefixPanel");
+ mainPanel = new FlowPanel();
+ VerticalPanel vPanel = new VerticalPanel();
+ vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
+ vPanel.add(prefixPanel);
+ vPanel.add(mainPanel);
+ initWidget(new ScrollPanel(vPanel));
+ setStylePrimaryName("my-FridgeBagPanel");
+ addStyleDependentName("empty");
+ }
+
+ public void updateBag (String text) {
+ updateBag(text, "");
+ }
+
+ public void updateBag (final String text, String prefix) {
+ if (completeRequest != null) {
+ completeRequest.cancel();
+ }
+ final boolean updatePrefixes = prefix.equals("");
+ mainPanel.clear();
+ addStyleDependentName("empty");
+ if (updatePrefixes) { clearPrefixes(); }
+ int limit = updatePrefixes ? 0 : maxMagnets;
+ completeRequest = pgf.complete(text + " " + prefix,
+ limit, new PGF.CompleteCallback() {
+ public void onResult(PGF.Completions completions) {
+ for (PGF.Completion completion : completions.iterable()) {
+ String newText = completion.getText();
+ if (!newText.equals(text + " ")) {
+ String[] words = newText.split("\\s+");
+ if (words.length > 0) {
+ String word = words[words.length - 1];
+ if (word.length() > 0) {
+ if (updatePrefixes) {
+ addPrefix(text, word.substring(0,1));
+ }
+ if (mainPanel.getWidgetCount() < maxMagnets) {
+ Magnet magnet = magnetFactory.createMagnet(word, completion.getFrom());
+ mainPanel.add(magnet);
+ removeStyleDependentName("empty");
+ } else {
+ prefixPanel.setVisible(true);
+ }
+ }
+ }
+ }
+ }
+ }
+ public void onError(Throwable e) {
+ // FIXME: show message to user?
+ GWT.log("Error getting completions.", e);
+ }
+ });
+ }
+
+ protected void clearPrefixes () {
+ prefixes.clear();
+ prefixPanel.clear();
+ prefixPanel.setVisible(false);
+ }
+
+ protected void addPrefix(final String text, final String prefix) {
+ if (prefixes.add(prefix)) {
+ Button prefixButton = new Button(prefix, new ClickListener() {
+ public void onClick(Widget sender) {
+ updateBag(text, prefix);
+ }
+ });
+ prefixButton.setTitle("Show only magnets stating with '" + prefix + "'");
+ prefixPanel.add(prefixButton);
+ }
+ }
+
+
+ /*
+ public void cloneMagnet (Magnet magnet) {
+ int i = getWidgetIndex(magnet);
+ GWT.log("cloneMagnet: " + magnet.getParent(), null);
+ if (i != -1) {
+ GWT.log("cloning", null);
+ insert(magnetFactory.createMagnet(magnet), i);
+ }
+ }
+ */
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeTextPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeTextPanel.java
new file mode 100644
index 000000000..804db509f
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeTextPanel.java
@@ -0,0 +1,113 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.user.client.ui.*;
+
+public class FridgeTextPanel extends Composite {
+
+ private MagnetFactory magnetFactory;
+
+ private FlowPanel mainPanel;
+
+ private ChangeListenerCollection listeners = null;
+
+ public FridgeTextPanel (MagnetFactory magnetFactory) {
+ this.magnetFactory = magnetFactory;
+ mainPanel = new FlowPanel();
+ mainPanel.setStylePrimaryName("magnets");
+ DockPanel wrapper = new DockPanel();
+ wrapper.add(mainPanel, DockPanel.CENTER);
+ Widget buttons = createButtonPanel();
+ wrapper.add(buttons, DockPanel.EAST);
+ wrapper.setCellWidth(mainPanel, "100%");
+ wrapper.setCellWidth(buttons, "6em");
+ wrapper.setHorizontalAlignment(DockPanel.ALIGN_RIGHT);
+ initWidget(wrapper);
+ setStylePrimaryName("my-FridgeTextPanel");
+ }
+
+
+ protected Widget createButtonPanel () {
+ Panel buttons = new VerticalPanel();
+ buttons.setStylePrimaryName("buttons");
+ PushButton deleteLastButton = new PushButton(new Image("se.chalmers.cs.gf.gwt.FridgeApp/delete-last.png"));
+ deleteLastButton.setTitle("Removes the last magnet.");
+ deleteLastButton.addClickListener(new ClickListener () {
+ public void onClick(Widget sender) {
+ deleteLast();
+ }
+ });
+ buttons.add(deleteLastButton);
+ PushButton clearButton = new PushButton("Clear");
+ clearButton.addClickListener(new ClickListener () {
+ public void onClick(Widget sender) {
+ clear();
+ }
+ });
+ clearButton.setTitle("Removes all magnets.");
+ buttons.add(clearButton);
+ return buttons;
+ }
+
+ public void setEngaged(boolean engaged) {
+ if (engaged) {
+ addStyleDependentName("engage");
+ } else {
+ removeStyleDependentName("engage");
+ }
+ }
+
+ public String getText () {
+ StringBuilder sb = new StringBuilder();
+ for (Widget w : mainPanel) {
+ if (w instanceof Magnet) {
+ String word = ((Magnet)w).getText();
+ if (sb.length() > 0) {
+ sb.append(' ');
+ }
+ sb.append(word);
+ }
+ }
+ return sb.toString();
+ }
+
+ public void setText (String text, String language) {
+ if (!text.equals(getText())) {
+ mainPanel.clear();
+ for (String word : text.split("\\s+")) {
+ if (word.length() > 0) {
+ mainPanel.add(magnetFactory.createUsedMagnet(word, language));
+ }
+ }
+ fireChange();
+ }
+ }
+
+ public void clear () {
+ mainPanel.clear();
+ fireChange();
+ }
+
+ public void addMagnet (Magnet magnet) {
+ mainPanel.add(magnetFactory.createUsedMagnet(magnet));
+ fireChange();
+ }
+
+ public void deleteLast() {
+ int c = mainPanel.getWidgetCount();
+ if (c > 0) {
+ mainPanel.remove(c-1);
+ fireChange();
+ }
+ }
+
+ protected void fireChange() {
+ listeners.fireChange(this);
+ }
+
+ public void addChangeListener(ChangeListener listener) {
+ if (listeners == null) {
+ listeners = new ChangeListenerCollection();
+ }
+ listeners.add(listener);
+ }
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/IterableJsArray.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/IterableJsArray.java
new file mode 100644
index 000000000..b1d501ddb
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/IterableJsArray.java
@@ -0,0 +1,39 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArray;
+
+public class IterableJsArray<T extends JavaScriptObject> extends JsArray<T> {
+
+ protected IterableJsArray() {}
+
+ public final boolean isEmpty() {
+ return length() == 0;
+ }
+
+ public final Iterable<T> iterable() {
+ return new Iterable<T>() {
+ public Iterator<T> iterator() {
+ return new Iterator<T>() {
+ private int i = 0;
+ public boolean hasNext() {
+ return i < length();
+ }
+ public T next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ return get(i++);
+ }
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONCallback.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONCallback.java
new file mode 100644
index 000000000..485173b49
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONCallback.java
@@ -0,0 +1,8 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+public interface JSONCallback<T extends JavaScriptObject> {
+ public void onResult (T result) ;
+ public void onError (Throwable e) ;
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequest.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequest.java
new file mode 100644
index 000000000..15da7caf0
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequest.java
@@ -0,0 +1,19 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.http.client.*;
+
+public class JSONRequest {
+
+ private Request httpRequest;
+
+ JSONRequest (Request httpRequest) {
+ this.httpRequest = httpRequest;
+ }
+
+ public void cancel() {
+ if (httpRequest != null) {
+ httpRequest.cancel();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java
new file mode 100644
index 000000000..1e4fc8e4a
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java
@@ -0,0 +1,79 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestBuilder;
+import com.google.gwt.http.client.RequestCallback;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.http.client.Response;
+import com.google.gwt.http.client.URL;
+
+import java.util.List;
+
+public class JSONRequestBuilder {
+
+ public static class Arg {
+ public final String name;
+ public final String value;
+ public Arg (String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+ public Arg (String name, int value) {
+ this(name, Integer.toString(value));
+ }
+ }
+
+ public static <T extends JavaScriptObject> JSONRequest sendRequest (String base, List<Arg> vars, final JSONCallback<T> callback) {
+ String url = getQueryURL(base,vars);
+ RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
+ builder.setTimeoutMillis(30000);
+ builder.setHeader("Accept","text/plain, text/html;q=0.5, */*;q=0.1");
+ Request request = null;
+
+ try {
+ request = builder.sendRequest(null, new RequestCallback() {
+ public void onError(Request request, Throwable e) {
+ callback.onError(e);
+ }
+
+ public void onResponseReceived(Request request, Response response) {
+ if (200 == response.getStatusCode()) {
+ callback.onResult(JSONRequestBuilder.<T>eval(response.getText()));
+ } else {
+ RequestException e = new RequestException("Response not OK: " + response.getStatusCode() + ". " + response.getText());
+ callback.onError(e);
+ }
+ }
+ });
+ } catch (RequestException e) {
+ callback.onError(e);
+ }
+
+ return new JSONRequest(request);
+ }
+
+ private static native <T extends JavaScriptObject> T eval(String json) /*-{
+ return eval('(' + json + ')');
+ }-*/;
+
+ public static String getQueryURL(String base, List<Arg> args) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(base);
+ sb.append("?");
+ if (args != null) {
+ for (Arg arg : args) {
+ if (arg.value != null) {
+ if (sb.length() > 0) {
+ sb.append("&");
+ }
+ sb.append(URL.encodeComponent(arg.name));
+ sb.append("=");
+ sb.append(URL.encodeComponent(arg.value));
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/Magnet.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/Magnet.java
new file mode 100644
index 000000000..687cfee60
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/Magnet.java
@@ -0,0 +1,19 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.user.client.ui.HTML;
+
+public class Magnet extends HTML {
+
+ private String language;
+
+ public Magnet (String text, String language) {
+ this.language = language;
+ setHTML(text);
+ setStylePrimaryName("my-Magnet");
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MagnetFactory.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MagnetFactory.java
new file mode 100644
index 000000000..5bb780456
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MagnetFactory.java
@@ -0,0 +1,31 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.user.client.ui.*;
+
+public class MagnetFactory {
+
+ private ClickListener clickListener;
+
+ public MagnetFactory (ClickListener clickListener) {
+ this.clickListener = clickListener;
+ }
+
+ public Magnet createUsedMagnet(Magnet magnet) {
+ return createUsedMagnet(magnet.getText(), magnet.getLanguage());
+ }
+
+ public Magnet createUsedMagnet(String text, String language) {
+ return new Magnet(text, language);
+ }
+
+ public Magnet createMagnet(Magnet magnet) {
+ return createMagnet(magnet.getText(), magnet.getLanguage());
+ }
+
+ public Magnet createMagnet(String text, String language) {
+ Magnet magnet = new Magnet(text, language);
+ magnet.addClickListener(clickListener);
+ return magnet;
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MorphoApp.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MorphoApp.java
new file mode 100644
index 000000000..44e7bacb6
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MorphoApp.java
@@ -0,0 +1,63 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.*;
+
+import com.google.gwt.core.client.*;
+import com.google.gwt.user.client.ui.*;
+import com.google.gwt.core.client.JavaScriptObject;
+
+public class MorphoApp implements EntryPoint {
+ private TextBox lemmaBox = new TextBox();
+ private Button submitButton = new Button("Submit");
+ private Grid outputGrid = new Grid(2,0);
+
+ public void onModuleLoad() {
+ HorizontalPanel inputPanel = new HorizontalPanel();
+ inputPanel.add(lemmaBox);
+ inputPanel.add(submitButton);
+
+ submitButton.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+
+ String url = "http://localhost:41296/morpho/morpho.fcgi/eval";
+ List<JSONRequestBuilder.Arg> args = new ArrayList<JSONRequestBuilder.Arg>();
+ args.add(new JSONRequestBuilder.Arg("term", lemmaBox.getText()));
+
+ JSONRequestBuilder.sendRequest(url, args, new TableCallback() {
+ public void onResult (IterableJsArray<InflectionForm> table)
+ {
+ outputGrid.resize(table.length(),2);
+ int row = 0;
+ for (InflectionForm form : table.iterable()) {
+ outputGrid.setText(row,0,form.getName());
+ outputGrid.setText(row,1,form.getValue());
+ row++;
+ }
+ }
+
+ public void onError (Throwable e)
+ {
+ outputGrid.resize(1,1);
+ outputGrid.setText(0,0,e.toString());
+ }
+ });
+ }
+ });
+
+
+ VerticalPanel mainPanel = new VerticalPanel();
+ mainPanel.add(inputPanel);
+ mainPanel.add(outputGrid);
+ RootPanel.get().add(mainPanel);
+ }
+
+ public interface TableCallback extends JSONCallback<IterableJsArray<InflectionForm>> { }
+
+ public static class InflectionForm extends JavaScriptObject {
+ protected InflectionForm() { }
+
+ public final native String getName() /*-{ return this.name; }-*/;
+
+ public final native String getValue() /*-{ return this.value; }-*/;
+ }
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MyListBox.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MyListBox.java
new file mode 100644
index 000000000..ce716b91d
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MyListBox.java
@@ -0,0 +1,40 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.Collection;
+
+import com.google.gwt.user.client.ui.ListBox;
+
+public class MyListBox extends ListBox {
+
+ public MyListBox () { }
+
+ public void clearSelection () {
+ setSelectedIndex(-1);
+ }
+
+ public String getSelectedValue() {
+ int i = getSelectedIndex();
+ return i == -1 ? null : getValue(i);
+ }
+
+ public void setSelectedValue(String value) {
+ if (value == null) {
+ clearSelection();
+ } else {
+ int c = getItemCount();
+ for (int i = 0; i < c; i++) {
+ if (getValue(i).equals(value)) {
+ setSelectedIndex(i);
+ return;
+ }
+ }
+ }
+ }
+
+ public void addItems(Collection<String> items) {
+ for (String item : items) {
+ addItem(item);
+ }
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java
new file mode 100644
index 000000000..41e77539c
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java
@@ -0,0 +1,194 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import org.grammaticalframework.ui.gwt.client.JSONRequestBuilder.Arg;
+
+import java.util.*;
+import com.google.gwt.core.client.*;
+import com.google.gwt.http.client.*;
+
+public class PGF {
+
+ public PGF () {
+ }
+
+ /* Grammar */
+
+ public JSONRequest grammar (String pgfURL, final GrammarCallback callback) {
+ return sendGrammarRequest(pgfURL, "grammar", new ArrayList<Arg>(), callback);
+ }
+
+ public interface GrammarCallback extends JSONCallback<Grammar> { }
+
+ public static class Grammar extends JavaScriptObject {
+ protected Grammar() { }
+
+ public final native String getName() /*-{ return this.name; }-*/;
+
+ public final native String getUserLanguage() /*-{ return this.userLanguage; }-*/;
+
+ public final native IterableJsArray<Language> getLanguages() /*-{ return this.languages; }-*/;
+
+ public final native JsArrayString getCategories() /*-{ return this.categories; }-*/;
+
+ public final native JsArrayString getFunctions() /*-{ return this.functions; }-*/;
+ }
+
+ public static class Language extends JavaScriptObject {
+ protected Language() { }
+
+ public final native String getName() /*-{ return this.name; }-*/;
+ public final native String getLanguageCode() /*-{ return this.languageCode; }-*/;
+ public final native boolean canParse() /*-{ return this.canParse; }-*/;
+ }
+
+ /* Translation */
+
+ public JSONRequest translate (String pgfURL, String input, String fromLang, String cat, String toLang,
+ final TranslateCallback callback) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("input", input));
+ args.add(new Arg("from", fromLang));
+ args.add(new Arg("cat", cat));
+ args.add(new Arg("to", toLang));
+ return sendGrammarRequest(pgfURL, "translate", args, callback);
+ }
+
+ public interface TranslateCallback extends JSONCallback<Translations> { }
+
+ public static class Translations extends IterableJsArray<TranslationResult> {
+ protected Translations() { }
+ }
+
+ public static class TranslationResult extends JavaScriptObject {
+ protected TranslationResult() { }
+
+ public final native String getFrom() /*-{ return this.from; }-*/;
+ public final native String getBracketedString() /*-{ return this.brackets; }-*/;
+ public final native IterableJsArray<Translation> getTranslations() /*-{ return this.translations; }-*/;
+ public final native String[] getTypeErrors() /*-{ return this.typeErrors; }-*/;
+ }
+
+ public static class Translation extends JavaScriptObject {
+ protected Translation() { }
+
+ public final native String getTree() /*-{ return this.tree; }-*/;
+ public final native Linearizations getLinearizations() /*-{ return this.linearizations; }-*/;
+ }
+
+ public static class Linearizations extends IterableJsArray<Linearization> {
+ protected Linearizations() { }
+ }
+
+ public static class Linearization extends JavaScriptObject {
+ protected Linearization() { }
+
+ public final native String getTo() /*-{ return this.to; }-*/;
+ public final native String getText() /*-{ return this.text; }-*/;
+ }
+
+ /* Completion */
+
+ /**
+ * Get suggestions for completing the input.
+ * @param limit The number of suggestions to get.
+ * If -1 is passed, all available suggestions are retrieved.
+ */
+ public JSONRequest complete (String pgfURL, String input, String fromLang, String cat, int limit, final CompleteCallback callback) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("input", input));
+ args.add(new Arg("from", fromLang));
+ args.add(new Arg("cat", cat));
+ if (limit > 0) {
+ args.add(new Arg("limit", limit));
+ }
+ return sendGrammarRequest(pgfURL, "complete", args, callback);
+ }
+
+ public interface CompleteCallback extends JSONCallback<Completions> { }
+
+ public static class Completions extends IterableJsArray<Completion> {
+ protected Completions() { }
+ }
+
+ public static class Completion extends JavaScriptObject {
+ protected Completion() { }
+
+ public final native String getFrom() /*-{ return this.from; }-*/;
+ public final native String getText() /*-{ return this.text; }-*/;
+ }
+
+ /* Parsing */
+
+ public JSONRequest parse (String pgfURL, String input, String fromLang, String cat, final ParseCallback callback) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("input", input));
+ args.add(new Arg("from", fromLang));
+ args.add(new Arg("cat", cat));
+ return sendGrammarRequest(pgfURL, "parse", args, callback);
+ }
+
+ public interface ParseCallback extends JSONCallback<ParseResults> { }
+
+ public static class ParseResults extends IterableJsArray<ParseResult> {
+ protected ParseResults() { }
+ }
+
+ public static class ParseResult extends JavaScriptObject {
+ protected ParseResult() { }
+
+ public final native String getFrom() /*-{ return this.from; }-*/;
+ public final native String getBracketedString() /*-{ return this.brackets; }-*/;
+ public final native String[] getTrees() /*-{ return this.trees; }-*/;
+ public final native String[] getTypeErrors() /*-{ return this.typeErrors; }-*/;
+ }
+
+ public String graphvizAbstractTree(String pgfURL, String abstractTree) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("command", "abstrtree"));
+ args.add(new Arg("tree", abstractTree));
+ return JSONRequestBuilder.getQueryURL(pgfURL,args);
+ }
+
+ public String graphvizParseTree(String pgfURL, String abstractTree, String lang) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("command", "parsetree"));
+ args.add(new Arg("tree", abstractTree));
+ args.add(new Arg("from", lang));
+ return JSONRequestBuilder.getQueryURL(pgfURL,args);
+ }
+
+ public String graphvizAlignment(String pgfURL, String abstractTree) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("command", "alignment"));
+ args.add(new Arg("tree", abstractTree));
+ return JSONRequestBuilder.getQueryURL(pgfURL,args);
+ }
+
+ public Request browse(String pgfURL, String id, String href, String cssClass, RequestCallback callback) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("command", "browse"));
+ args.add(new Arg("id", id));
+ args.add(new Arg("href", href));
+ args.add(new Arg("css-class", cssClass));
+
+ Request request = null;
+ try {
+ RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
+ JSONRequestBuilder.getQueryURL(pgfURL,args));
+ builder.setCallback(callback);
+ request = builder.send();
+ } catch (RequestException ex) {
+ callback.onError(request, ex);
+ }
+
+ return request;
+ }
+
+ /* Common */
+
+ public <T extends JavaScriptObject> JSONRequest sendGrammarRequest(String pgfURL, String resource, List<Arg> args, final JSONCallback<T> callback) {
+ args.add(new Arg("command", resource));
+ return JSONRequestBuilder.sendRequest(pgfURL, args, callback);
+ }
+
+} \ No newline at end of file
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java
new file mode 100644
index 000000000..4896dc151
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java
@@ -0,0 +1,323 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import com.google.gwt.http.client.*;
+import com.google.gwt.xml.client.*;
+import com.google.gwt.core.client.*;
+
+public class PGFWrapper {
+
+ private String baseURL;
+
+ private String grammarURL;
+
+ private String pgfName = null;
+
+ private PGF pgf;
+
+ private String inputLanguage = null;
+
+ private String outputLanguage = null;
+
+ private String cat = null;
+
+ // Cached info about the available grammars
+
+ private List<String> grammars;
+
+ // Cached info about the currently selected grammar
+
+ private String userLanguage;
+
+ private LinkedHashMap<String,PGF.Language> languages;
+
+ private List<String> parseableLanguages;
+
+ private JsArrayString categories;
+ private JsArrayString functions;
+
+ // Event listeners
+
+ private List<SettingsListener> listeners = new LinkedList<SettingsListener>();
+
+
+ public PGFWrapper() {
+ this.baseURL = null;
+ this.pgf = new PGF();
+ }
+
+ public PGFWrapper(String baseURL) {
+ this.baseURL = baseURL;
+ this.pgf = new PGF();
+ }
+
+ public void updateAvailableGrammars() {
+ String url = baseURL+"/grammars.xml";
+ RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
+ try
+ {
+ builder.sendRequest(null, new RequestCallback() {
+ public void onResponseReceived(Request request, Response response)
+ {
+ if (200 == response.getStatusCode())
+ {
+ grammars = new ArrayList<String>();
+ try
+ {
+ Document grammarsDoc = XMLParser.parse(response.getText());
+
+ NodeList grammarsList = grammarsDoc.getElementsByTagName("grammar");
+ for (int i = 0; i < grammarsList.getLength(); i++)
+ {
+ Node grammarNode = grammarsList.item(i);
+ grammars.add(((Element)grammarNode).getAttribute("name"));
+ }
+ }
+ catch (DOMException e)
+ {
+ fireSettingsError("Could not parse XML document.", e);
+ }
+ fireAvailableGrammarsChanged();
+ }
+ else
+ {
+ fireSettingsError("Error getting grammar list", null);
+ }
+ }
+
+ public void onError(Request request, Throwable e)
+ {
+ fireSettingsError("Error getting grammar list", e);
+ }
+ });
+ }
+ catch (RequestException e)
+ {
+ fireSettingsError("Couldn't connect to server", e);
+ }
+ }
+
+ protected void updateSelectedGrammar () {
+ clearCachedInfo();
+ pgf.grammar(grammarURL, new PGF.GrammarCallback() {
+ public void onResult(PGF.Grammar grammar) {
+ userLanguage = grammar.getUserLanguage();
+ languages = new LinkedHashMap<String,PGF.Language>();
+ parseableLanguages = new ArrayList<String>();
+ for (PGF.Language l : grammar.getLanguages().iterable()) {
+ String name = l.getName();
+ languages.put(name, l);
+ if (l.canParse()) {
+ parseableLanguages.add(name);
+ }
+ }
+
+ categories = grammar.getCategories();
+ functions = grammar.getFunctions();
+
+ fireSelectedGrammarChanged();
+ }
+
+ public void onError (Throwable e) {
+ fireSettingsError("Error getting language information", e);
+ }
+ });
+ }
+
+ //
+ // PGF functionality
+ //
+
+ public JSONRequest translate (String input, final PGF.TranslateCallback callback) {
+ return pgf.translate(grammarURL, input, inputLanguage, cat, outputLanguage, callback);
+ }
+
+ public JSONRequest complete (String input, int limit, final PGF.CompleteCallback callback) {
+ return pgf.complete(grammarURL, input, inputLanguage, cat, limit, callback);
+ }
+
+ public JSONRequest parse (String input, final PGF.ParseCallback callback) {
+ return pgf.parse(grammarURL, input, inputLanguage, cat, callback);
+ }
+
+ public String graphvizAbstractTree(String abstractTree) {
+ return pgf.graphvizAbstractTree(grammarURL,abstractTree);
+ }
+
+ public String graphvizParseTree(String abstractTree, String lang) {
+ return pgf.graphvizParseTree(grammarURL,abstractTree,lang);
+ }
+
+ public String graphvizAlignment(String abstractTree) {
+ return pgf.graphvizAlignment(grammarURL,abstractTree);
+ }
+
+ public Request browse(String id, String href, String cssClass, RequestCallback callback) {
+ return pgf.browse(grammarURL, id, href, cssClass, callback);
+ }
+
+ //
+ // Settings
+ //
+
+ public String getPGFName() {
+ return pgfName;
+ }
+
+ public void setPGFName(String pgfName) {
+ this.pgfName = pgfName;
+ this.grammarURL = baseURL + "/" + pgfName;
+ this.inputLanguage = null;
+ this.outputLanguage = null;
+ this.cat = null;
+ updateSelectedGrammar();
+ }
+
+ public String getGrammarURL() {
+ return grammarURL;
+ }
+
+ public void setGrammarURL(String grammarURL) {
+ this.pgfName = null;
+ this.grammarURL = grammarURL;
+ this.inputLanguage = null;
+ this.outputLanguage = null;
+ this.cat = null;
+ updateSelectedGrammar();
+ }
+
+ public String getInputLanguage() {
+ return inputLanguage;
+ }
+
+ public void setInputLanguage(String inputLanguage) {
+ this.inputLanguage = inputLanguage;
+ fireInputLanguageChanged();
+ }
+
+ public String getOutputLanguage() {
+ return outputLanguage;
+ }
+
+ public void setOutputLanguage(String outputLanguage) {
+ this.outputLanguage = outputLanguage;
+ fireOutputLanguageChanged();
+ }
+
+ public String getStartCategory() {
+ return cat;
+ }
+
+ public void setStartCategory(String cat) {
+ this.cat = cat;
+ fireStartCategoryChanged();
+ }
+
+ public JsArrayString getCategories() {
+ return categories;
+ }
+
+ public JsArrayString getFunctions() {
+ return functions;
+ }
+
+
+ //
+ // Information about the available grammars
+ //
+ public List<String> getGrammars() {
+ return grammars;
+ }
+
+ //
+ // Information about the selected grammar
+ //
+ private void clearCachedInfo () {
+ languages = null;
+ parseableLanguages = null;
+ }
+
+ public String getUserLanguage () {
+ return userLanguage;
+ }
+
+ public String getLanguageCode (String language) {
+ PGF.Language l = languages.get(language);
+ return l == null ? null : l.getLanguageCode();
+ }
+
+ public Collection<String> getParseableLanguages() {
+ return parseableLanguages;
+ }
+
+ public Collection<String> getAllLanguages() {
+ return languages.keySet();
+ }
+
+ //
+ // Listeners
+ //
+
+ public interface SettingsListener {
+ public void onAvailableGrammarsChanged();
+ public void onSelectedGrammarChanged();
+ public void onInputLanguageChanged();
+ public void onOutputLanguageChanged();
+ public void onStartCategoryChanged();
+ public void onSettingsError(String msg, Throwable e);
+ }
+
+ public static class SettingsAdapter implements SettingsListener {
+ public void onAvailableGrammarsChanged() {}
+ public void onSelectedGrammarChanged() {}
+ public void onInputLanguageChanged() {}
+ public void onOutputLanguageChanged() {}
+ public void onStartCategoryChanged() {}
+ public void onSettingsError(String msg, Throwable e) {}
+ }
+
+ public void addSettingsListener(SettingsListener listener) {
+ listeners.add(listener);
+ }
+
+ protected void fireAvailableGrammarsChanged() {
+ for (SettingsListener listener : listeners) {
+ listener.onAvailableGrammarsChanged();
+ }
+ }
+
+ protected void fireSelectedGrammarChanged() {
+ for (SettingsListener listener : listeners) {
+ listener.onSelectedGrammarChanged();
+ }
+ }
+
+ protected void fireInputLanguageChanged() {
+ for (SettingsListener listener : listeners) {
+ listener.onInputLanguageChanged();
+ }
+ }
+
+ protected void fireOutputLanguageChanged() {
+ for (SettingsListener listener : listeners) {
+ listener.onOutputLanguageChanged();
+ }
+ }
+
+ protected void fireStartCategoryChanged() {
+ for (SettingsListener listener : listeners) {
+ listener.onStartCategoryChanged();
+ }
+ }
+
+ protected void fireSettingsError(String msg, Throwable e) {
+ for (SettingsListener listener : listeners) {
+ listener.onSettingsError(msg, e);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SettingsPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SettingsPanel.java
new file mode 100644
index 000000000..3ae14d969
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SettingsPanel.java
@@ -0,0 +1,111 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.user.client.ui.*;
+
+public class SettingsPanel extends Composite {
+
+ private PGFWrapper pgf;
+
+ private MyListBox grammarBox;
+ private MyListBox fromLangBox;
+ private MyListBox toLangBox;
+
+ public SettingsPanel (PGFWrapper pgf) {
+ this(pgf, true, true);
+ }
+
+ public SettingsPanel (PGFWrapper pgf, boolean showPGFName, boolean showOutputLanguage) {
+ this.pgf = pgf;
+
+ HorizontalPanel settingsPanel = new HorizontalPanel();
+ settingsPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
+ settingsPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
+
+ if (showPGFName) {
+ grammarBox = new MyListBox();
+ grammarBox.addChangeListener(new ChangeListener() {
+ public void onChange(Widget sender) {
+ SettingsPanel.this.pgf.setPGFName(grammarBox.getSelectedValue());
+ }
+ });
+ settingsPanel.add(new FormWidget("Grammar:", grammarBox));
+ }
+
+ fromLangBox = new MyListBox();
+ fromLangBox.addChangeListener(new ChangeListener() {
+ public void onChange(Widget sender) {
+ SettingsPanel.this.pgf.setInputLanguage(fromLangBox.getSelectedValue());
+ }
+ });
+ settingsPanel.add(new FormWidget("From:", fromLangBox));
+
+ if (showOutputLanguage) {
+ toLangBox = new MyListBox();
+ toLangBox.addChangeListener(new ChangeListener() {
+ public void onChange(Widget sender) {
+ SettingsPanel.this.pgf.setOutputLanguage(toLangBox.getSelectedValue());
+ }
+ });
+ settingsPanel.add(new FormWidget("To:", toLangBox));
+ }
+
+ initWidget(settingsPanel);
+ setStylePrimaryName("my-SettingsPanel");
+
+ pgf.addSettingsListener(new MySettingsListener());
+ }
+
+ private static class FormWidget extends HorizontalPanel {
+ public FormWidget(String label, Widget w) {
+ setStylePrimaryName(".my-FormWidget");
+ setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
+ add(new Label(label));
+ add(w);
+ }
+ }
+
+ private class MySettingsListener implements PGFWrapper.SettingsListener {
+ public void onAvailableGrammarsChanged() {
+ if (grammarBox != null) {
+ grammarBox.clear();
+ grammarBox.addItems(pgf.getGrammars());
+ }
+ }
+ public void onSelectedGrammarChanged() {
+ if (grammarBox != null) {
+ grammarBox.setSelectedValue(pgf.getPGFName());
+ }
+ if (fromLangBox != null) {
+ fromLangBox.clear();
+ fromLangBox.addItem("Any language", "");
+ fromLangBox.addItems(pgf.getParseableLanguages());
+ String inputLanguage = pgf.getInputLanguage();
+ if (inputLanguage != null) {
+ fromLangBox.setSelectedValue(inputLanguage);
+ }
+ }
+ if (toLangBox != null) {
+ toLangBox.clear();
+ toLangBox.addItem("All languages", "");
+ toLangBox.addItems(pgf.getAllLanguages());
+ String outputLanguage = pgf.getOutputLanguage();
+ if (outputLanguage != null) {
+ fromLangBox.setSelectedValue(outputLanguage);
+ }
+ }
+ }
+ public void onInputLanguageChanged() {
+ if (fromLangBox != null) {
+ fromLangBox.setSelectedValue(pgf.getInputLanguage());
+ }
+ }
+ public void onOutputLanguageChanged() {
+ if (toLangBox != null) {
+ toLangBox.setSelectedValue(pgf.getOutputLanguage());
+ }
+ }
+ public void onStartCategoryChanged() { }
+ public void onSettingsError(String msg, Throwable e) { }
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/StatusPopup.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/StatusPopup.java
new file mode 100644
index 000000000..73ff82e0d
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/StatusPopup.java
@@ -0,0 +1,36 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.PopupPanel;
+
+public class StatusPopup extends PopupPanel {
+
+ private Label label = new Label();
+
+ public StatusPopup () {
+ super(true, true);
+ label = new Label();
+ add(label);
+ }
+
+ public void setStatus(String msg) {
+ removeStyleDependentName("error");
+ label.setText(msg);
+ center();
+ }
+
+ public void showError(String msg, Throwable e) {
+ GWT.log(msg, e);
+ addStyleDependentName("error");
+ label.setText(msg);
+ center();
+ }
+
+ public void clearStatus() {
+ removeStyleDependentName("error");
+ label.setText("");
+ hide();
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SubList.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SubList.java
new file mode 100644
index 000000000..9d3221f39
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SubList.java
@@ -0,0 +1,37 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.AbstractList;
+import java.util.List;
+
+/** Work-around for missing List.subList() method in GWT JRE API emulation. */
+public class SubList<T> extends AbstractList<T> {
+
+ private List<T> list;
+
+ private int fromIndex;
+
+ private int toIndex;
+
+ public SubList(List<T> list, int fromIndex, int toIndex) {
+ this.list = list;
+ this.fromIndex = fromIndex;
+ this.toIndex = toIndex;
+ if (fromIndex < 0 || toIndex > list.size())
+ throw new IndexOutOfBoundsException("Endpoint index value out of range");
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException("Endpoint indices out of order");
+ }
+
+ public T get(int index) {
+ return list.get(fromIndex + index);
+ }
+
+ public int size() {
+ return toIndex - fromIndex;
+ }
+
+ public static <T> SubList<T> makeSubList(List<T> list, int fromIndex, int toIndex) {
+ return new SubList<T>(list, fromIndex, toIndex);
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SuggestPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SuggestPanel.java
new file mode 100644
index 000000000..8e2edf582
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/SuggestPanel.java
@@ -0,0 +1,102 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.*;
+
+public class SuggestPanel extends Composite implements HasText {
+
+ private SuggestBox suggest;
+ private Button submitButton;
+
+ private List<SubmitListener> listeners = new LinkedList<SubmitListener>();
+
+ public SuggestPanel (PGFWrapper pgf) {
+
+ CompletionOracle oracle = new CompletionOracle(pgf, new CompletionOracle.ErrorHandler() {
+ public void onError(Throwable e) {
+ GWT.log("Completion failed", e);
+ }
+ });
+
+ suggest = new SuggestBox(oracle);
+ suggest.setLimit(10);
+ suggest.addKeyboardListener(new KeyboardListenerAdapter() {
+ public void onKeyUp (Widget sender, char keyCode, int modifiers) {
+ if (keyCode == KEY_ENTER) {
+ submit();
+ }
+ }
+ });
+
+ submitButton = new Button("Submit");
+ submitButton.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+ submit();
+ }
+ });
+
+ DockPanel mainPanel = new DockPanel();
+ mainPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
+ mainPanel.add(suggest, DockPanel.CENTER);
+ mainPanel.add(submitButton, DockPanel.EAST);
+
+ initWidget(mainPanel);
+ setStylePrimaryName("my-SuggestPanel");
+
+ }
+
+ public int getLimit() {
+ return suggest.getLimit();
+ }
+
+ public String getText() {
+ return suggest.getText();
+ }
+
+ public String getTitle() {
+ return suggest.getTitle();
+ }
+
+ public void onLoad() {
+ suggest.setFocus(true);
+ }
+
+ public void setButtonText (String text) {
+ submitButton.setText(text);
+ }
+
+ public void setEnabled(boolean enabled) {
+ submitButton.setEnabled(enabled);
+ }
+
+ public void setLimit(int limit) {
+ suggest.setLimit(limit);
+ }
+
+ public void setText (String text) {
+ suggest.setText(text);
+ }
+
+ public void setTitle(String title) {
+ suggest.setTitle(title);
+ }
+
+ public void addSubmitListener(SubmitListener listener) {
+ listeners.add(listener);
+ }
+
+ public void submit() {
+ String text = getText();
+ for (SubmitListener listener : listeners) {
+ listener.onSubmit(text);
+ }
+ }
+
+ public interface SubmitListener {
+ public void onSubmit(String text);
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TranslateApp.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TranslateApp.java
new file mode 100644
index 000000000..5e210a549
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TranslateApp.java
@@ -0,0 +1,386 @@
+package org.grammaticalframework.ui.gwt.client;
+
+import java.util.List;
+
+import com.google.gwt.core.client.*;
+import com.google.gwt.user.client.*;
+import com.google.gwt.user.client.ui.*;
+
+
+public class TranslateApp implements EntryPoint {
+
+ protected static final String pgfBaseURL = "/grammars";
+
+ protected PGFWrapper pgf;
+
+ protected SuggestPanel suggestPanel;
+ protected VerticalPanel outputPanel;
+ protected Widget translatePanel;
+ protected BrowsePanel browsePanel;
+ protected StatusPopup statusPopup;
+
+ //
+ // Text
+ //
+
+ public String getText () {
+ return suggestPanel.getText();
+ }
+
+ protected void update () {
+ translate();
+ }
+
+ //
+ // Translation
+ //
+
+ protected void translate() {
+ outputPanel.clear();
+ outputPanel.addStyleDependentName("working");
+ pgf.translate(getText(),
+ new PGF.TranslateCallback() {
+ public void onResult (PGF.Translations translations) {
+ outputPanel.clear();
+ outputPanel.removeStyleDependentName("working");
+ for (PGF.TranslationResult tr : translations.iterable()) {
+ if (tr.getTranslations() != null)
+ for (PGF.Translation t : tr.getTranslations().iterable()) {
+ HorizontalPanel hPanel = new HorizontalPanel();
+ hPanel.addStyleName("my-translation-frame");
+ VerticalPanel linsPanel = new VerticalPanel();
+ linsPanel.addStyleName("my-translation-bar");
+ hPanel.add(linsPanel);
+ HorizontalPanel btnPanel = new HorizontalPanel();
+ btnPanel.addStyleName("my-translation-btns");
+ btnPanel.setSpacing(4);
+ btnPanel.add(createAbsTreeButton(t.getTree()));
+ btnPanel.add(createAlignButton(t.getTree()));
+ hPanel.add(btnPanel);
+ hPanel.setCellHorizontalAlignment(btnPanel,
+ HasHorizontalAlignment.ALIGN_RIGHT);
+ outputPanel.add(hPanel);
+
+ for (PGF.Linearization l : t.getLinearizations().iterable()) {
+ linsPanel.add(createTranslation(l.getTo(), t.getTree(), l.getText()));
+ }
+ }
+
+ if (tr.getTypeErrors() != null)
+ for (String error : tr.getTypeErrors()) {
+ SimplePanel panel = new SimplePanel();
+ panel.addStyleName("my-typeError");
+ panel.add(new HTML("<pre>"+error+"</pre>"));
+ outputPanel.add(panel);
+ }
+ }
+ }
+ public void onError (Throwable e) {
+ showError("Translation failed", e);
+ }
+ });
+ }
+
+ protected Widget createAbsTreeButton(final String abstractTree) {
+ Image treeBtn = new Image("se.chalmers.cs.gf.gwt.TranslateApp/tree-btn.png");
+ treeBtn.addClickListener(
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ // Create a dialog box and set the caption text
+ final DialogBox dialogBox = new DialogBox();
+ dialogBox.setText("Abstract Syntax Tree");
+
+ // Create a table to layout the content
+ HorizontalPanel dialogContents = new HorizontalPanel();
+ dialogContents.setSpacing(4);
+ dialogBox.setWidget(dialogContents);
+
+ // Add an image to the dialog
+
+ Frame image = new Frame(pgf.graphvizAbstractTree(abstractTree));
+ image.addStyleName("my-treeimage");
+ dialogContents.add(image);
+
+ // Add a close button at the bottom of the dialog
+ Button closeButton = new Button("Close",
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ dialogBox.hide();
+ }
+ });
+ dialogContents.add(closeButton);
+
+ dialogBox.center();
+ dialogBox.show();
+ }
+ });
+ return treeBtn;
+ }
+
+ protected Widget createAlignButton(final String abstractTree) {
+ Image alignBtn = new Image("se.chalmers.cs.gf.gwt.TranslateApp/align-btn.png");
+ alignBtn.addClickListener(
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ // Create a dialog box and set the caption text
+ final DialogBox dialogBox = new DialogBox();
+ dialogBox.setText("Word Alignment");
+
+ // Create a table to layout the content
+ HorizontalPanel dialogContents = new HorizontalPanel();
+ dialogContents.setSpacing(4);
+ dialogBox.setWidget(dialogContents);
+
+ // Add an image to the dialog
+ Frame image = new Frame(pgf.graphvizAlignment(abstractTree));
+ image.addStyleName("my-alignmentimage");
+ dialogContents.add(image);
+
+ // Add a close button at the bottom of the dialog
+ Button closeButton = new Button("Close",
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ dialogBox.hide();
+ }
+ });
+ dialogContents.add(closeButton);
+
+ dialogBox.center();
+ dialogBox.show();
+ }
+ });
+ return alignBtn;
+ }
+
+ protected Widget createTranslation(final String language, final String abstractTree, String text) {
+ Label l = new Label(text);
+ l.addStyleName("my-translation");
+ String lang = pgf.getLanguageCode(language);
+ if (lang != null) {
+ l.getElement().setLang(lang);
+ }
+ l.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+ // Create a dialog box and set the caption text
+ final DialogBox dialogBox = new DialogBox();
+ dialogBox.setText("Parse Tree");
+
+ // Create a table to layout the content
+ HorizontalPanel dialogContents = new HorizontalPanel();
+ dialogContents.setSpacing(4);
+ dialogBox.setWidget(dialogContents);
+
+ // Add an image to the dialog
+ Frame image = new Frame(pgf.graphvizParseTree(abstractTree, language));
+ image.addStyleName("my-treeimage");
+ dialogContents.add(image);
+
+ // Add a close button at the bottom of the dialog
+ Button closeButton = new Button("Close",
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ dialogBox.hide();
+ }
+ });
+ dialogContents.add(closeButton);
+
+ dialogBox.center();
+ dialogBox.show();
+ }
+ });
+ return l;
+ }
+
+ //
+ // Status stuff
+ //
+
+ protected void setStatus(String msg) {
+ statusPopup.setStatus(msg);
+ }
+
+ protected void showError(String msg, Throwable e) {
+ statusPopup.showError(msg, e);
+ }
+
+ protected void clearStatus() {
+ statusPopup.clearStatus();
+ }
+
+ //
+ // GUI
+ //
+
+ protected Widget createUI() {
+ translatePanel = createTranslatePanel();
+ browsePanel = createBrowsePanel();
+
+ VerticalPanel vPanel = new VerticalPanel();
+
+ HorizontalPanel hPanel = new HorizontalPanel();
+ hPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
+ hPanel.setStylePrimaryName("my-HeaderPanel");
+
+ Widget linksPanel = createLinksPanel(vPanel);
+ hPanel.add(linksPanel);
+ hPanel.setCellHorizontalAlignment(linksPanel,HorizontalPanel.ALIGN_LEFT);
+
+ Widget settingsPanel = createSettingsPanel();
+ hPanel.add(settingsPanel);
+ hPanel.setCellHorizontalAlignment(settingsPanel,HorizontalPanel.ALIGN_RIGHT);
+
+ vPanel.setWidth("100%");
+ vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
+ vPanel.add(hPanel);
+ vPanel.add(translatePanel);
+
+ return vPanel;
+ }
+
+ protected Widget createSuggestPanel () {
+ suggestPanel = new SuggestPanel(pgf);
+ suggestPanel.setButtonText("Translate");
+ suggestPanel.addSubmitListener(new SuggestPanel.SubmitListener() {
+ public void onSubmit(String text) {
+ translate();
+ }
+ });
+ return suggestPanel;
+ }
+
+ protected Widget createSettingsPanel () {
+ return new SettingsPanel(pgf);
+ }
+
+ protected Widget createTranslationsPanel () {
+ outputPanel = new VerticalPanel();
+ outputPanel.addStyleName("my-translations");
+ return outputPanel;
+ }
+
+ protected Widget createTranslatePanel() {
+ VerticalPanel translatePanel = new VerticalPanel();
+ translatePanel.add(createSuggestPanel());
+ translatePanel.add(createTranslationsPanel());
+ return translatePanel;
+ }
+
+ protected BrowsePanel createBrowsePanel() {
+ return new BrowsePanel(pgf);
+ }
+
+ protected Widget createLinksPanel(final Panel parent) {
+ HorizontalPanel linksPanel = new HorizontalPanel();
+ linksPanel.setStylePrimaryName("my-LinksPanel");
+
+ Hyperlink translateLink = new Hyperlink("Translate", null);
+ translateLink.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+ parent.remove(browsePanel);
+ parent.add(translatePanel);
+ }
+ });
+ linksPanel.add(translateLink);
+
+ Hyperlink browseLink = new Hyperlink("Browse", null);
+ browseLink.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+ parent.remove(translatePanel);
+ parent.add(browsePanel);
+ browsePanel.onActivate();
+ }
+ });
+ linksPanel.add(browseLink);
+
+ return linksPanel;
+ }
+
+ protected Widget createLoadingWidget () {
+ VerticalPanel loadingPanel = new VerticalPanel();
+ loadingPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
+ loadingPanel.add(new Label("Loading..."));
+ return loadingPanel;
+ }
+
+ //
+ // History stuff
+ //
+
+ protected class MyHistoryListener implements HistoryListener {
+ public void onHistoryChanged(String historyToken) {
+ updateSettingsFromHistoryToken();
+ }
+ };
+
+ protected void updateSettingsFromHistoryToken() {
+ updateSettingsFromHistoryToken(History.getToken().split("/"));
+ }
+
+ protected void updateSettingsFromHistoryToken(String[] tokenParts) {
+ if (tokenParts.length >= 1 && tokenParts[0].length() > 0) {
+ setPGFName(tokenParts[0]);
+ }
+ if (tokenParts.length >= 2 && tokenParts[1].length() > 0) {
+ setInputLanguage(tokenParts[1]);
+ }
+ }
+
+ protected void setPGFName (String pgfName) {
+ if (pgfName != null && !pgfName.equals(pgf.getPGFName())) {
+ pgf.setPGFName(pgfName);
+ }
+ }
+
+ protected void setInputLanguage (String inputLanguage) {
+ if (inputLanguage != null && !inputLanguage.equals(pgf.getInputLanguage())) {
+ pgf.setInputLanguage(inputLanguage);
+ }
+ }
+
+ //
+ // Initialization
+ //
+
+ protected class MySettingsListener implements PGFWrapper.SettingsListener {
+ // Will only happen on load
+ public void onAvailableGrammarsChanged() {
+ if (pgf.getPGFName() == null) {
+ List<String> grammars = pgf.getGrammars();
+ if (!grammars.isEmpty()) {
+ pgf.setPGFName(grammars.get(0));
+ }
+ }
+ }
+ public void onSelectedGrammarChanged() {
+ if (pgf.getInputLanguage() == null) {
+ GWT.log("Setting input language to user language: " + pgf.getUserLanguage(), null);
+ pgf.setInputLanguage(pgf.getUserLanguage());
+ }
+ update();
+ }
+ public void onInputLanguageChanged() {
+ update();
+ }
+ public void onOutputLanguageChanged() {
+ update();
+ }
+ public void onStartCategoryChanged() {
+ update();
+ }
+ public void onSettingsError(String msg, Throwable e) {
+ showError(msg,e);
+ }
+ }
+
+ public void onModuleLoad() {
+ statusPopup = new StatusPopup();
+
+ pgf = new PGFWrapper(pgfBaseURL);
+ RootPanel.get().add(createUI());
+ pgf.addSettingsListener(new MySettingsListener());
+ History.addHistoryListener(new MyHistoryListener());
+ updateSettingsFromHistoryToken();
+ pgf.updateAvailableGrammars();
+ }
+
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css
new file mode 100644
index 000000000..5c641665e
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css
@@ -0,0 +1,102 @@
+body {
+ background: url("brushed-metal.png");
+}
+
+.my-WordsPanel {
+ float: left;
+ padding: 0;
+}
+
+.my-WordsPanel-selected {
+ background-color: rgb(147,194,241);
+}
+
+.my-WordsPanel-focused {
+ background-color: rgb(147,194,241);
+ border: 1px solid #666;
+}
+
+.my-WordLabel {
+ float: left;
+ padding: 2px;
+}
+
+.my-TextEdit {
+ width: 100%;
+ height: 100%;
+ border: 1px solid #666;
+ padding: none;
+ margin: none;
+}
+
+.my-ChoiceListBox {
+ width: 100%;
+ height: 100%;
+ background-color: #eee;
+}
+
+.my-EditorPanel {
+ border: 1px solid #666;
+ background-color: #eee;
+}
+
+.my-AbstractTree {
+ width: 100%;
+ height: 100%;
+}
+
+.my-AbstractTree .gwt-TreeItem {
+ cursor: hand;
+ cursor: pointer;
+
+ padding: 0 10px;
+}
+
+.my-AbstractTree .gwt-TreeItem-selected {
+ background-color: #ffc;
+}
+
+.my-CommandsMenu {
+ margin: 0 auto;
+ width: 100%;
+ font-size: 80%;
+ background-color: #eee;
+}
+
+.my-CommandsMenu .gwt-MenuItem {
+ cursor: hand;
+ cursor: pointer;
+
+ padding: 0 10px;
+}
+
+.my-CommandsMenu .gwt-MenuItem-selected {
+ background-color: #ffc;
+}
+
+.my-Magnet {
+ float: left;
+ margin: 0.3em;
+ border-width: 1px;
+ border-style: solid;
+ border-color: black;
+ padding: 0.3em;
+ color: black;
+ background-color: white;
+}
+
+.my-Magnet {
+ float: left;
+ margin: 0.3em;
+ border-width: 1px;
+ border-style: solid;
+ border-color: black;
+ padding: 0.3em;
+ color: black;
+ background-color: white;
+}
+
+.my-FridgeBagPopup {
+ padding: 0.2em;
+ width: 500px;
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Fridge.css b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Fridge.css
new file mode 100644
index 000000000..5816831ad
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Fridge.css
@@ -0,0 +1,89 @@
+body {
+ background: url("brushed-metal.png");
+}
+
+.my-FridgeApp {
+
+}
+
+.my-FridgeTextPanel {
+ padding: 0.2em;
+ width: 100%;
+ border: 3px dashed #dddddd;
+}
+
+.my-FridgeTextPanel .magnets {
+ width: 100%;
+}
+
+.my-FridgeTextPanel .buttons {
+ width: 100%;
+}
+
+.my-FridgeTextPanel .buttons button {
+ width: 100%;
+}
+
+.my-FridgeTextPanel-engage {
+ border-color: #666666;
+ background-color: #dddddd;
+}
+
+.my-FridgeBagPanel {
+ padding: 0.2em;
+ border: 3px solid #dddddd;
+}
+
+.my-FridgeBagPanel-empty {
+ visibility: hidden;
+}
+
+.my-PrefixPanel {
+ margin-bottom: 1em;
+}
+
+.my-FridgeTextPanel .my-Magnet {
+ font-size: 150%;
+}
+
+.my-Magnet {
+ float: left;
+ margin: 0.3em;
+ border-width: 1px;
+ border-style: solid;
+ border-color: black;
+ padding: 0.3em;
+ color: black;
+ background-color: white;
+}
+
+.my-TranslationsPanel {
+ padding: 0.2em;
+ border: 3px solid #dddddd;
+ width: 100%;
+}
+
+.my-TranslationsPanel-empty {
+ visibility: hidden;
+}
+
+.my-translation {
+ margin: 0.2em;
+}
+
+.my-typeError {
+ padding: 6px;
+ font-size: 150%;
+ font-weight: bold;
+ background: #B9BEC0;
+}
+
+.my-SettingsPanel {
+ width: 100%;
+ padding: 0.5em 0;
+ border-top: 1px solid #dddddd;
+}
+
+.my-SettingsPanel .my-FormWidget {
+ margin: 0.2em;
+} \ No newline at end of file
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Translate.css b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Translate.css
new file mode 100644
index 000000000..49efa8c76
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Translate.css
@@ -0,0 +1,121 @@
+/** Add css rules here for your application. */
+
+.my-SuggestPanel {
+ margin: 1em 0 0.5em 0;
+}
+
+.my-SuggestPanel .gwt-SuggestBox {
+ width: 400px;
+ font-size: 150%;
+ margin: 0;
+}
+
+.my-SuggestPanel .gwt-Button {
+ font-size: 150%;
+ margin: 0;
+ margin-left: 2px;
+}
+
+.my-SettingsPanel * {
+ margin: 0 0.4em;
+}
+
+.my-LinksPanel * {
+ margin: 0 0.1em;
+}
+
+.my-HeaderPanel {
+ width: 100%;
+ margin: 0 0.1em;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ border-bottom-color: rgb(122,165,214);
+}
+
+.my-BrowsePanel {
+ width: 100%;
+ margin: 1em;
+ border-width: 5px;
+ border-color: rgb(122,165,214);
+}
+
+.my-BrowseFrame {
+ width: 100%;
+ height: 100%;
+ margin: 1em;
+ border-style:none;
+}
+
+.my-translations {
+ margin-top: 1em;
+}
+
+.my-translation-frame {
+ width: 100%;
+ margin: 0.5em;
+ background: #D0E4F6;
+}
+
+.my-translation-bar {
+ padding-left: 25px;
+ padding-right: 25px;
+ width: 100%;
+}
+
+.my-translation {
+ margin: 0.2em;
+ font-size: 150%;
+ background-repeat: no-repeat;
+ background-position: 0% 50%;
+ cursor:pointer;
+}
+
+.my-typeError {
+ padding: 12px;
+ font-size: 150%;
+ font-weight: bold;
+ background: #CDFFDA;
+}
+
+.my-translation-btns {
+ background: #DDDDDD;
+ cursor:pointer;
+}
+
+.my-treeimage {
+ width: 650px;
+ height: 520px;
+}
+
+.my-alignmentimage {
+ width: 450px;
+ height: 300px;
+}
+
+.my-identifierLink:link {
+ text-decoration: none;
+ color: black;
+}
+
+.my-identifierLink:hover {
+ text-decoration: none;
+ color: black;
+ background-color: silver;
+}
+
+/*
+* [LANG=bg] { background-image: url("flags/bg.png"); }
+* [LANG=ca] { background-image: url("flags/catalonia.png"); }
+* [LANG=da] { background-image: url("flags/dk.png"); }
+* [LANG=de] { background-image: url("flags/de.png"); }
+* [LANG=en] { background-image: url("flags/gb.png"); }
+* [LANG=fi] { background-image: url("flags/fi.png"); }
+* [LANG=fr] { background-image: url("flags/fr.png"); }
+* [LANG=it] { background-image: url("flags/it.png"); }
+* [LANG=no] { background-image: url("flags/no.png"); }
+* [LANG=ru] { background-image: url("flags/ru.png"); }
+* [LANG=es] { background-image: url("flags/es.png"); }
+* [LANG=sv] { background-image: url("flags/se.png"); }
+*/ \ No newline at end of file
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/align-btn.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/align-btn.png
new file mode 100644
index 000000000..ca6a391c1
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/align-btn.png
Binary files differ
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/brushed-metal.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/brushed-metal.png
new file mode 100644
index 000000000..c2f03fe7d
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/brushed-metal.png
Binary files differ
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/delete-last.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/delete-last.png
new file mode 100644
index 000000000..f984b976e
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/delete-last.png
Binary files differ
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/tree-btn.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/tree-btn.png
new file mode 100644
index 000000000..ebd243617
--- /dev/null
+++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/tree-btn.png
Binary files differ
diff --git a/src/ui/gwt/www/editor/index.html b/src/ui/gwt/www/editor/index.html
new file mode 100644
index 000000000..6d1e36c92
--- /dev/null
+++ b/src/ui/gwt/www/editor/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
+<!-- above set at the top of the file will set -->
+<!-- the browser's rendering engine into -->
+<!-- "Quirks Mode". Replacing this declaration -->
+<!-- with a "Standards Mode" doctype is supported, -->
+<!-- but may lead to some differences in layout. -->
+
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <!-- -->
+ <!-- Any title is fine -->
+ <!-- -->
+ <title>Editor</title>
+
+ <!-- -->
+ <!-- This script loads your compiled module. -->
+ <!-- If you add any GWT meta tags, they must -->
+ <!-- be added before this line. -->
+ <!-- -->
+ <script type="text/javascript" language="javascript" src="se.chalmers.cs.gf.gwt.EditorApp/se.chalmers.cs.gf.gwt.EditorApp.nocache.js"></script>
+ </head>
+
+ <!-- -->
+ <!-- The body can have arbitrary html, or -->
+ <!-- you can leave the body empty if you want -->
+ <!-- to create a completely dynamic UI. -->
+ <!-- -->
+ <body>
+
+ <!-- OPTIONAL: include this if you want history support -->
+ <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+
+ </body>
+</html>
diff --git a/src/ui/gwt/www/fridge/index.html b/src/ui/gwt/www/fridge/index.html
new file mode 100644
index 000000000..b530946d5
--- /dev/null
+++ b/src/ui/gwt/www/fridge/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
+<!-- above set at the top of the file will set -->
+<!-- the browser's rendering engine into -->
+<!-- "Quirks Mode". Replacing this declaration -->
+<!-- with a "Standards Mode" doctype is supported, -->
+<!-- but may lead to some differences in layout. -->
+
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <!-- -->
+ <!-- Any title is fine -->
+ <!-- -->
+ <title>Fridge</title>
+
+ <!-- -->
+ <!-- This script loads your compiled module. -->
+ <!-- If you add any GWT meta tags, they must -->
+ <!-- be added before this line. -->
+ <!-- -->
+ <script type="text/javascript" language="javascript" src="se.chalmers.cs.gf.gwt.FridgeApp/se.chalmers.cs.gf.gwt.FridgeApp.nocache.js"></script>
+ </head>
+
+ <!-- -->
+ <!-- The body can have arbitrary html, or -->
+ <!-- you can leave the body empty if you want -->
+ <!-- to create a completely dynamic UI. -->
+ <!-- -->
+ <body>
+
+ <!-- OPTIONAL: include this if you want history support -->
+ <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+
+ </body>
+</html>
diff --git a/src/ui/gwt/www/morpho/index.html b/src/ui/gwt/www/morpho/index.html
new file mode 100644
index 000000000..9e3beabb6
--- /dev/null
+++ b/src/ui/gwt/www/morpho/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
+<!-- above set at the top of the file will set -->
+<!-- the browser's rendering engine into -->
+<!-- "Quirks Mode". Replacing this declaration -->
+<!-- with a "Standards Mode" doctype is supported, -->
+<!-- but may lead to some differences in layout. -->
+
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <!-- -->
+ <!-- Any title is fine -->
+ <!-- -->
+ <title>Morpho</title>
+
+ <!-- -->
+ <!-- This script loads your compiled module. -->
+ <!-- If you add any GWT meta tags, they must -->
+ <!-- be added before this line. -->
+ <!-- -->
+ <script type="text/javascript" language="javascript" src="se.chalmers.cs.gf.gwt.MorphoApp/se.chalmers.cs.gf.gwt.MorphoApp.nocache.js"></script>
+ </head>
+
+ <!-- -->
+ <!-- The body can have arbitrary html, or -->
+ <!-- you can leave the body empty if you want -->
+ <!-- to create a completely dynamic UI. -->
+ <!-- -->
+ <body>
+
+ <!-- OPTIONAL: include this if you want history support -->
+ <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+
+ </body>
+</html>
diff --git a/src/ui/gwt/www/morpho/morpho.fcgi b/src/ui/gwt/www/morpho/morpho.fcgi
new file mode 100644
index 000000000..8d1c8b69c
--- /dev/null
+++ b/src/ui/gwt/www/morpho/morpho.fcgi
@@ -0,0 +1 @@
+
diff --git a/src/ui/gwt/www/translate/index.html b/src/ui/gwt/www/translate/index.html
new file mode 100644
index 000000000..8bad4c250
--- /dev/null
+++ b/src/ui/gwt/www/translate/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
+<!-- above set at the top of the file will set -->
+<!-- the browser's rendering engine into -->
+<!-- "Quirks Mode". Replacing this declaration -->
+<!-- with a "Standards Mode" doctype is supported, -->
+<!-- but may lead to some differences in layout. -->
+
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <!-- -->
+ <!-- Any title is fine -->
+ <!-- -->
+ <title>Translate</title>
+
+ <!-- -->
+ <!-- This script loads your compiled module. -->
+ <!-- If you add any GWT meta tags, they must -->
+ <!-- be added before this line. -->
+ <!-- -->
+ <script type="text/javascript" language="javascript" src="se.chalmers.cs.gf.gwt.TranslateApp/se.chalmers.cs.gf.gwt.TranslateApp.nocache.js"></script>
+ </head>
+
+ <!-- -->
+ <!-- The body can have arbitrary html, or -->
+ <!-- you can leave the body empty if you want -->
+ <!-- to create a completely dynamic UI. -->
+ <!-- -->
+ <body>
+
+ <!-- OPTIONAL: include this if you want history support -->
+ <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+
+ </body>
+</html>