From df5e7b336360b311e9739aaf1e7c706e26df4442 Mon Sep 17 00:00:00 2001 From: bjorn Date: Mon, 3 Nov 2008 16:43:47 +0000 Subject: [PATCH] Added first version of the fridge poetry gui --- src/server/gwt/Fridge-compile | 17 ++ src/server/gwt/Fridge-shell-external | 17 ++ src/server/gwt/FridgeApp.launch | 21 ++ src/server/gwt/TranslateApp.launch | 15 +- .../se/chalmers/cs/gf/gwt/FridgeApp.gwt.xml | 24 ++ .../chalmers/cs/gf/gwt/client/FridgeApp.java | 235 ++++++++++++++++++ .../se/chalmers/cs/gf/gwt/client/Magnet.java | 66 +++++ .../cs/gf/gwt/client/MultiListBox.java | 40 +-- .../src/se/chalmers/cs/gf/gwt/client/PGF.java | 9 +- .../cs/gf/gwt/client/SettingsPanel.java | 8 +- .../se/chalmers/cs/gf/gwt/public/Fridge.css | 32 +++ .../se/chalmers/cs/gf/gwt/public/Fridge.html | 36 +++ 12 files changed, 497 insertions(+), 23 deletions(-) create mode 100644 src/server/gwt/Fridge-compile create mode 100644 src/server/gwt/Fridge-shell-external create mode 100644 src/server/gwt/FridgeApp.launch create mode 100644 src/server/gwt/src/se/chalmers/cs/gf/gwt/FridgeApp.gwt.xml create mode 100644 src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java create mode 100644 src/server/gwt/src/se/chalmers/cs/gf/gwt/client/Magnet.java create mode 100644 src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.css create mode 100644 src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.html diff --git a/src/server/gwt/Fridge-compile b/src/server/gwt/Fridge-compile new file mode 100644 index 000000000..1a421c5d5 --- /dev/null +++ b/src/server/gwt/Fridge-compile @@ -0,0 +1,17 @@ +#!/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 + +java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$GWT_CLASSPATH" com.google.gwt.dev.GWTCompiler -out "$APPDIR/www" "$@" se.chalmers.cs.gf.gwt.FridgeApp; diff --git a/src/server/gwt/Fridge-shell-external b/src/server/gwt/Fridge-shell-external new file mode 100644 index 000000000..b6261e63a --- /dev/null +++ b/src/server/gwt/Fridge-shell-external @@ -0,0 +1,17 @@ +#!/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 + +java $GWT_JAVA_OPTS -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$GWT_CLASSPATH" com.google.gwt.dev.GWTShell -out "$APPDIR/www" -noserver "$@" http://localhost:41296/gwt/www/se.chalmers.cs.gf.gwt.FridgeApp/Fridge.html; diff --git a/src/server/gwt/FridgeApp.launch b/src/server/gwt/FridgeApp.launch new file mode 100644 index 000000000..69acf02d0 --- /dev/null +++ b/src/server/gwt/FridgeApp.launch @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/server/gwt/TranslateApp.launch b/src/server/gwt/TranslateApp.launch index 400ecca5c..8eff471c2 100644 --- a/src/server/gwt/TranslateApp.launch +++ b/src/server/gwt/TranslateApp.launch @@ -1,16 +1,21 @@ - - + + + + + + + - - + + - + diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/FridgeApp.gwt.xml b/src/server/gwt/src/se/chalmers/cs/gf/gwt/FridgeApp.gwt.xml new file mode 100644 index 000000000..c1a7fbf0e --- /dev/null +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/FridgeApp.gwt.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java new file mode 100644 index 000000000..b2dc0a6c7 --- /dev/null +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java @@ -0,0 +1,235 @@ +package se.chalmers.cs.gf.gwt.client; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Panel; +import com.google.gwt.user.client.ui.PushButton; +import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; + + +public class FridgeApp implements EntryPoint { + + private static final String pgfBaseURL = "/pgf"; + + private PGF pgf; + + private FlowPanel textPanel; + private Panel bagPanel; + private SettingsPanel settingsPanel; + private VerticalPanel outputPanel; + private StatusPopup statusPopup; + + // + // Translation + // + + private void translate() { + outputPanel.clear(); + setStatus("Translating..."); + pgf.translate(settingsPanel.getGrammarName(), + getText(), + settingsPanel.getInputLanguages(), null, + settingsPanel.getOutputLanguages(), + new PGF.TranslateCallback() { + public void onResult (PGF.Translations translations) { + for (final PGF.Translation t : translations.iterable()) { + PushButton l = new PushButton(t.getText()); + l.addStyleName("my-translation"); + l.addClickListener(new ClickListener() { + public void onClick(Widget sender) { + setText(t.getTo(), t.getText()); + } + }); + PGF.Language lang = settingsPanel.getGrammar().getLanguage(t.getTo()); + if (lang != null) { + l.getElement().setLang(lang.getLanguageCode()); + } + outputPanel.add(l); + } + clearStatus(); + } + public void onError (Throwable e) { + showError("Translation failed", e); + } + }); + } + + // + // Magnets + // + + private List getWords() { + List l = new ArrayList(); + for (Widget w : textPanel) { + l.add(((Magnet)w).getText()); + } + return l; + } + + private String getText () { + StringBuilder sb = new StringBuilder(); + for (String word : getWords()) { + if (sb.length() > 0) { + sb.append(' '); + } + sb.append(word); + } + return sb.toString(); + } + + private void setText (String language, String text) { + settingsPanel.setInputLanguages(Collections.singletonList(language)); + textPanel.clear(); + for (String word : text.split("\\s+")) { + textPanel.add(new Magnet(language, word)); + } + updateBag(); + } + + private ClickListener magnetClickListener = new ClickListener () { + public void onClick(Widget sender) { + Magnet magnet = (Magnet)sender; + textPanel.add(new Magnet(magnet)); + update(); + } + }; + + private void updateBag () { + bagPanel.clear(); + int limit = 100; + pgf.complete(settingsPanel.getGrammarName(), + getText() + " ", + settingsPanel.getInputLanguages(), null, + limit, new PGF.CompleteCallback() { + public void onResult(PGF.Completions completions) { + boolean empty = true; + List oldWords = getWords(); + for (PGF.Completion completion : completions.iterable()) { + String[] newWords = completion.getText().split("\\s+"); + if (newWords.length == oldWords.size()+1) { + String word = newWords[newWords.length-1]; + bagPanel.add(new Magnet(completion.getFrom(), word, magnetClickListener)); + empty = false; + } + } + if (empty) { + bagPanel.add(new Label("")); + } + } + public void onError(Throwable e) { + showError("Error getting completions.", e); + } + }); + } + + public void update() { + updateBag(); + translate(); + } + + public void clear() { + textPanel.clear(); + update(); + } + + public void deleteLastMagnet() { + int c = textPanel.getWidgetCount(); + if (c > 0) { + textPanel.remove(c-1); + update(); + } + } + + // + // Status stuff + // + + private void setStatus(String msg) { + statusPopup.setStatus(msg); + } + + private void showError(String msg, Throwable e) { + statusPopup.showError(msg, e); + } + + private void clearStatus() { + statusPopup.clearStatus(); + } + + // + // GUI + // + + private void createTranslationUI() { + + statusPopup = new StatusPopup(); + setStatus("Loading..."); + + settingsPanel = new SettingsPanel(pgf); + settingsPanel.addSettingsListener(new SettingsPanel.SettingsListener() { + public void grammarChanged(String pgfName) { + } + public void languagesChanged(List inputLangs, List outputLangs) { + update(); + } + public void settingsError(String msg, Throwable e) { + showError(msg,e); + } + }); + + Panel buttons = new HorizontalPanel(); + buttons.add(new Button("Clear", new ClickListener () { + public void onClick(Widget sender) { + clear(); + } + })); + buttons.add(new Button("Delete last", new ClickListener () { + public void onClick(Widget sender) { + deleteLastMagnet(); + } + })); + + + outputPanel = new VerticalPanel(); + outputPanel.addStyleName("my-translations"); + + textPanel = new FlowPanel(); + textPanel.setStylePrimaryName("my-TextPanel"); + + bagPanel = new FlowPanel(); + bagPanel.setStylePrimaryName("my-BagPanel"); + + VerticalPanel mainPanel = new VerticalPanel(); + mainPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER); + mainPanel.setWidth("100%"); + mainPanel.add(textPanel); + mainPanel.add(buttons); + mainPanel.add(bagPanel); + mainPanel.add(outputPanel); + mainPanel.add(settingsPanel); + + RootPanel.get().add(mainPanel); + + } + + // + // Initialization + // + + public void onModuleLoad() { + pgf = new PGF(pgfBaseURL); + createTranslationUI(); + settingsPanel.updateAvailableGrammars(); + } + +} diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/Magnet.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/Magnet.java new file mode 100644 index 000000000..9f86a6747 --- /dev/null +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/Magnet.java @@ -0,0 +1,66 @@ +package se.chalmers.cs.gf.gwt.client; + +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.ClickListenerCollection; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.PushButton; +import com.google.gwt.user.client.ui.SourcesClickEvents; +import com.google.gwt.user.client.ui.Widget; + +public class Magnet extends Composite implements SourcesClickEvents { + + private String language; + + private String text; + + private ClickListenerCollection clickListeners = null; + + public Magnet(Magnet magnet) { + this(magnet.language, magnet.text); + } + + public Magnet(String language, String text) { + this(language, text, null); + } + + public Magnet(String language, String text, ClickListener listener) { + this.language = language; + this.text = text; + final PushButton button = new PushButton(text); + button.addClickListener(new ClickListener() { + public void onClick(Widget sender) { + button.setFocus(false); + fireClick(); + } + }); + initWidget(button); + addStyleName("my-Magnet"); + if (listener != null) { + addClickListener(listener); + } + } + + public String getText() { + return text; + } + + public void addClickListener(ClickListener listener) { + if (clickListeners == null) { + clickListeners = new ClickListenerCollection(); + } + clickListeners.add(listener); + } + + public void removeClickListener(ClickListener listener) { + if (clickListeners != null) { + clickListeners.remove(listener); + } + } + + public void fireClick () { + if (clickListeners != null) { + clickListeners.fireClick(this); + } + } + +} diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/MultiListBox.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/MultiListBox.java index ac09c751f..fafdf2646 100644 --- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/MultiListBox.java +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/MultiListBox.java @@ -1,24 +1,34 @@ package se.chalmers.cs.gf.gwt.client; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import com.google.gwt.user.client.ui.ListBox; -import java.util.ArrayList; -import java.util.List; - public class MultiListBox extends ListBox { - public MultiListBox() { - } - - public List getSelectedValues() { - int c = getItemCount(); - List l = new ArrayList(); - for (int i = 0; i < c; i++) { - if (isItemSelected(i)) { - l.add(getValue(i)); - } + public MultiListBox() { + } + + public List getSelectedValues() { + int c = getItemCount(); + List l = new ArrayList(); + for (int i = 0; i < c; i++) { + if (isItemSelected(i)) { + l.add(getValue(i)); + } + } + return l; + } + + public void setSelectedValues(List values) { + Set vs = new HashSet(values); + int c = getItemCount(); + for (int i = 0; i < c; i++) { + setItemSelected(i, vs.contains(getValue(i))); + } } - return l; - } } \ No newline at end of file diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java index d97b64c1d..a9d38c6a8 100644 --- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java @@ -105,6 +105,11 @@ public class PGF { /* 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 pgfName, String input, List fromLangs, String cat, int limit, final CompleteCallback callback) { List args = new ArrayList(); args.add(new Arg("input", input)); @@ -114,7 +119,9 @@ public class PGF { } } args.add(new Arg("cat", cat)); - args.add(new Arg("limit", limit)); + if (limit != -1) { + args.add(new Arg("limit", limit)); + } return sendGrammarRequest(pgfName, "complete", args, callback); } diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/SettingsPanel.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/SettingsPanel.java index 3f52b1fab..893bff8ff 100644 --- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/SettingsPanel.java +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/SettingsPanel.java @@ -121,12 +121,16 @@ public class SettingsPanel extends Composite { public List getInputLanguages() { return fromLangBox.getSelectedValues(); - } - + } + public List getOutputLanguages() { return toLangBox.getSelectedValues(); } + public void setInputLanguages(List langs) { + fromLangBox.setSelectedValues(langs); + } + private void updateAvailableLanguages() { pgf.grammar(getGrammarName(), new PGF.GrammarCallback() { public void onResult(PGF.Grammar grammar) { diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.css b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.css new file mode 100644 index 000000000..6d692d606 --- /dev/null +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.css @@ -0,0 +1,32 @@ +.my-TextPanel, .my-BagPanel, .my-translations, .my-SettingsPanel { + margin: 1em; +} + +.my-TextPanel { + font-size: 150%; + min-height: 2em; + border: 3px dashed silver; + overflow: auto; +} + +.my-BagPanel { + border: 1px solid silver; + overflow: auto; +} + +.my-Magnet { + float: left; + margin: 0.3em; + padding: 0.3em; +} + +.my-translations { + border: 1px solid silver; +} + +.my-translation { + margin: 0.2em; +} + +.my-SettingsPanel { +} \ No newline at end of file diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.html b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.html new file mode 100644 index 000000000..2686838f6 --- /dev/null +++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Fridge.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + Fridge + + + + + + + + + + + + + + + + + + + + +