initial import of the new GF editor. Note: the FridgeApp is temporary broken. It will be fixed with the next patch

This commit is contained in:
krasimir
2010-09-29 13:17:48 +00:00
parent 518a27a009
commit f1713c3634
18 changed files with 2353 additions and 116 deletions

View File

@@ -13,8 +13,10 @@
<!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
<!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> -->
<!-- Other module inherits -->
<replace-with class="org.grammaticalframework.ui.gwt.client.selection.support.InternetExplorerSelectionSupport">
<when-type-is class="org.grammaticalframework.ui.gwt.client.selection.support.SelectionSupport"/>
<when-property-is name="user.agent" value="ie6"/>
</replace-with>
<!-- Specify the app entry point class. -->
<entry-point class="org.grammaticalframework.ui.gwt.client.EditorApp" />

View File

@@ -0,0 +1,267 @@
package org.grammaticalframework.ui.gwt.client;
import java.util.*;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.http.client.*;
import com.google.gwt.xml.client.*;
import com.google.gwt.event.logical.shared.*;
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();
VerticalPanel vPanel = new VerticalPanel();
vPanel.add(createSearchPanel(oracle));
vPanel.add(createTreeView());
browsePanel.add(vPanel);
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) {
callBrowse(BrowsePanel.this,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);
History.newItem("browse:"+id);
}
public void browse(final String id) {
if (id == null || id.equals("")) {
sourceView.setHTML("");
return;
}
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 createTreeView() {
hierarchyTree = new Tree();
hierarchyTree.addSelectionHandler(new SelectionHandler<TreeItem>() {
public void onSelection(SelectionEvent<TreeItem> event) {
TreeItem item = event.getSelectedItem();
callBrowse(BrowsePanel.this,item.getText());
}
});
return hierarchyTree;
}
protected Widget createSourcePanel() {
sourceView = new HTML();
sourceView.setStylePrimaryName("source");
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;
}
}
Tree hierarchyTree = null;
protected void reloadHierarchyTree() {
hierarchyTree.clear();
final String url = pgf.getGrammarURL()+".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())
{
try
{
Document browseDoc = XMLParser.parse(response.getText());
TreeLoader loader = new TreeLoader();
Element element = browseDoc.getDocumentElement();
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node instanceof Element) {
Element childElement = (Element) node;
TreeItem childItem = hierarchyTree.addItem(childElement.getAttribute("name"));
loader.push(childElement, childItem);
}
}
loader.execute();
}
catch (DOMException e)
{
}
}
else
{
}
}
public void onError(Request request, Throwable e)
{
}
});
}
catch (RequestException e)
{
}
}
private class TreeLoader implements Command {
private int count = 0;
private ArrayList<Element> elements = new ArrayList<Element>();
private ArrayList<TreeItem> items = new ArrayList<TreeItem>();
public void execute() {
for (int n = 0; n < 100; n++) {
if (count <= 0)
return;
int index = --count;
Element element = (Element) elements.remove(index);
TreeItem item = (TreeItem) items.remove(index);
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node instanceof Element) {
Element childElement = (Element) node;
TreeItem childItem = item.addItem(childElement.getAttribute("name"));
push(childElement, childItem);
}
}
}
DeferredCommand.addCommand(this);
}
public final void push(Element element, TreeItem item) {
elements.add(element);
items.add(item);
count++;
}
}
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("");
reloadHierarchyTree();
}
public void onInputLanguageChanged() { }
public void onOutputLanguageChanged() { }
public void onStartCategoryChanged() { }
public void onSettingsError(String msg, Throwable e) { }
}
}

View File

