diff --git a/src/server/gwt/Editor-compile b/src/server/gwt/Editor-compile
new file mode 100644
index 000000000..89968b4ce
--- /dev/null
+++ b/src/server/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/server/gwt/src/se/chalmers/cs/gf/gwt/EditorApp.gwt.xml b/src/server/gwt/src/se/chalmers/cs/gf/gwt/EditorApp.gwt.xml
new file mode 100644
index 000000000..d6bb2312e
--- /dev/null
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/EditorApp.gwt.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/AbstractSyntaxController.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/AbstractSyntaxController.java
new file mode 100644
index 000000000..da39a8a5e
--- /dev/null
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/AbstractSyntaxController.java
@@ -0,0 +1,211 @@
+package se.chalmers.cs.gf.gwt.client;
+
+import java.util.*;
+
+import com.google.gwt.core.client.*;
+import com.google.gwt.user.client.*;
+import com.google.gwt.user.client.ui.*;
+
+
+public class AbstractSyntaxController {
+ private final Tree abstractTree;
+ private final FlowPanel textPanel;
+
+ private Map panels;
+ private Map> 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 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)
+ {
+ HorizontalPanel wordsPanel = new HorizontalPanel();
+ wordsPanel.setStylePrimaryName("my-WordsPanel");
+ panels.put(wordsPanel,item);
+
+ List 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 curr = new LinkedList();
+ tmpItem = item;
+ while (tmpItem != null)
+ {
+ curr.addFirst(tmpItem);
+ tmpItem = tmpItem.getParentItem();
+ }
+
+ LinkedList 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 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 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/server/gwt/src/se/chalmers/cs/gf/gwt/client/EditorApp.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/EditorApp.java
new file mode 100644
index 000000000..f9cd1422e
--- /dev/null
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/EditorApp.java
@@ -0,0 +1,127 @@
+package se.chalmers.cs.gf.gwt.client;
+
+import java.util.*;
+
+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/server/gwt/src/se/chalmers/cs/gf/gwt/public/Editor.css b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Editor.css
new file mode 100644
index 000000000..3ddb3d442
--- /dev/null
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Editor.css
@@ -0,0 +1,101 @@
+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 {
+ 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/server/gwt/www/editor/index.html b/src/server/gwt/www/editor/index.html
new file mode 100644
index 000000000..6d1e36c92
--- /dev/null
+++ b/src/server/gwt/www/editor/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Editor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+