mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-22 19:22:50 -06:00
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:
@@ -13,8 +13,10 @@
|
|||||||
<!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
|
<!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
|
||||||
<!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> -->
|
<!-- <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. -->
|
<!-- Specify the app entry point class. -->
|
||||||
<entry-point class="org.grammaticalframework.ui.gwt.client.EditorApp" />
|
<entry-point class="org.grammaticalframework.ui.gwt.client.EditorApp" />
|
||||||
|
|||||||
@@ -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) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,108 +1,38 @@
|
|||||||
package org.grammaticalframework.ui.gwt.client;
|
package org.grammaticalframework.ui.gwt.client;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.*;
|
||||||
|
|
||||||
import com.google.gwt.core.client.GWT;
|
import com.google.gwt.core.client.GWT;
|
||||||
import com.google.gwt.user.client.ui.*;
|
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;
|
public FridgeBagPanel () {
|
||||||
|
|
||||||
private JSONRequest completeRequest = null;
|
|
||||||
|
|
||||||
private FlowPanel prefixPanel;
|
|
||||||
|
|
||||||
private FlowPanel mainPanel;
|
|
||||||
|
|
||||||
private int maxMagnets = 100;
|
|
||||||
|
|
||||||
private LinkedHashSet<String> prefixes = new LinkedHashSet<String>();
|
|
||||||
|
|
||||||
|
|
||||||
public FridgeBagPanel (PGFWrapper pgf, MagnetFactory magnetFactory) {
|
|
||||||
this.pgf = pgf;
|
|
||||||
this.magnetFactory = magnetFactory;
|
|
||||||
prefixPanel = new FlowPanel();
|
|
||||||
prefixPanel.setStylePrimaryName("my-PrefixPanel");
|
|
||||||
mainPanel = new FlowPanel();
|
mainPanel = new FlowPanel();
|
||||||
VerticalPanel vPanel = new VerticalPanel();
|
|
||||||
vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
|
initWidget(new ScrollPanel(mainPanel));
|
||||||
vPanel.add(prefixPanel);
|
|
||||||
vPanel.add(mainPanel);
|
|
||||||
initWidget(new ScrollPanel(vPanel));
|
|
||||||
setStylePrimaryName("my-FridgeBagPanel");
|
setStylePrimaryName("my-FridgeBagPanel");
|
||||||
addStyleDependentName("empty");
|
addStyleDependentName("empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateBag (String text) {
|
public void clear() {
|
||||||
updateBag(text, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateBag (final String text, String prefix) {
|
|
||||||
if (completeRequest != null) {
|
|
||||||
completeRequest.cancel();
|
|
||||||
}
|
|
||||||
final boolean updatePrefixes = prefix.equals("");
|
|
||||||
mainPanel.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 () {
|
public void fill(List<Magnet> magnets) {
|
||||||
prefixes.clear();
|
for (Magnet magnet : magnets) {
|
||||||
prefixPanel.clear();
|
mainPanel.add(magnet);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mainPanel.getWidgetCount() == 0)
|
||||||
|
addStyleDependentName("empty");
|
||||||
|
else
|
||||||
|
removeStyleDependentName("empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Magnet> iterator() {
|
||||||
/*
|
return (Iterator<Magnet>) (Iterator) mainPanel.iterator();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,17 +74,6 @@ public class PGF {
|
|||||||
public final native Linearizations getLinearizations() /*-{ return this.linearizations; }-*/;
|
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 */
|
/* Completion */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,20 +141,6 @@ public class PGF {
|
|||||||
public final native int getFId() /*-{ return this.fid; }-*/;
|
public final native int getFId() /*-{ return this.fid; }-*/;
|
||||||
public final native int getIndex() /*-{ return this.index; }-*/;
|
public final native int getIndex() /*-{ return this.index; }-*/;
|
||||||
public final native BracketedString[] getChildren() /*-{ return this.children; }-*/;
|
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 {
|
public static class TcError extends JavaScriptObject {
|
||||||
@@ -174,6 +149,29 @@ public class PGF {
|
|||||||
public final native int getFId() /*-{ return this.fid; }-*/;
|
public final native int getFId() /*-{ return this.fid; }-*/;
|
||||||
public final native String getMsg() /*-{ return this.msg; }-*/;
|
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) {
|
public String graphvizAbstractTree(String pgfURL, String abstractTree) {
|
||||||
List<Arg> args = new ArrayList<Arg>();
|
List<Arg> args = new ArrayList<Arg>();
|
||||||
@@ -216,8 +214,20 @@ public class PGF {
|
|||||||
|
|
||||||
return request;
|
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) {
|
public <T extends JavaScriptObject> JSONRequest sendGrammarRequest(String pgfURL, String resource, List<Arg> args, final JSONCallback<T> callback) {
|
||||||
args.add(new Arg("command", resource));
|
args.add(new Arg("command", resource));
|
||||||
|
|||||||
@@ -138,6 +138,10 @@ public class PGFWrapper {
|
|||||||
return pgf.parse(grammarURL, input, inputLanguage, cat, callback);
|
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) {
|
public String graphvizAbstractTree(String abstractTree) {
|
||||||
return pgf.graphvizAbstractTree(grammarURL,abstractTree);
|
return pgf.graphvizAbstractTree(grammarURL,abstractTree);
|
||||||
}
|
}
|
||||||
@@ -154,6 +158,10 @@ public class PGFWrapper {
|
|||||||
return pgf.browse(grammarURL, id, href, cssClass, callback);
|
return pgf.browse(grammarURL, id, href, cssClass, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSONRequest query(String query, PGF.QueryCallback callback) {
|
||||||
|
return pgf.query(grammarURL, query, callback);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Settings
|
// Settings
|
||||||
//
|
//
|
||||||
@@ -242,7 +250,7 @@ public class PGFWrapper {
|
|||||||
PGF.Language l = languages.get(language);
|
PGF.Language l = languages.get(language);
|
||||||
return l == null ? null : l.getLanguageCode();
|
return l == null ? null : l.getLanguageCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<String> getAllLanguages() {
|
public Collection<String> getAllLanguages() {
|
||||||
return languages.keySet();
|
return languages.keySet();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}-*/;
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}-*/;
|
||||||
|
}
|
||||||
253
src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css
Normal file
253
src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css
Normal 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 |
BIN
src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/new.png
Normal file
BIN
src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/new.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 230 B |
Binary file not shown.
|
After Width: | Height: | Size: 518 B |
Reference in New Issue
Block a user