@@ -0,0 +1,460 @@
package org.grammaticalframework.ui.gwt.client;
import java.util.*;
import com.google.gwt.core.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.*;
import com.google.gwt.event.shared.*;
public class EditorApp implements EntryPoint {
protected static final String pgfBaseURL = "/grammars";
protected PGFWrapper pgf;
protected VerticalPanel outputPanel;
protected Widget translatePanel;
protected BrowsePanel browsePanel;
protected QueryPanel queryPanel;
protected StatusPopup statusPopup;
protected TextInputPanel textPanel;
protected FridgeBagPanel bagPanel;
protected MagnetFactory magnetFactory;
private JSONRequest completeRequest = null;
private JSONRequest translateRequest = null;
private int maxMagnets = 100;
private static final int LIMIT_SCALE_FACTOR = 4;
private String cachedPrefix = null;
private List<Magnet> cachedMagnets = Collections.emptyList();
//
// Update
//
protected void update() {
clearMagnetCache();
updateBag("");
updateTranslation();
}
protected void clearMagnetCache() {
cachedPrefix = null;
cachedMagnets = Collections.emptyList();
}
protected void updateTranslation() {
if (translateRequest != null) {
translateRequest.cancel();
}
outputPanel.clear();
outputPanel.addStyleDependentName("working");
translateRequest = pgf.translate(textPanel.getText(),
new PGF.TranslateCallback() {
public void onResult (PGF.Translations translations) {
translateRequest = null;
outputPanel.clear();
outputPanel.removeStyleDependentName("working");
for (PGF.TranslationResult tr : translations.iterable()) {
textPanel.renderBracketedString(tr.getBracketedString());
if (tr.getTranslations() != null)
for (PGF.Translation t : tr.getTranslations().iterable()) {
LinearizationsPanel lin = new LinearizationsPanel(pgf, t.getTree(), t.getLinearizations());
lin.setWidth("100%");
outputPanel.add(lin);
}
if (tr.getTypeErrors() != null && tr.getTypeErrors().length > 0) {
for (PGF.TcError error : tr.getTypeErrors()) {
VerticalPanel panel = new VerticalPanel();
panel.addStyleName("my-typeError");
Label errLabel = new Label("Type Error");
errLabel.addStyleName("title");
panel.add(errLabel);
panel.add(createErrorMsg(error));
outputPanel.add(panel);
}
textPanel.showError(tr.getTypeErrors()[0].getFId());
}
}
}
public void onError (Throwable e) {
translateRequest = null;
showError("Translation failed", e);
}
});
}
private class Callback {
private String prefix;
public Callback(String prefix) {
this.prefix = prefix;
}
public void onResult(List<Magnet> magnets) {
bagPanel.fill(magnets);
if (magnets.size() == 0) {
if (prefix.isEmpty()) {
textPanel.hideSearchBox();
textPanel.setFocus(true);
}
else
textPanel.showSearchError();
} else {
textPanel.clearSearchError();
}
}
}
public void updateBag(String prefix) {
Callback callback = new Callback(prefix);
List<Magnet> magnets = filterCachedMagnets(prefix);
if (magnets != null)
callback.onResult(magnets);
else
retrieveMagnets(prefix, callback);
}
public List<Magnet> filterCachedMagnets(final String prefix) {
if (prefix.length() > 0 && cachedPrefix != null && prefix.startsWith(cachedPrefix)) {
// If the prefix had no completions, there is no way that the current input will.
if (cachedMagnets.isEmpty()) {
return Collections.emptyList();
}
List<Magnet> magnets = new ArrayList<Magnet>();
for (Magnet magnet : cachedMagnets) {
if (magnet.getWord().startsWith(prefix)) {
magnets.add(magnet);
if (magnets.size() >= maxMagnets)
return magnets;
}
}
}
return null;
}
public void retrieveMagnets(final String prefix, final Callback callback) {
final String query = textPanel.getText() + " " + prefix;
if (completeRequest != null) {
completeRequest.cancel();
}
bagPanel.clear();
completeRequest = pgf.complete(query, LIMIT_SCALE_FACTOR * maxMagnets,
new PGF.CompleteCallback() {
public void onResult(PGF.Completions completions) {
completeRequest = null;
cachedPrefix = query;
cachedMagnets = new ArrayList<Magnet>();
for (PGF.Completion completion : completions.iterable()) {
textPanel.renderBracketedString(completion.getBracketedString());
if (completion.getCompletions() != null) {
if (completion.getText() != prefix)
textPanel.setSearchTerm(completion.getText());
for (String word : completion.getCompletions()) {
Magnet magnet = magnetFactory.createMagnet(word, completion.getFrom());
cachedMagnets.add(magnet);
}
} else {
textPanel.setSearchTerm(completion.getText());
}
}
List<Magnet> magnets = new ArrayList<Magnet>();
for (Magnet magnet : cachedMagnets) {
magnets.add(magnet);
if (magnets.size() >= maxMagnets)
break;
}
callback.onResult(magnets);
}
public void onError(Throwable e) {
completeRequest = null;
showError("Getting completions failed", e);
}
});
}
//
// 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();
queryPanel = createQueryPanel();
VerticalPanel vPanel = new VerticalPanel();
vPanel.setWidth("100%");
vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
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.add(hPanel);
vPanel.add(translatePanel);
History.newItem("translate");
History.addHistoryListener(new MyHistoryListener(vPanel));
return vPanel;
}
protected Widget createSettingsPanel () {
return new SettingsPanel(pgf);
}
protected Widget createTranslatePanel() {
textPanel = new TextInputPanel();
textPanel.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
update();
}
});
textPanel.addSelectionHandler(new SelectionHandler<String>() {
public void onSelection(SelectionEvent<String> event) {
String prefix = event.getSelectedItem();
char lastChar = prefix.charAt(prefix.length()-1);
Iterator<Magnet> iter = bagPanel.iterator();
if ((Character.isSpace(lastChar) || lastChar == 160) && iter.hasNext()) {
Magnet magnet = iter.next();
textPanel.setSearchTerm("");
textPanel.addMagnet(magnet);
}
else
updateBag(prefix);
}
});
final ClickListener magnetClickListener = new ClickListener () {
public void onClick(Widget widget) {
Magnet magnet = (Magnet)widget;
textPanel.hideSearchBox();
textPanel.addMagnet(magnet);
textPanel.setFocus(true);
}
};
magnetFactory = new MagnetFactory(magnetClickListener);
bagPanel = new FridgeBagPanel();
outputPanel = new VerticalPanel();
outputPanel.addStyleName("my-translations");
final DockPanel translatePanel = new DockPanel();
translatePanel.setStyleName("my-TranslatePanel");
translatePanel.add(textPanel, DockPanel.NORTH);
translatePanel.add(bagPanel, DockPanel.CENTER);
translatePanel.add(outputPanel, DockPanel.EAST);
translatePanel.setCellHeight(bagPanel, "100%");
translatePanel.setCellWidth(bagPanel, "70%");
translatePanel.setCellHeight(outputPanel, "100%");
translatePanel.setCellWidth(outputPanel, "30%");
translatePanel.setCellVerticalAlignment(bagPanel, HasVerticalAlignment.ALIGN_TOP);
translatePanel.setCellHorizontalAlignment(outputPanel, HasHorizontalAlignment.ALIGN_RIGHT);
Window.addWindowResizeListener(new WindowResizeListener() {
public void onWindowResized(int w, int h) {
translatePanel.setPixelSize(w-20, h-50);
}
});
int w = Window.getClientWidth();
int h = Window.getClientHeight();
translatePanel.setPixelSize(w-20, h-50);
return translatePanel;
}
protected BrowsePanel createBrowsePanel() {
return new BrowsePanel(pgf);
}
protected QueryPanel createQueryPanel() {
return new QueryPanel(pgf);
}
protected Widget createLinksPanel(final Panel parent) {
HorizontalPanel linksPanel = new HorizontalPanel();
linksPanel.setStylePrimaryName("my-LinksPanel");
Hyperlink translateLink = new Hyperlink("Translate", "translate");
translateLink.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
parent.remove(browsePanel);
parent.remove(queryPanel);
parent.add(translatePanel);
}
});
linksPanel.add(translateLink);
Hyperlink queryLink = new Hyperlink("Query", "query");
queryLink.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
parent.remove(translatePanel);
parent.remove(browsePanel);
parent.add(queryPanel);
}
});
linksPanel.add(queryLink);
Hyperlink browseLink = new Hyperlink("Browse", "browse");
browseLink.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
parent.remove(translatePanel);
parent.remove(queryPanel);
parent.add(browsePanel);
browsePanel.onActivate();
}
});
linksPanel.add(browseLink);
return linksPanel;
}
protected Widget createErrorMsg(final PGF.TcError error) {
HTML msgHTML = new HTML("<pre>"+error.getMsg()+"</pre>");
msgHTML.addStyleName("content");
msgHTML.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
textPanel.showError(error.getFId());
}
});
return msgHTML;
}
//
// History stuff
//
protected class MyHistoryListener implements HistoryListener {
private final Panel parent;
public MyHistoryListener(Panel parent) {
this.parent = parent;
}
public void onHistoryChanged(String token) {
if (token.equals("translate")) {
parent.remove(queryPanel);
parent.remove(browsePanel);
parent.add(translatePanel);
} else if (token.equals("query")) {
parent.remove(translatePanel);
parent.remove(browsePanel);
parent.add(queryPanel);
} else if (token.equals("browse")) {
parent.remove(translatePanel);
parent.remove(queryPanel);
parent.add(browsePanel);
browsePanel.onActivate();
browsePanel.browse(null);
} else if (token.startsWith("browse:")) {
browsePanel.browse(token.substring(7));
}
}
};
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() {
textPanel.clear();
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());
pgf.updateAvailableGrammars();
textPanel.setFocus(true);
}
}

