Make GWT compilation easier.

This commit is contained in:
bjorn
2008-10-22 13:29:57 +00:00
parent 94b8b451df
commit 252ae4cb31
14 changed files with 33 additions and 26 deletions

View File

@@ -0,0 +1,13 @@
#!/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
java -XstartOnFirstThread -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:$GWT_CLASSPATH" com.google.gwt.dev.GWTCompiler -out "$APPDIR/www" "$@" se.chalmers.cs.gf.gwt.TranslateApp;

View File

@@ -0,0 +1,13 @@
#!/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
java -XstartOnFirstThread -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.TranslateApp/Translate.html;

View File

@@ -0,0 +1,8 @@
<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" />
</module>

View File

@@ -0,0 +1,24 @@
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name="com.google.gwt.user.User" />
<inherits name="se.chalmers.cs.gf.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.TranslateApp" />
<!-- Specify the application specific style sheet. -->
<stylesheet src="Translate.css" />
</module>

View File

@@ -0,0 +1,84 @@
package se.chalmers.cs.gf.gwt.client;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.core.client.GWT;
import java.util.*;
public class CompletionOracle extends SuggestOracle {
private PGF pgf;
private ErrorHandler errorHandler;
private List<String> inputLangs = null;
private PGFRequest pgfRequest = null;
public CompletionOracle (PGF pgf) {
this(pgf, null);
}
public CompletionOracle (PGF pgf, ErrorHandler errorHandler) {
this.pgf = pgf;
this.errorHandler = errorHandler;
}
public void setInputLangs(List<String> inputLangs) {
this.inputLangs = inputLangs;
}
public List<String> getInputLangs() {
return inputLangs;
}
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(final SuggestOracle.Request request, final SuggestOracle.Callback callback) {
// only allow a single completion request at a time
if (pgfRequest != null)
pgfRequest.cancel();
pgfRequest = pgf.complete(request.getQuery(), getInputLangs(), null, request.getLimit(),
new PGF.CompleteCallback() {
public void onResult(PGF.Completions completions) {
Collection<CompletionSuggestion> suggestions = new ArrayList<CompletionSuggestion>();
for (int i = 0; i < completions.length(); i++) {
String text = completions.get(i).getText();
suggestions.add(new CompletionSuggestion(text));
}
callback.onSuggestionsReady(request, new SuggestOracle.Response(suggestions));
}
public void onError(Throwable e) {
errorHandler.onError(e);
}
});
}
}

View File

@@ -0,0 +1,221 @@
package se.chalmers.cs.gf.gwt.client;
import com.google.gwt.http.client.*;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import java.util.Set;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.ArrayList;
public class PGF {
private String baseURL;
private String pgfName;
public PGF (String baseURL, String pgfName) {
this.baseURL = baseURL;
this.pgfName = pgfName;
}
public static interface GFCallback<T extends JavaScriptObject> {
public void onResult (T result) ;
public void onError (Throwable e) ;
}
public static class IterableJsArray<T extends JavaScriptObject> extends JsArray<T> {
protected IterableJsArray() {}
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();
}
};
}
};
}
}
/* Grammar */
public PGFRequest grammar (final GrammarCallback callback) {
return sendRequest("grammar", null, callback);
}
public interface GrammarCallback extends GFCallback<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 Language getLanguage(String name) {
int c = getLanguages().length();
for (int i = 0; i < c; i++) {
Language l = getLanguages().get(i);
if (l.getName().equals(name))
return l;
}
return null;
}
}
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 PGFRequest translate (String input, List<String> fromLangs, String cat, List<String> toLangs,
final TranslateCallback callback) {
List<Arg> args = new ArrayList<Arg>();
args.add(new Arg("input", input));
if (fromLangs != null) {
for (String from : fromLangs) {
args.add(new Arg("from", from));
}
}
args.add(new Arg("cat", cat));
if (toLangs != null) {
for (String to : toLangs) {
args.add(new Arg("to", to));
}
}
return sendRequest("translate", args, callback);
}
public interface TranslateCallback extends GFCallback<Translations> { }
public static class Translations extends IterableJsArray<Translation> {
protected Translations() { }
}
public static class Translation extends JavaScriptObject {
protected Translation() { }
public final native String getFrom() /*-{ return this.from; }-*/;
public final native String getTo() /*-{ return this.to; }-*/;
public final native String getText() /*-{ return this.text; }-*/;
}
/* Completion */
public PGFRequest complete (String input, List<String> fromLangs, String cat, int limit, final CompleteCallback callback) {
List<Arg> args = new ArrayList<Arg>();
args.add(new Arg("input", input));
if (fromLangs != null) {
for (String from : fromLangs) {
args.add(new Arg("from", from));
}
}
args.add(new Arg("cat", cat));
args.add(new Arg("limit", limit));
return sendRequest("complete", args, callback);
}
public interface CompleteCallback extends GFCallback<Completions> { }
public static class Completions extends IterableJsArray<Translation> {
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; }-*/;
}
/* Utilities */
private <T extends JavaScriptObject> PGFRequest sendRequest (String resource, List<Arg> vars, final GFCallback<T> callback) {
String url = baseURL + "/" + pgfName + "/" + resource + "?" + buildQueryString(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((T)eval(response.getText()).cast());
} else {
RequestException e = new RequestException("Response not OK: " + response.getStatusCode() + ". " + response.getText());
callback.onError(e);
}
}
});
} catch (RequestException e) {
callback.onError(e);
}
return new PGFRequest(request);
}
private static native JavaScriptObject eval(String json) /*-{
return eval('(' + json + ')');
}-*/;
private 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));
}
}
private static String buildQueryString(List<Arg> args) {
StringBuffer sb = new StringBuffer();
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();
}
}

