diff options
| author | krasimir <krasimir@chalmers.se> | 2010-09-29 13:17:48 +0000 |
|---|---|---|
| committer | krasimir <krasimir@chalmers.se> | 2010-09-29 13:17:48 +0000 |
| commit | 3b11f81c6bdb536ac5cc7c9c729d2ff22836e894 (patch) | |
| tree | 07a48bc5a34105e40c64bc7907006c7013150908 /src/ui/gwt | |
| parent | 8b7d27fe4c2975fb5e8718f4b79face22733eb0b (diff) | |
initial import of the new GF editor. Note: the FridgeApp is temporary broken. It will be fixed with the next patch
Diffstat (limited to 'src/ui/gwt')
18 files changed, 2353 insertions, 116 deletions
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml index 0fa154520..a7b24c1af 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/EditorApp.gwt.xml @@ -13,8 +13,10 @@ <!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> --> <!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> --> - <!-- Other module inherits --> - + <replace-with class="org.grammaticalframework.ui.gwt.client.selection.support.InternetExplorerSelectionSupport"> + <when-type-is class="org.grammaticalframework.ui.gwt.client.selection.support.SelectionSupport"/> + <when-property-is name="user.agent" value="ie6"/> + </replace-with> <!-- Specify the app entry point class. --> <entry-point class="org.grammaticalframework.ui.gwt.client.EditorApp" /> diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/BrowsePanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/BrowsePanel.java new file mode 100644 index 000000000..ea7e0aca8 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/BrowsePanel.java @@ -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) { } + } +} diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java new file mode 100644 index 000000000..107e2c6cd --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java @@ -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); + } +} diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java index 657f3bf13..bab14808e 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/FridgeBagPanel.java @@ -1,108 +1,38 @@ package org.grammaticalframework.ui.gwt.client; -import java.util.LinkedHashSet; +import java.util.*; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.*; -public class FridgeBagPanel extends Composite { +public class FridgeBagPanel extends Composite implements Iterable<Magnet> { - private PGFWrapper pgf; + private FlowPanel mainPanel; - private MagnetFactory magnetFactory; - - private JSONRequest completeRequest = null; - - private FlowPanel prefixPanel; - - private FlowPanel mainPanel; - - private int maxMagnets = 100; - - private LinkedHashSet<String> prefixes = new LinkedHashSet<String>(); - - - public FridgeBagPanel (PGFWrapper pgf, MagnetFactory magnetFactory) { - this.pgf = pgf; - this.magnetFactory = magnetFactory; - prefixPanel = new FlowPanel(); - prefixPanel.setStylePrimaryName("my-PrefixPanel"); + public FridgeBagPanel () { mainPanel = new FlowPanel(); - VerticalPanel vPanel = new VerticalPanel(); - vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER); - vPanel.add(prefixPanel); - vPanel.add(mainPanel); - initWidget(new ScrollPanel(vPanel)); + + initWidget(new ScrollPanel(mainPanel)); setStylePrimaryName("my-FridgeBagPanel"); addStyleDependentName("empty"); } - public void updateBag (String text) { - updateBag(text, ""); - } - - public void updateBag (final String text, String prefix) { - if (completeRequest != null) { - completeRequest.cancel(); - } - final boolean updatePrefixes = prefix.equals(""); + public void clear() { mainPanel.clear(); - addStyleDependentName("empty"); - if (updatePrefixes) { clearPrefixes(); } - int limit = updatePrefixes ? 0 : maxMagnets; - completeRequest = pgf.complete(text + " " + prefix, - limit, new PGF.CompleteCallback() { - public void onResult(PGF.Completions completions) { - for (PGF.Completion completion : completions.iterable()) { - for (String word : completion.getCompletions()) { - if (updatePrefixes) { - addPrefix(text, word.substring(0,1)); - } - if (mainPanel.getWidgetCount() < maxMagnets) { - Magnet magnet = magnetFactory.createMagnet(word, completion.getFrom()); - mainPanel.add(magnet); - removeStyleDependentName("empty"); - } else { - prefixPanel.setVisible(true); - } - } - } - } - public void onError(Throwable e) { - // FIXME: show message to user? - GWT.log("Error getting completions.", e); - } - }); - } - - protected void clearPrefixes () { - prefixes.clear(); - prefixPanel.clear(); - prefixPanel.setVisible(false); } - protected void addPrefix(final String text, final String prefix) { - if (prefixes.add(prefix)) { - Button prefixButton = new Button(prefix, new ClickListener() { - public void onClick(Widget sender) { - updateBag(text, prefix); - } - }); - prefixButton.setTitle("Show only magnets stating with '" + prefix + "'"); - prefixPanel.add(prefixButton); + public void fill(List<Magnet> magnets) { + for (Magnet magnet : magnets) { + mainPanel.add(magnet); } - } - - /* - 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); - } + if (mainPanel.getWidgetCount() == 0) + addStyleDependentName("empty"); + else + removeStyleDependentName("empty"); } - */ + public Iterator<Magnet> iterator() { + return (Iterator<Magnet>) (Iterator) mainPanel.iterator(); + } } diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/LinearizationsPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/LinearizationsPanel.java new file mode 100644 index 000000000..2a916db29 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/LinearizationsPanel.java @@ -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; + } +} diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MagnetSearchBox.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MagnetSearchBox.java new file mode 100644 index 000000000..5a2a70401 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/MagnetSearchBox.java @@ -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; + } +} diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java index a6c5cab55..e3396cad1 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGF.java @@ -74,17 +74,6 @@ public class PGF { public final native Linearizations getLinearizations() /*-{ return this.linearizations; }-*/; } - public static class Linearizations extends IterableJsArray<Linearization> { - protected Linearizations() { } - } - - public static class Linearization extends JavaScriptObject { - protected Linearization() { } - - public final native String getTo() /*-{ return this.to; }-*/; - public final native String getText() /*-{ return this.text; }-*/; - } - /* Completion */ /** @@ -152,20 +141,6 @@ public class PGF { public final native int getFId() /*-{ return this.fid; }-*/; public final native int getIndex() /*-{ return this.index; }-*/; public final native BracketedString[] getChildren() /*-{ return this.children; }-*/; - - public final String render() { - if (getToken() != null) - return getToken(); - else { - StringBuilder sbuilder = new StringBuilder(); - for (BracketedString bs : getChildren()) { - if (sbuilder.length() > 0) - sbuilder.append(' '); - sbuilder.append(bs.render()); - } - return sbuilder.toString(); - } - } } public static class TcError extends JavaScriptObject { @@ -174,6 +149,29 @@ public class PGF { public final native int getFId() /*-{ return this.fid; }-*/; public final native String getMsg() /*-{ return this.msg; }-*/; } + + + /* Linearization */ + + public JSONRequest linearize (String pgfURL, String tree, String toLang, final LinearizeCallback callback) { + List<Arg> args = new ArrayList<Arg>(); + args.add(new Arg("tree", tree)); + args.add(new Arg("to", toLang)); + return sendGrammarRequest(pgfURL, "linearize", args, callback); + } + + public interface LinearizeCallback extends JSONCallback<Linearizations> { } + + public static class Linearizations extends IterableJsArray<Linearization> { + protected Linearizations() { } + } + + public static class Linearization extends JavaScriptObject { + protected Linearization() { } + + public final native String getTo() /*-{ return this.to; }-*/; + public final native String getText() /*-{ return this.text; }-*/; + } public String graphvizAbstractTree(String pgfURL, String abstractTree) { List<Arg> args = new ArrayList<Arg>(); @@ -216,8 +214,20 @@ public class PGF { return request; } + + public JSONRequest query(String pgfURL, String query, QueryCallback callback) { + List<Arg> args = new ArrayList<Arg>(); + args.add(new Arg("cat", query)); + return sendGrammarRequest(pgfURL, "query", args, callback); + } + + public interface QueryCallback extends JSONCallback<QueryResult> {} - /* Common */ + public static class QueryResult extends JavaScriptObject { + protected QueryResult() { } + + public final native String[] getRows() /*-{ return this.rows; }-*/; + } public <T extends JavaScriptObject> JSONRequest sendGrammarRequest(String pgfURL, String resource, List<Arg> args, final JSONCallback<T> callback) { args.add(new Arg("command", resource)); diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java index b8087ab9b..b1dfcf278 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/PGFWrapper.java @@ -138,6 +138,10 @@ public class PGFWrapper { return pgf.parse(grammarURL, input, inputLanguage, cat, callback); } + public JSONRequest linearize (String tree, final PGF.LinearizeCallback callback) { + return pgf.linearize(grammarURL, tree, outputLanguage, callback); + } + public String graphvizAbstractTree(String abstractTree) { return pgf.graphvizAbstractTree(grammarURL,abstractTree); } @@ -154,6 +158,10 @@ public class PGFWrapper { return pgf.browse(grammarURL, id, href, cssClass, callback); } + public JSONRequest query(String query, PGF.QueryCallback callback) { + return pgf.query(grammarURL, query, callback); + } + // // Settings // @@ -242,7 +250,7 @@ public class PGFWrapper { PGF.Language l = languages.get(language); return l == null ? null : l.getLanguageCode(); } - + public Collection<String> getAllLanguages() { return languages.keySet(); } diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/QueryPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/QueryPanel.java new file mode 100644 index 000000000..6f732dbe2 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/QueryPanel.java @@ -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) { } + } +} diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TextInputPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TextInputPanel.java new file mode 100644 index 000000000..cfaec4f03 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TextInputPanel.java @@ -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(); + } + } + } +} diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/Selection.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/Selection.java new file mode 100644 index 000000000..ceee8c1a7 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/Selection.java @@ -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);
+ }
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/SelectionEndPoint.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/SelectionEndPoint.java new file mode 100644 index 000000000..d429b4b19 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/SelectionEndPoint.java @@ -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 + "\"";
+ }
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/support/InternetExplorerSelectionSupport.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/support/InternetExplorerSelectionSupport.java new file mode 100644 index 000000000..f986365c7 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/support/InternetExplorerSelectionSupport.java @@ -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;
+ }-*/;
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/support/SelectionSupport.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/support/SelectionSupport.java new file mode 100644 index 000000000..946c2a812 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/selection/support/SelectionSupport.java @@ -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();
+ }-*/;
+}
diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css new file mode 100644 index 000000000..2b876160e --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css @@ -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; +} diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/background.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/background.png Binary files differnew file mode 100644 index 000000000..4c1e4989e --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/background.png diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/new.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/new.png Binary files differnew file mode 100644 index 000000000..6f13ca749 --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/new.png diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/textinput-buttons.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/textinput-buttons.png Binary files differnew file mode 100644 index 000000000..46029f34e --- /dev/null +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/textinput-buttons.png |