View File

@@ -1,108 +1,38 @@
package org.grammaticalframework.ui.gwt.client;
import java.util.LinkedHashSet;
import java.util.*;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.*;
public class FridgeBagPanel extends Composite {
public class FridgeBagPanel extends Composite implements Iterable<Magnet> {
private PGFWrapper pgf;
private FlowPanel mainPanel;
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");
public FridgeBagPanel () {
mainPanel = new FlowPanel();
VerticalPanel vPanel = new VerticalPanel();
vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
vPanel.add(prefixPanel);
vPanel.add(mainPanel);
initWidget(new ScrollPanel(vPanel));
initWidget(new ScrollPanel(mainPanel));
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("");
public void clear() {
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()) {
for (String word : completion.getCompletions()) {
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 fill(List<Magnet> magnets) {
for (Magnet magnet : magnets) {
mainPanel.add(magnet);
}
if (mainPanel.getWidgetCount() == 0)
addStyleDependentName("empty");
else
removeStyleDependentName("empty");
}
/*
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);
}
public Iterator<Magnet> iterator() {
return (Iterator<Magnet>) (Iterator) mainPanel.iterator();
}
*/
}

View File

@@ -0,0 +1,150 @@
package org.grammaticalframework.ui.gwt.client;
import java.util.*;
import com.google.gwt.core.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.*;
import com.google.gwt.event.shared.*;
public class LinearizationsPanel extends Composite {
protected PGFWrapper pgf;
public LinearizationsPanel(PGFWrapper pgf, String tree, PGF.Linearizations lins) {
this.pgf = pgf;
HorizontalPanel hPanel = new HorizontalPanel();
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(tree));
btnPanel.add(createAlignButton(tree));
hPanel.add(btnPanel);
hPanel.setCellHorizontalAlignment(btnPanel,HasHorizontalAlignment.ALIGN_RIGHT);
for (PGF.Linearization l : lins.iterable()) {
linsPanel.add(createTranslation(l.getTo(), tree, l.getText()));
}
initWidget(hPanel);
setStylePrimaryName("my-translation-frame");
}
protected Widget createAbsTreeButton(final String abstractTree) {
Image treeBtn = new Image("org.grammaticalframework.ui.gwt.EditorApp/tree-btn.png");
treeBtn.setTitle("Displays the abstract syntax tree.");
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("org.grammaticalframework.ui.gwt.EditorApp/align-btn.png");
alignBtn.setTitle("Displays word-alignment diagram.");
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;
}
}

View File

@@ -0,0 +1,49 @@
package org.grammaticalframework.ui.gwt.client;
import java.util.*;
import com.google.gwt.core.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.*;
import com.google.gwt.event.shared.*;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Text;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Document;
import org.grammaticalframework.ui.gwt.client.selection.*;
public class MagnetSearchBox extends FocusWidget {
public MagnetSearchBox() {
this(Document.get().createDivElement());
}
public MagnetSearchBox(Element elem) {
super(elem);
elem.setAttribute("contentEditable", "true");
setStyleName("searchbox");
}
public String getText() {
return getElement().getInnerText();
}
public void setText(String s) {
getElement().setInnerText(s);
}
public int getCursorPos() {
return 0;
}
public void setCursorPos(int pos) {
Node child = getElement().getFirstChild();
if (child instanceof Text) {
SelectionEndPoint selPoint = new SelectionEndPoint((Text) child,pos);
Selection sel = Selection.getSelection();
sel.select(selPoint,selPoint);
}
return;
}
}

View File

@@ -74,17 +74,6 @@ public class PGF {
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 */
/**
@@ -152,20 +141,6 @@ public class PGF {
public final native int getFId() /*-{ return this.fid; }-*/;
public final native int getIndex() /*-{ return this.index; }-*/;
public final native BracketedString[] getChildren() /*-{ return this.children; }-*/;
public final String render() {
if (getToken() != null)
return getToken();
else {
StringBuilder sbuilder = new StringBuilder();
for (BracketedString bs : getChildren()) {
if (sbuilder.length() > 0)
sbuilder.append(' ');
sbuilder.append(bs.render());
}
return sbuilder.toString();
}
}
}
public static class TcError extends JavaScriptObject {
@@ -174,6 +149,29 @@ public class PGF {
public final native int getFId() /*-{ return this.fid; }-*/;
public final native String getMsg() /*-{ return this.msg; }-*/;
}
/* Linearization */
public JSONRequest linearize (String pgfURL, String tree, String toLang, final LinearizeCallback callback) {
List<Arg> args = new ArrayList<Arg>();
args.add(new Arg("tree", tree));
args.add(new Arg("to", toLang));
return sendGrammarRequest(pgfURL, "linearize", args, callback);
}
public interface LinearizeCallback extends JSONCallback<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; }-*/;
}
public String graphvizAbstractTree(String pgfURL, String abstractTree) {
List<Arg> args = new ArrayList<Arg>();
@@ -216,8 +214,20 @@ public class PGF {
return request;
}
public JSONRequest query(String pgfURL, String query, QueryCallback callback) {
List<Arg> args = new ArrayList<Arg>();
args.add(new Arg("cat", query));
return sendGrammarRequest(pgfURL, "query", args, callback);
}
public interface QueryCallback extends JSONCallback<QueryResult> {}
/* Common */
public static class QueryResult extends JavaScriptObject {
protected QueryResult() { }
public final native String[] getRows() /*-{ return this.rows; }-*/;
}
public <T extends JavaScriptObject> JSONRequest sendGrammarRequest(String pgfURL, String resource, List<Arg> args, final JSONCallback<T> callback) {
args.add(new Arg("command", resource));

View File

@@ -138,6 +138,10 @@ public class PGFWrapper {
return pgf.parse(grammarURL, input, inputLanguage, cat, callback);
}
public JSONRequest linearize (String tree, final PGF.LinearizeCallback callback) {
return pgf.linearize(grammarURL, tree, outputLanguage, callback);
}
public String graphvizAbstractTree(String abstractTree) {
return pgf.graphvizAbstractTree(grammarURL,abstractTree);
}
@@ -154,6 +158,10 @@ public class PGFWrapper {
return pgf.browse(grammarURL, id, href, cssClass, callback);
}
public JSONRequest query(String query, PGF.QueryCallback callback) {
return pgf.query(grammarURL, query, callback);
}
//
// Settings
//
@@ -242,7 +250,7 @@ public class PGFWrapper {
PGF.Language l = languages.get(language);
return l == null ? null : l.getLanguageCode();
}
public Collection<String> getAllLanguages() {
return languages.keySet();
}

View File

@@ -0,0 +1,109 @@
package org.grammaticalframework.ui.gwt.client;
import java.util.*;
import com.google.gwt.http.client.*;
import com.google.gwt.user.client.ui.*;
public class QueryPanel extends Composite {
private PGFWrapper pgf;
public QueryPanel(PGFWrapper pgf) {
this.pgf = pgf;
VerticalPanel vPanel = new VerticalPanel();
vPanel.add(createQueryPanel());
initWidget(vPanel);
setStylePrimaryName("my-QueryPanel");
pgf.addSettingsListener(new MySettingsListener(pgf));
}
protected Widget createQueryPanel() {
final TextArea queryBox = new TextArea();
queryBox.setStylePrimaryName("my-QueryBox");
final Grid resultGrid = new Grid(0, 1);
resultGrid.setStylePrimaryName("my-ResultGrid");
resultGrid.setBorderWidth(3);
Button execButton = new Button("Execute");
execButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
pgf.query(queryBox.getText(), new PGF.QueryCallback() {
public void onResult(PGF.QueryResult result) {
while (resultGrid.getRowCount() > 0) {
resultGrid.removeRow(resultGrid.getRowCount() - 1);
}
ClickListener labelClickListener = new ClickListener() {
public void onClick(Widget sender) {
final Label label = (Label) sender;
pgf.linearize(label.getText(), new PGF.LinearizeCallback() {
public void onResult(PGF.Linearizations result) {
final PopupPanel popup = new PopupPanel(true);
popup.setWidget(new LinearizationsPanel(pgf, label.getText(), result));
popup.setPopupPosition(label.getAbsoluteLeft(),
label.getAbsoluteTop()+label.getOffsetHeight());
popup.show();
}
public void onError(Throwable e) {
}
});
}
};
int row = 0;
for (String tree : result.getRows()) {
Label label = new Label(tree);
label.addClickListener(labelClickListener);
resultGrid.insertRow(row);
resultGrid.setWidget(row, 0, label);
row++;
}
}
public void onError(Throwable e) {
}
});
}
});
DecoratorPanel queryDecorator = new DecoratorPanel();
VerticalPanel vPanel = new VerticalPanel();
vPanel.add(new Label("Query"));
HorizontalPanel hPanel = new HorizontalPanel();
hPanel.add(queryBox);
hPanel.add(execButton);
vPanel.add(hPanel);
queryDecorator.add(vPanel);
VerticalPanel queryPanel = new VerticalPanel();
queryPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
queryPanel.add(queryDecorator);
queryPanel.add(resultGrid);
return queryPanel;
}
protected class MySettingsListener implements PGFWrapper.SettingsListener {
private PGFWrapper pgf;
public MySettingsListener(PGFWrapper pgf) {
this.pgf = pgf;
}
public void onAvailableGrammarsChanged() { }
public void onSelectedGrammarChanged() { }
public void onInputLanguageChanged() { }
public void onOutputLanguageChanged() { }
public void onStartCategoryChanged() { }
public void onSettingsError(String msg, Throwable e) { }
}
}

View File

@@ -0,0 +1,547 @@
package org.grammaticalframework.ui.gwt.client;
import java.util.*;
import com.google.gwt.core.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.*;
import com.google.gwt.event.shared.*;
public class TextInputPanel extends Composite implements Focusable, HasValueChangeHandlers<String>, HasSelectionHandlers<String> {
protected FlowPanel textPanel = null;
protected FlowPanel mainPanel = null;
protected FocusPanel focusPanel = null;
protected Panel focusedPanel = null;
protected List<Panel> selectedPanels = null;
protected List<Panel> errorPanels = null;
protected Panel tempPanel = null;
protected Label status = null;
protected NavigationController navigationController;
protected MagnetSearchBox searchBox = null;
private List<Label> words = new ArrayList<Label>();
private Map<Panel, Phrase> mapPanel2Phrase = new HashMap<Panel, Phrase>();
private Map<Integer, Phrase> mapFId2Phrase = new HashMap<Integer, Phrase>();
private ChangeListenerCollection changeListeners = null;
public TextInputPanel() {
mainPanel = new FlowPanel();
mainPanel.setStylePrimaryName("wordspanel");
textPanel = new FlowPanel();
textPanel.add(mainPanel);
textPanel.setStylePrimaryName("wordspanel");
Label space = new Label(" ");
space.setStylePrimaryName("wordspace");
textPanel.add(space);
Panel contentPanel = new FlowPanel();
contentPanel.add(textPanel);
contentPanel.setStylePrimaryName("text");
focusPanel = new FocusPanel();
focusPanel.setWidget(contentPanel);
focusPanel.setStylePrimaryName("frame");
Widget buttons = createToolbarPanel();
VerticalPanel wrapper = new VerticalPanel();
wrapper.add(buttons);
wrapper.add(focusPanel);
initWidget(wrapper);
setStylePrimaryName("my-TextInputPanel");
navigationController = new NavigationController();
focusPanel.addKeyDownHandler(navigationController);
}
protected Widget createToolbarPanel() {
HorizontalPanel toolbar = new HorizontalPanel();
toolbar.setStylePrimaryName("toolbar");
Panel buttons = new HorizontalPanel();
toolbar.add(buttons);
toolbar.setCellHorizontalAlignment(buttons,HorizontalPanel.ALIGN_LEFT);
toolbar.setCellVerticalAlignment(buttons,HorizontalPanel.ALIGN_MIDDLE);
Image clearButton = new Image("org.grammaticalframework.ui.gwt.EditorApp/textinput-buttons.png",0,0,20,20);
clearButton.setTitle("Clears the whole text.");
clearButton.setStylePrimaryName("button");
clearButton.addClickListener(new ClickListener () {
public void onClick(Widget sender) {
clear();
}
});
buttons.add(clearButton);
Image deleteLastButton = new Image("org.grammaticalframework.ui.gwt.EditorApp/textinput-buttons.png",20,0,20,20);
deleteLastButton.setTitle("Removes the last word.");
deleteLastButton.setStylePrimaryName("button");
deleteLastButton.addClickListener(new ClickListener () {
public void onClick(Widget sender) {
deleteLast();
}
});
buttons.add(deleteLastButton);
status = new Label();
status.setTitle("The currently selected category.");
status.setStylePrimaryName("status");
toolbar.add(status);
toolbar.setCellHorizontalAlignment(status,HorizontalPanel.ALIGN_RIGHT);
toolbar.setCellVerticalAlignment(status,HorizontalPanel.ALIGN_MIDDLE);
return toolbar;
}
public void renderBracketedString(final PGF.BracketedString bs) {
words.clear();
mapPanel2Phrase.clear();
mapFId2Phrase.clear();
mainPanel.clear();
selectedPanels = null;
focusedPanel = null;
errorPanels = null;
tempPanel = null;
Widget widget = createWordPanels(bs);
mainPanel.add(widget);
}
private Widget createWordPanels(final PGF.BracketedString bs) {
if (bs.getToken() != null) {
Label wordLabel = new Label(bs.getToken());
wordLabel.setStylePrimaryName("wordlabel");
wordLabel.addClickListener(navigationController);
words.add(wordLabel);
return wordLabel;
} else {
FlowPanel panel = new FlowPanel();
panel.setStylePrimaryName("wordspanel");
Integer fid = new Integer(bs.getFId());
Phrase phrase = mapFId2Phrase.get(fid);
if (phrase == null) {
phrase = new Phrase();
phrase.cat = bs.getCat();
phrase.panels = new ArrayList<Panel>();
mapFId2Phrase.put(fid,phrase);
}
phrase.panels.add(panel);
mapPanel2Phrase.put(panel, phrase);
for (PGF.BracketedString child : bs.getChildren()) {
if (panel.getWidgetCount() > 0) {
Label space = new Label(" ");
space.setStylePrimaryName("wordspace");
panel.add(space);
}
panel.add(createWordPanels(child));
}
return panel;
}
}
public void clear() {
setSearchTerm("");
words.clear();
mapPanel2Phrase.clear();
mapFId2Phrase.clear();
mainPanel.clear();
selectedPanels = null;
focusedPanel = null;
errorPanels = null;
tempPanel = null;
fireValueChange();
}
public void addMagnet(Magnet magnet) {
Label wordLabel = new Label(magnet.getText());
wordLabel.setStylePrimaryName("wordlabel");
getTempPanel().add(wordLabel);
words.add(wordLabel);
fireValueChange();
}
public String deleteLast() {
int wordsCount = words.size();
if (wordsCount <= 0)
return null;
Label lastWord = words.remove(wordsCount-1);
setSearchTerm("");
mapPanel2Phrase.clear();
mapFId2Phrase.clear();
mainPanel.clear();
selectedPanels = null;
focusedPanel = null;
errorPanels = null;
tempPanel = null;
for (Label word : words) {
if (((FlowPanel) getTempPanel()).getWidgetCount() > 0) {
Label space = new Label(" ");
space.setStylePrimaryName("wordspace");
getTempPanel().add(space);
}
getTempPanel().add(word);
}
fireValueChange();
return lastWord.getText();
}
public void showSearchBox() {
if (searchBox == null) {
searchBox = new MagnetSearchBox();
SearchBoxKeyboardHandler handler = new SearchBoxKeyboardHandler();
searchBox.addKeyUpHandler(handler);
searchBox.addKeyDownHandler(handler);
textPanel.add(searchBox);
searchBox.setFocus(true);
}
}
public void hideSearchBox() {
if (searchBox != null) {
searchBox.removeFromParent();
searchBox = null;
}
}
public void setSearchTerm(String term) {
if (searchBox != null) {
searchBox.setText(term);
if ("".equals(term))
searchBox.setCursorPos(0);
}
}
public String getSearchTerm() {
if (searchBox != null)
return searchBox.getText();
else
return null;
}
public void showSearchError() {
if (searchBox != null) {
searchBox.addStyleDependentName("error");
}
}
public void clearSearchError() {
if (searchBox != null) {
searchBox.removeStyleDependentName("error");
}
}
public void showError(int fid) {
if (errorPanels != null) {
for (Panel panel : errorPanels) {
panel.removeStyleDependentName("error");
}
errorPanels = null;
}
Phrase phrase = mapFId2Phrase.get(fid);
if (phrase != null) {
errorPanels = phrase.panels;
if (errorPanels != null) {
for (Panel selPanel : errorPanels) {
selPanel.addStyleDependentName("error");
}
}
}
}
private Panel getTempPanel() {
if (tempPanel == null) {
if (mainPanel.getWidgetCount() > 0) {
Label space = new Label(" ");
space.setStylePrimaryName("wordspace");
mainPanel.add(space);
}
tempPanel = new FlowPanel();
tempPanel.setStylePrimaryName("wordspanel");
mainPanel.add(tempPanel);
}
return tempPanel;
}
protected void fireValueChange() {
DeferredCommand.addCommand(new Command() {
public void execute() {
ValueChangeEvent.fire(TextInputPanel.this, getText());
}
});
}
protected void fireSelection() {
SelectionEvent.fire(this, (searchBox == null) ? "" : searchBox.getText());
}
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
public HandlerRegistration addSelectionHandler(SelectionHandler<String> handler) {
return addHandler(handler, SelectionEvent.getType());
}
public String getText () {
StringBuilder sb = new StringBuilder();
for (Label word : words) {
if (sb.length() > 0) {
sb.append(' ');
}
sb.append(word.getText());
}
return sb.toString();
}
public int getTabIndex() {
return focusPanel.getTabIndex();
}
public void setTabIndex(int index) {
focusPanel.setTabIndex(index);
}
public void setAccessKey(char key) {
focusPanel.setAccessKey(key);
}
public void setFocus(boolean focused) {
focusPanel.setFocus(focused);
}
private class Phrase {
public String cat;
public ArrayList<Panel> panels;
}
private final class NavigationController implements KeyDownHandler, ClickListener {
public void onKeyDown(KeyDownEvent event) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_UP:
if (focusedPanel != null) {
Panel firstUp = null;
FlowPanel parent = (FlowPanel) focusedPanel.getParent();
while (parent != mainPanel) {
if (parent.getWidgetCount() > 1) {
firstUp = parent;
break;
}
parent = (FlowPanel) parent.getParent();
}
if (firstUp != null)
setFocusedPanel(firstUp);
event.stopPropagation();
}
break;
case KeyCodes.KEY_DOWN:
if (focusedPanel != null) {
Panel firstDown = null;
for (Widget child : focusedPanel) {
if (child instanceof Panel) {
firstDown = (Panel) child;
break;
}
}
if (firstDown != null)
setFocusedPanel(firstDown);
event.stopPropagation();
}
break;
case KeyCodes.KEY_LEFT:
if (focusedPanel != null) {
Panel firstLeft = null;
Panel parent = (Panel) focusedPanel.getParent();
for (Widget child : parent) {
if (child instanceof Panel) {
if (child == focusedPanel)
break;
firstLeft = (Panel) child;
}
}
if (firstLeft == null) {
if (parent != mainPanel)
firstLeft = parent;
} else {
for (;;) {
Panel lastChild = null;
for (Widget child : firstLeft) {
if (child instanceof Panel) {
lastChild = (Panel) child;
}
}
if (lastChild == null)
break;
firstLeft = lastChild;
}
}
if (firstLeft != null)
setFocusedPanel(firstLeft);
event.stopPropagation();
}
break;
case KeyCodes.KEY_RIGHT:
if (focusedPanel != null) {
Panel firstRight = null;
Panel parent = (Panel) focusedPanel.getParent();
Widget prev = null;
for (Widget child : parent) {
if (child instanceof Panel) {
if (prev == focusedPanel) {
firstRight = (Panel) child;
break;
}
prev = child;
}
}
if (firstRight == null) {
if (parent != mainPanel)
firstRight = parent;
} else {
for (;;) {
Panel firstChild = null;
for (Widget child : firstRight) {
if (child instanceof Panel) {
firstChild = (Panel) child;
break;
}
}
if (firstChild == null)
break;
firstRight = firstChild;
}
}
if (firstRight != null)
setFocusedPanel(firstRight);
event.stopPropagation();
}
break;
case KeyCodes.KEY_ENTER:
case KeyCodes.KEY_ESCAPE:
break;
default:
if (searchBox == null) {
showSearchBox();
searchBox.fireEvent(event);
}
}
}
public void onClick(Widget sender) {
FlowPanel panel = (FlowPanel) sender.getParent();
FlowPanel tmpPanel = panel;
while (tmpPanel != mainPanel) {
FlowPanel parent = (FlowPanel) tmpPanel.getParent();
if (tmpPanel == focusedPanel && parent != mainPanel) {
panel = parent;
break;
}
tmpPanel = parent;
}
tmpPanel = (FlowPanel) panel.getParent();
while (tmpPanel != mainPanel) {
if (tmpPanel.getWidgetCount() > 1)
break;
panel = tmpPanel;
tmpPanel = (FlowPanel) panel.getParent();
}
setFocusedPanel(panel);
}
private void setFocusedPanel(Panel panel) {
if (selectedPanels != null) {
for (Panel tmpPanel : selectedPanels) {
tmpPanel.removeStyleDependentName("selected");
}
selectedPanels = null;
}
if (focusedPanel != null) {
focusedPanel.removeStyleDependentName("focused");
focusedPanel = null;
}
Phrase phrase = mapPanel2Phrase.get(panel);
if (phrase != null) {
status.setText(phrase.cat);
selectedPanels = phrase.panels;
if (selectedPanels != null) {
for (Panel selPanel : selectedPanels) {
selPanel.addStyleDependentName("selected");
}
}
focusedPanel = panel;
focusedPanel.addStyleDependentName("focused");
}
}
}
private final class SearchBoxKeyboardHandler implements KeyUpHandler, KeyDownHandler {
public void onKeyDown(KeyDownEvent event) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_ESCAPE:
hideSearchBox();
fireSelection();
setFocus(true);
event.stopPropagation();
break;
case KeyCodes.KEY_ENTER:
searchBox.setText(searchBox.getText()+" ");
fireSelection();
hideSearchBox();
setFocus(true);
event.stopPropagation();
break;
case KeyCodes.KEY_BACKSPACE:
if ("".equals(searchBox.getText())) {
String word = deleteLast();
searchBox.setText(word);
searchBox.setCursorPos(word.length());
event.stopPropagation();
event.preventDefault();
}
break;
}
}
public void onKeyUp(KeyUpEvent event) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_ESCAPE:
case KeyCodes.KEY_ENTER:
case KeyCodes.KEY_UP:
case KeyCodes.KEY_DOWN:
case KeyCodes.KEY_LEFT:
case KeyCodes.KEY_RIGHT:
break;
default:
fireSelection();
}
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright Miroslav Pokorny
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.grammaticalframework.ui.gwt.client.selection;
import org.grammaticalframework.ui.gwt.client.selection.support.SelectionSupport;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.RootPanel;
/**
* The Selection class is a singleton that represents any selection made by the
* user typically done with the mouse.
*
* @author Miroslav Pokorny (mP)
*/
public class Selection extends JavaScriptObject {
/**
* The browser aware support that takes care of browser difference nasties.
*/
static private SelectionSupport support = (SelectionSupport) GWT.create(SelectionSupport.class);
static SelectionSupport getSupport() {
return Selection.support;
}
/**
* Returns the document Selection singleton
*
* @return The singleton instance
*/
static public Selection getSelection() {
return Selection.support.getSelection();
}
protected Selection() {
super();
}
final public SelectionEndPoint getStart() {
return Selection.getSupport().getStart(this);
}
final public SelectionEndPoint getEnd() {
return Selection.getSupport().getEnd(this);
}
final public void select(final SelectionEndPoint start, final SelectionEndPoint end) {
Selection.getSupport().select(this, start, end);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright Miroslav Pokorny
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.grammaticalframework.ui.gwt.client.selection;
import com.google.gwt.dom.client.Text;
/**
* An end point uses a combination of a textNode and offset to mark the
* start/end of a selection
*
* @author Miroslav Pokorny (mP)
*/
public class SelectionEndPoint {
public SelectionEndPoint() {
super();
}
public SelectionEndPoint(Text text, final int offset) {
super();
this.setTextNode(text);
this.setOffset(offset);
}
/**
* The textNode containing the start/end of the selection.
*/
private Text textNode;
public Text getTextNode() {
return textNode;
}
public void setTextNode(final Text textNode) {
this.textNode = textNode;
}
/**
* The number of characters starting from the beginning of the textNode
* where the selection begins/ends.
*/
public int offset;
public int getOffset() {
return offset;
}
public void setOffset(final int offset) {
this.offset = offset;
}
public String toString() {
return super.toString() + ", offset: " + offset + ", textNode\"" + this.textNode + "\"";
}
}

View File

@@ -0,0 +1,248 @@
/*
* Copyright Miroslav Pokorny
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.grammaticalframework.ui.gwt.client.selection.support;
import org.grammaticalframework.ui.gwt.client.selection.Selection;
import org.grammaticalframework.ui.gwt.client.selection.SelectionEndPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Text;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
/**
* A specialised SelectionSupport class that is adapted to handle
* InternetExplorer differences from the standard implementation.
*
* @author Miroslav Pokorny (mP)
*/
public class InternetExplorerSelectionSupport extends SelectionSupport {
final static String PARENT_NODE = "parentNode";
@Override
native public Selection getSelection()/*-{
return $wnd.document.selection;
}-*/;
@Override
public SelectionEndPoint getStart(final Selection selection) {
return this.getStart0(selection);
}
native protected SelectionEndPoint getStart0(final Selection selection) /*-{
var selectionRange = selection.createRange();
var element = selectionRange.parentElement();
return this.@org.grammaticalframework.ui.gwt.client.selection.support.InternetExplorerSelectionSupport::getStart1(Lorg/grammaticalframework/ui/gwt/client/selection/Selection;Lcom/google/gwt/user/client/Element;)(selection,element);
}-*/;
native protected SelectionEndPoint getStart1(final Selection selection, final Element element)/*-{
var endPoint = null;
if(! selection.createRange ){
alert( "selection.createRange" + selection.createRange );
}
var selectionRange = selection.createRange();
var range = selectionRange.duplicate();
range.moveToElementText( element );
range.collapse();
// loop thru all the childNodes belonging to element.
var childNodes = element.childNodes;
for( var i = 0; i < childNodes.length; i++ ){
var node = childNodes[ i ];
var nodeType = node.nodeType;
// found an element check its child nodes...
if( 1 == nodeType ){
endPoint = this.@org.grammaticalframework.ui.gwt.client.selection.support.InternetExplorerSelectionSupport::getStart1(Lorg/grammaticalframework/ui/gwt/client/selection/Selection;Lcom/google/gwt/user/client/Element;)(selection,node);
if( null == endPoint ){
range.move( "character", node.innerText.toString().length );
continue;
}
// endPoint found stop searching....
break;
}
// found a textNode...
if( 3 == nodeType ){
var text = node.data;
for( var j = 0; j < text.length; j++ ){
// found selection start stop searching!
if( selectionRange.compareEndPoints( "StartToStart", range ) == 0 ){
endPoint = @org.grammaticalframework.ui.gwt.client.selection.SelectionEndPoint::new(Lcom/google/gwt/dom/client/Text;I)(node,j);
break;
}
range.move("character", 1 );
}
// did the above for loop find the start ? if so stop escape!
if( null != endPoint ){
break;
}
}
}
return endPoint;
}-*/;
@Override
public void select(final Selection selection, final SelectionEndPoint start, final SelectionEndPoint end) {
this.setStart0(selection, start.getTextNode(), start.getOffset());
this.setEnd0(selection, end.getTextNode(), end.getOffset());
}
native private void setStart0(final Selection selection, final Text textNode, final int offset)/*-{
var rangeOffset = offset;
var moveToElement = null;
// try an element before $textNode counting the number of characters one has moved backwards...
var node = textNode.previousSibling;
while( node ){
// if a textNode is try its previous sibling...
if( node.nodeType == 3 ){
rangeOffset = rangeOffset + node.data.length;
continue;
}
// found an element stop searching...
if( node.nodeType == 1 ){
moveToElement = node;
rangeOffset = rangeOffset + node.innerText.toString().length;
break;
}
// ignore other types...
node = node.previousSibling;
}
// if moveToElement is null use textNode's parent.
if( ! moveToElement ){
moveToElement = textNode.parentNode;
}
// update the start of selection range...
var range = selection.createRange();
range.moveToElementText( moveToElement );
range.moveStart( "character", rangeOffset );
range.select();
}-*/;
native private void setEnd0(final Selection selection, final Text textNode, final int offset)/*-{
var rangeOffset = offset;
var moveToElement = null;
// try an element before $textNode counting the number of characters one has moved backwards...
var node = textNode.previousSibling;
while( node ){
// if textNode is try its previous sibling...
if( node.nodeType == 3 ){
rangeOffset = rangeOffset + node.data.length;
continue;
}
// found an element stop searching...
if( node.nodeType == 1 ){
moveToElement = node;
rangeOffset = rangeOffset + node.innerText.toString().length;
break;
}
// ignore other types...
node = node.previousSibling;
}
// if moveToElement is null use textNode's parent.
if( ! moveToElement ){
moveToElement = textNode.parentNode;
}
// update the end of selection range...
var range = selection.createRange();
range.moveToElementText( moveToElement );
range.moveStart( "character", rangeOffset );
range.collapse();
var selectionRange = selection.createRange();
selectionRange.setEndPoint( "EndToStart", range );
selectionRange.select();
}-*/;
@Override
public SelectionEndPoint getEnd(final Selection selection) {
return this.getEnd0(selection);
}
protected native SelectionEndPoint getEnd0(final Selection selection) /*-{
var selectionRange = selection.createRange();
var element = selectionRange.parentElement();
return this.@org.grammaticalframework.ui.gwt.client.selection.support.InternetExplorerSelectionSupport::getEnd1(Lorg/grammaticalframework/ui/gwt/client/selection/Selection;Lcom/google/gwt/user/client/Element;)(selection,element);
}-*/;
protected native SelectionEndPoint getEnd1(final Selection selection, final Element element)/*-{
var endPoint = null;
var selectionRange = selection.createRange();
var range = selectionRange.duplicate();
range.moveToElementText( element );
range.collapse( true );
// loop thru all the childNodes belonging to element.
var childNodes = element.childNodes;
for( var i = 0; i < childNodes.length; i++ ){
var node = childNodes[ i ];
var nodeType = node.nodeType;
// found an element check its child nodes...
if( 1 == nodeType ){
endPoint = this.@org.grammaticalframework.ui.gwt.client.selection.support.InternetExplorerSelectionSupport::getEnd1(Lorg/grammaticalframework/ui/gwt/client/selection/Selection;Lcom/google/gwt/user/client/Element;)(selection,node);
if( null == endPoint ){
range.move( "character", node.innerText.toString().length );
continue;
}
// endPoint found stop searching....
break;
}
// found a textNode...
if( 3 == nodeType ){
var text = node.data;
for( var j = 0; j < text.length; j++ ){
// found selection end stop searching!
if( selectionRange.compareEndPoints( "EndToStart", range ) == 0 ){
endPoint = @org.grammaticalframework.ui.gwt.client.selection.SelectionEndPoint::new(Lcom/google/gwt/dom/client/Text;I)(node,j);
break;
}
range.move( "character", 1 );
}
// did the above for loop find the end ? if so stop escape!
if( null != endPoint ){
break;
}
}
}
return endPoint;
}-*/;
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright Miroslav Pokorny
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.grammaticalframework.ui.gwt.client.selection.support;
import org.grammaticalframework.ui.gwt.client.selection.Selection;
import org.grammaticalframework.ui.gwt.client.selection.SelectionEndPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Text;
import com.google.gwt.user.client.Element;
/**
* This class provides the standard implementation of
*
* @author Miroslav Pokorny (mP)
*/
public class SelectionSupport {
public SelectionEndPoint getStart(final Selection selection) {
return getStart0(selection);
}
native private SelectionEndPoint getStart0(final Selection selection) /*-{
var node = selection.anchorNode || null;
var offset = selection.anchorOffset;
return @org.grammaticalframework.ui.gwt.client.selection.SelectionEndPoint::new(Lcom/google/gwt/dom/client/Text;I)(value,j);
}-*/;
public SelectionEndPoint getEnd(final Selection selection) {
return getEnd0(selection);
}
native private SelectionEndPoint getEnd0(final Selection selection) /*-{
var node = selection.focusNode || null;
var offset = selection.focusOffset;
return @org.grammaticalframework.ui.gwt.client.selection.SelectionEndPoint::new(Lcom/google/gwt/dom/client/Text;I)(value,j);
}-*/;
public void select(final Selection selection, final SelectionEndPoint start, final SelectionEndPoint end) {
select0(selection, start.getTextNode(), start.getOffset(), end.getTextNode(), end.getOffset());
}
native private void select0(final Selection selection, final Text startNode, final int startOffset, final Text endNode, final int endOffset)/*-{
var range = startNode.ownerDocument.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
// delete all ranges then recreate...
selection.removeAllRanges();
selection.addRange(range);
}-*/;
native public Selection getSelection()/*-{
return $wnd.getSelection();
}-*/;
}

View File

@@ -0,0 +1,253 @@
/** Add css rules here for your application. */
.my-TranslatePanel {
padding-top: 1em;
padding-bottom: 1em
}
.my-TextInputPanel {
width: 100%;
}
.my-TextInputPanel .frame {
margin: 0;
padding: 1em;
background-color: #F3F3F3;
outline: 0;
}
.my-TextInputPanel .text {
padding: 1em;
background-color: white;
border-top: 1px solid #CCCCCC;
border-left: 1px solid #CCCCCC;
border-bottom: 2px solid #BBBBBB;
border-right: 2px solid #BBBBBB;
min-width: 100px;
min-height: 100px;
}
.my-TextInputPanel .toolbar {
width: 100%;
padding: 3px;
background-attachement: scroll;
background-color: #E5E5E5;
background-image: url("background.png");
background-position: 0px -192px;
background-repeat: repeat-x;
}
.my-TextInputPanel .toolbar .button {
float: left;
margin: 2px;
}
.my-TextInputPanel .toolbar .button:hover {
margin: 1px;
border: 1px solid rgb(147,194,241);
}
.my-TextInputPanel .toolbar .status {
padding: 1px;
background-color: #E5E5E5;
border: 1px solid #BBBBBB;
float: right;
}
.my-TextInputPanel .searchbox {
font-size: 150%;
padding: 2px;
display: inline;
border-bottom: 1px dashed green;
outline: 0;
}
.my-TextInputPanel .searchbox-error {
border-bottom: 1px dashed red;
}
.my-TextInputPanel .wordspanel {
padding: 0;
display: inline;
}
.my-TextInputPanel .wordspanel-selected {
background-color: rgb(147,194,241);
}
.my-TextInputPanel .wordspanel-focused {
background-color: rgb(147,194,241);
border: 1px solid #666;
}
.my-TextInputPanel .wordspanel-error {
border-bottom: 1px dashed red;
}
.my-TextInputPanel .wordlabel {
display: inline;
font-size: 150%;
}
.my-TextInputPanel .wordspace {
display: inline;
font-size: 150%;
}
.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-BrowsePanel .source {
padding: 1em;
}
.my-BrowseFrame {
width: 100%;
height: 100%;
margin: 1em;
border-style:none;
}
.my-QueryPanel {
margin: 1em;
border-width: 5px;
border-color: rgb(122,165,214);
}
.my-QueryBox {
min-width: 630px;
min-height: 94px;
}
.my-ResultGrid {
margin: 1em;
}
.my-translations {
margin-top: 1em;
}
.my-translation-frame {
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-translation-btns {
background: #DDDDDD;
cursor:pointer;
}
.my-treeimage {
width: 650px;
height: 520px;
}
.my-alignmentimage {
width: 450px;
height: 300px;
}
.my-typeError {
margin: 2px;
padding: 12px;
font-size: 150%;
font-weight: bold;
background: #CDFFDA;
}
.my-typeError .title {
background: #DDDDDD;
}
.my-typeError .content {
cursor:pointer;
}
.my-identifierLink:link {
text-decoration: none;
color: black;
}
.my-identifierLink:hover {
text-decoration: none;
color: black;
background-color: rgb(147, 194, 241);
}
.my-FridgeBagPanel {
padding: 0.2em;
margin-top: 1.5em;
border: 3px solid #dddddd;
}
.my-FridgeBagPanel-empty {
visibility: hidden;
}
.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-SyntaxTable {
font-size: 120%;
}
.my-SyntaxRow {
margin: 1px;
}
.my-SyntaxLang {
background: rgb(147,194,241);
padding: 2px;
}
.my-SyntaxLin {
border: 1px solid rgb(147,194,241);
padding-left: 8px;
padding-right: 8px;
padding-top: 2px;
padding-bottom: 2px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B