View File

@@ -0,0 +1,19 @@
package se.chalmers.cs.gf.gwt.client;
import com.google.gwt.http.client.*;
public class PGFRequest {
private Request httpRequest;
PGFRequest (Request httpRequest) {
this.httpRequest = httpRequest;
}
public void cancel() {
if (httpRequest != null) {
httpRequest.cancel();
}
}
}

View File

@@ -0,0 +1,214 @@
package se.chalmers.cs.gf.gwt.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.i18n.client.LocaleInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class TranslateApp implements EntryPoint {
private static final String pgfBaseURL = "/pgf";
private static final String pgfName = "grammar.pgf";
private PGF pgf;
private CompletionOracle oracle;
private SuggestBox suggest;
private PGF.Grammar grammar;
private ListBox fromLangBox;
private ListBox toLangBox;
private Button translateButton;
private VerticalPanel outputPanel;
private PopupPanel statusPopup;
private Label statusLabel;
private void addTranslation(String text, String toLang) {
Label l = new Label(text);
l.addStyleName("my-translation");
PGF.Language lang = grammar.getLanguage(toLang);
if (lang != null) {
l.getElement().setLang(lang.getLanguageCode());
}
outputPanel.add(l);
}
private void translate() {
outputPanel.clear();
setStatus("Translating...");
pgf.translate(suggest.getText(), listBoxSelection(fromLangBox), null,
listBoxSelection(toLangBox), new PGF.TranslateCallback() {
public void onResult (PGF.Translations translations) {
for (PGF.Translation t : translations.iterable()) {
addTranslation(t.getText(), t.getTo());
}
clearStatus();
}
public void onError (Throwable e) {
showError("Translation failed", e);
}
});
}
private void updateLangs() {
oracle.setInputLangs(listBoxSelection(fromLangBox));
}
private List<String> listBoxSelection(ListBox box) {
int c = box.getItemCount();
List<String> l = new ArrayList<String>();
for (int i = 0; i < c; i++) {
if (box.isItemSelected(i)) {
l.add(box.getValue(i));
}
}
return l;
}
private void setStatus(String msg) {
statusLabel.setText(msg);
statusPopup.center();
}
private void showError(String msg, Throwable e) {
GWT.log(msg, e);
setStatus(msg);
}
private void clearStatus() {
statusPopup.hide();
}
private void setGrammar(PGF.Grammar grammar) {
this.grammar = grammar;
for (PGF.Language l : grammar.getLanguages().iterable()) {
String name = l.getName();
if (l.canParse()) {
fromLangBox.addItem(name);
if (name.equals(grammar.getUserLanguage())) {
fromLangBox.setSelectedIndex(fromLangBox.getItemCount()-1);
}
}
toLangBox.addItem(name);
}
updateLangs();
clearStatus();
fromLangBox.setEnabled(true);
toLangBox.setEnabled(true);
translateButton.setEnabled(true);
}
private void createTranslationUI() {
oracle = new CompletionOracle(pgf, new CompletionOracle.ErrorHandler() {
public void onError(Throwable e) {
showError("Completion failed", e);
}
});
suggest = new SuggestBox(oracle);
suggest.addKeyboardListener(new KeyboardListenerAdapter() {
public void onKeyUp (Widget sender, char keyCode, int modifiers) {
if (keyCode == KEY_ENTER) {
translate();
}
}
});
fromLangBox = new ListBox();
fromLangBox.setEnabled(false);
fromLangBox.addItem("Any language", "");
fromLangBox.addChangeListener(new ChangeListener() {
public void onChange(Widget sender) {
updateLangs();
translate();
}
});
toLangBox = new ListBox();
toLangBox.setEnabled(false);
toLangBox.addItem("All languages", "");
toLangBox.addChangeListener(new ChangeListener() {
public void onChange(Widget sender) {
updateLangs();
translate();
}
});
translateButton = new Button("Translate");
translateButton.setEnabled(false);
translateButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
translate();
}
});
HorizontalPanel settingsPanel = new HorizontalPanel();
settingsPanel.addStyleName("my-settingsPanel");
settingsPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
settingsPanel.add(new Label("From:"));
settingsPanel.add(fromLangBox);
settingsPanel.add(new Label("To:"));
settingsPanel.add(toLangBox);
settingsPanel.add(translateButton);
outputPanel = new VerticalPanel();
outputPanel.addStyleName("my-translations");
VerticalPanel vPanel = new VerticalPanel();
vPanel.setWidth("100%");
vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
vPanel.add(suggest);
vPanel.add(settingsPanel);
vPanel.add(outputPanel);
RootPanel.get().add(vPanel);
}
public void onModuleLoad() {
statusLabel = new Label("Loading...");
statusPopup = new PopupPanel(true, true);
statusPopup.add(statusLabel);
statusPopup.center();
pgf = new PGF(pgfBaseURL, pgfName);
createTranslationUI();
pgf.grammar(new PGF.GrammarCallback() {
public void onResult(PGF.Grammar grammar) {
setGrammar(grammar);
}
public void onError (Throwable e) {
showError("Error getting language information", e);
}
});
}
}

View File

@@ -0,0 +1,38 @@
/** Add css rules here for your application. */
.gwt-SuggestBox {
width: 70%;
font-size: 150%;
margin: 1em 0 0.5em 0;
}
.my-settingsPanel * {
margin: 0 0.4em;
}
.my-translations {
margin-top: 1em;
}
.my-translation {
margin: 0.2em;
padding-left: 25px;
font-size: 150%;
background-repeat: no-repeat;
background-position: 0% 50%;
}
/*
* [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"); }
*/

View File

@@ -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.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>