From cd0a9982bd93cc62e35de3cfc25a3bd6573cdb3a Mon Sep 17 00:00:00 2001 From: krasimir Date: Mon, 1 Nov 2010 09:25:22 +0000 Subject: [PATCH] preliminary UI for storage/retrieval/search of documents in the GF editor --- .../ui/gwt/client/DocumentsPanel.java | 113 +++++++++++++++--- .../ui/gwt/client/EditorApp.java | 17 ++- .../ui/gwt/client/JSONRequestBuilder.java | 4 +- .../ui/gwt/client/TextInputPanel.java | 48 +++++++- .../ui/gwt/public/Editor.css | 4 +- .../ui/gwt/public/trash-button.png | Bin 0 -> 930 bytes 6 files changed, 157 insertions(+), 29 deletions(-) create mode 100644 src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/trash-button.png diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/DocumentsPanel.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/DocumentsPanel.java index 0ce7ab4fe..c2f5b3844 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/DocumentsPanel.java +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/DocumentsPanel.java @@ -7,46 +7,67 @@ import com.google.gwt.http.client.*; import com.google.gwt.xml.client.*; import com.google.gwt.event.logical.shared.*; import com.google.gwt.event.dom.client.*; +import com.google.gwt.event.shared.*; -public class DocumentsPanel extends Composite { +public class DocumentsPanel extends Composite implements HasSelectionHandlers { private PGFWrapper pgf; + private ContentService contentService; + private StatusPopup statusPopup; private FlexTable table; + private ArrayList documentIds = new ArrayList(); - public DocumentsPanel(PGFWrapper pgf) { + public DocumentsPanel(PGFWrapper pgf, ContentService contentService, StatusPopup statusPopup) { this.pgf = pgf; + this.contentService = contentService; + this.statusPopup = statusPopup; VerticalPanel documentsPanel = new VerticalPanel(); documentsPanel.setStylePrimaryName("my-DocumentsFrame"); HorizontalPanel searchPanel = new HorizontalPanel(); searchPanel.setStylePrimaryName("my-DocumentsSearchFrame"); - TextBox searchBox = new TextBox(); + final TextBox searchBox = new TextBox(); searchBox.setWidth("20em"); - Button searchBtn = new Button("Search"); + final Button searchBtn = new Button("Search"); searchPanel.add(searchBox); searchPanel.add(searchBtn); documentsPanel.add(searchPanel); - - Label header = new Label("Documents"); + + Image deleteButton = new Image("org.grammaticalframework.ui.gwt.EditorApp/trash-button.png"); + deleteButton.setTitle("Deletes the selected documents."); + deleteButton.setStylePrimaryName("toolbar-button"); + deleteButton.addClickListener(new ClickListener () { + public void onClick(Widget sender) { + deleteSelected(); + } + }); + + FlexTable header = new FlexTable(); header.setStylePrimaryName("my-DocumentsHeader"); + header.setText(0,0,"Documents"); + header.setWidget(0,1,deleteButton); + header.getColumnFormatter().setWidth(1,"20px"); documentsPanel.add(header); table = new FlexTable(); + table.setCellPadding(2); table.setStylePrimaryName("my-DocumentsTable"); + table.getColumnFormatter().setWidth(1,"80em"); + table.getColumnFormatter().setWidth(2,"80em"); documentsPanel.add(table); - - addRow(0, "Test0"); - addRow(1, "Test1"); - addRow(2, "Test2"); - addRow(3, "Test3"); + searchBtn.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + searchDocuments(searchBox.getText()); + } + }); table.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { HTMLTable.Cell cell = table.getCellForEvent(event); if (cell != null) { int row = cell.getRowIndex(); - selectRow(row); + selectDocument(row); } } }); @@ -54,12 +75,68 @@ public class DocumentsPanel extends Composite { initWidget(documentsPanel); setStylePrimaryName("my-DocumentsPanel"); } - - private void addRow(int row, String text) { - table.setText(row, 0, text); - table.getRowFormatter().addStyleName(row, "row"); + + public HandlerRegistration addSelectionHandler(SelectionHandler handler) { + return addHandler(handler, SelectionEvent.getType()); + } + + protected void selectDocument(int row) { + SelectionEvent.fire(this, documentIds.get(row)); } - private void selectRow(int row) { - } + protected void searchDocuments(String fullTextQuery) { + statusPopup.setStatus("Searching..."); + + documentIds.clear(); + while (table.getRowCount() > 0) + table.removeRow(0); + + contentService.search(fullTextQuery, new ContentService.SearchCallback() { + public void onResult(IterableJsArray documents) { + for (ContentService.DocumentSignature sign : documents.iterable()) { + int row = table.getRowCount(); + table.setWidget(row, 0, new CheckBox(sign.getTitle())); + table.setText(row, 1, sign.getCreated()); + table.setText(row, 2, sign.getModified()); + table.getRowFormatter().addStyleName(row, "row"); + documentIds.add(sign.getId()); + } + + statusPopup.clearStatus(); + } + + public void onError(Throwable e) { + statusPopup.showError("Search failed", e); + } + }); + } + + protected void deleteSelected() { + statusPopup.setStatus("Deleting..."); + + final ArrayList ids = new ArrayList(); + final ArrayList rows = new ArrayList(); + for (int row = 0; row < table.getRowCount(); row++) { + CheckBox checkBox = (CheckBox) table.getWidget(row,0); + if (checkBox.isChecked()) { + ids.add(documentIds.get(row)); + rows.add(new Integer(row)); + } + } + + contentService.delete(ids, new ContentService.DeleteCallback() { + public void onResult(ContentService.DeleteResult result) { + for (Integer row : rows) { + table.removeRow(row.intValue()); + } + + statusPopup.clearStatus(); + } + + public void onError(Throwable e) { + statusPopup.showError("Delete failed", 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 index 12bb0438b..b51eb4ee5 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/EditorApp.java @@ -12,7 +12,9 @@ import com.google.gwt.event.shared.*; public class EditorApp implements EntryPoint { protected static final String pgfBaseURL = "/grammars"; + protected static final String contentBaseURL = "/content.fcgi"; + protected ContentService contentService; protected PGFWrapper pgf; protected VerticalPanel outputPanel; @@ -24,6 +26,7 @@ public class EditorApp implements EntryPoint { protected TextInputPanel textPanel; protected FridgeBagPanel bagPanel; protected MagnetFactory magnetFactory; + protected TabBar tabBar; private JSONRequest completeRequest = null; private JSONRequest translateRequest = null; @@ -233,7 +236,7 @@ public class EditorApp implements EntryPoint { } protected Widget createEditorPanel() { - textPanel = new TextInputPanel(); + textPanel = new TextInputPanel(contentService, statusPopup); textPanel.addValueChangeHandler(new ValueChangeHandler() { public void onValueChange(ValueChangeEvent event) { update(); @@ -304,11 +307,18 @@ public class EditorApp implements EntryPoint { } protected DocumentsPanel createDocumentsPanel() { - return new DocumentsPanel(pgf); + DocumentsPanel panel = new DocumentsPanel(pgf, contentService, statusPopup); + panel.addSelectionHandler(new SelectionHandler() { + public void onSelection(SelectionEvent event) { + tabBar.selectTab(1); + textPanel.load(event.getSelectedItem()); + } + }); + return panel; } protected TabBar createLinksPanel(final Panel parent) { - TabBar tabBar = new TabBar(); + tabBar = new TabBar(); tabBar.setStylePrimaryName("my-LinksPanel"); tabBar.addTab("Documents"); tabBar.addTab("Editor"); @@ -426,6 +436,7 @@ public class EditorApp implements EntryPoint { statusPopup = new StatusPopup(); pgf = new PGFWrapper(pgfBaseURL); + contentService = new ContentService(contentBaseURL); RootPanel.get().add(createUI()); pgf.addSettingsListener(new MySettingsListener()); pgf.updateAvailableGrammars(); diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java index 104536770..e2e83dc6f 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/JSONRequestBuilder.java @@ -56,13 +56,13 @@ public class JSONRequestBuilder { public static JSONRequest sendDataRequest (String base, List vars, String content, final JSONCallback callback) { String url = getQueryURL(base,vars); RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url); - builder.setRequestData(content); builder.setTimeoutMillis(30000); + builder.setHeader("Content-Length", Integer.toString(content.length())); builder.setHeader("Accept","text/plain, text/html;q=0.5, */*;q=0.1"); Request request = null; try { - request = builder.sendRequest(null, new RequestCallback() { + request = builder.sendRequest(content, new RequestCallback() { public void onError(Request request, Throwable e) { callback.onError(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 index 2a70e4d02..bf2c04a03 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TextInputPanel.java +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/client/TextInputPanel.java @@ -11,6 +11,8 @@ import com.google.gwt.event.shared.*; public class TextInputPanel extends Composite implements Focusable, HasValueChangeHandlers, HasSelectionHandlers { + protected ContentService contentService; + protected StatusPopup statusPopup; protected FlowPanel textPanel = null; protected FlowPanel mainPanel = null; protected FocusPanel focusPanel = null; @@ -28,8 +30,13 @@ public class TextInputPanel extends Composite implements Focusable, HasValueChan private Map mapFId2Phrase = new HashMap(); private ChangeListenerCollection changeListeners = null; + + private Integer docId = null; + + public TextInputPanel(ContentService contentService, StatusPopup statusPopup) { + this.contentService = contentService; + this.statusPopup = statusPopup; - public TextInputPanel() { mainPanel = new FlowPanel(); mainPanel.setStylePrimaryName("wordspanel"); @@ -72,7 +79,7 @@ public class TextInputPanel extends Composite implements Focusable, HasValueChan Image clearButton = new Image("org.grammaticalframework.ui.gwt.EditorApp/textinput-buttons.png",0,0,20,20); clearButton.setTitle("Clears the whole document."); - clearButton.setStylePrimaryName("button"); + clearButton.setStylePrimaryName("toolbar-button"); clearButton.addClickListener(new ClickListener () { public void onClick(Widget sender) { clear(); @@ -82,7 +89,7 @@ public class TextInputPanel extends Composite implements Focusable, HasValueChan Image saveButton = new Image("org.grammaticalframework.ui.gwt.EditorApp/textinput-buttons.png",20,0,20,20); saveButton.setTitle("Save the document."); - saveButton.setStylePrimaryName("button"); + saveButton.setStylePrimaryName("toolbar-button"); saveButton.addClickListener(new ClickListener () { public void onClick(Widget sender) { save(); @@ -92,7 +99,7 @@ public class TextInputPanel extends Composite implements Focusable, HasValueChan Image deleteLastButton = new Image("org.grammaticalframework.ui.gwt.EditorApp/textinput-buttons.png",40,0,20,20); deleteLastButton.setTitle("Removes the last word."); - deleteLastButton.setStylePrimaryName("button"); + deleteLastButton.setStylePrimaryName("toolbar-button"); deleteLastButton.addClickListener(new ClickListener () { public void onClick(Widget sender) { deleteLast(); @@ -168,10 +175,43 @@ public class TextInputPanel extends Composite implements Focusable, HasValueChan focusedPanel = null; errorPanels = null; tempPanel = null; + docId = null; fireValueChange(); } public void save() { + statusPopup.setStatus("Saving..."); + + contentService.save(docId, getText(), new ContentService.SaveCallback() { + public void onResult(ContentService.DocumentSignature sign) { + docId = new Integer(sign.getId()); + statusPopup.clearStatus(); + } + + public void onError(Throwable e) { + statusPopup.showError("Saving failed", e); + } + }); + } + + public void load(Object id) { + statusPopup.setStatus("Loading..."); + + contentService.load(id, new ContentService.LoadCallback() { + public void onResult(ContentService.Document document) { + clear(); + + docId = new Integer(document.getId()); + showSearchBox(); + searchBox.setText(document.getContent()); + + statusPopup.clearStatus(); + } + + public void onError(Throwable e) { + statusPopup.showError("Saving failed", e); + } + }); } public void addMagnet(Magnet magnet) { 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 index 073f0a14b..7215b720a 100644 --- a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css +++ b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/Editor.css @@ -77,12 +77,12 @@ background-repeat: repeat-x; } -.my-TextInputPanel .toolbar .button { +.toolbar-button { float: left; margin: 2px; } -.my-TextInputPanel .toolbar .button:hover { +.toolbar-button:hover { margin: 1px; border: 1px solid rgb(147,194,241); } diff --git a/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/trash-button.png b/src/ui/gwt/src/org/grammaticalframework/ui/gwt/public/trash-button.png new file mode 100644 index 0000000000000000000000000000000000000000..11536bc01d07ef1aafe09bf0ac9888e3ff79fa3e GIT binary patch literal 930 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4mJh`hN1woGYkw2jKx9jP7LeL$-HD>U|>mi z^mSxl*x1kgCy|wbfk7eJBgmJ5p-PQ`p`nF=;THn~L&FOOhEf9thF1v;3|2E37{m+a z>AjADaVC3Kvey6Jjk(a{fS9F5@%bvi01 zcEv5x=y<;Qb3@nVM)o6`PC1KNitl-p2F6KnEy_8&bEUC!P~q%1U%vc_|B*2JHaq|O zm(_Lm|6A^v|0b#}JvsTYpN(97abe*{BN48<&wu*P^bzZJQK~=u@Wc8!bLRAGO+9t6 z`k_xxcG~8f2KM&vQzT?%|1Ny{R`=G;n`+B1d+JT^E-NoT`L^uxks~ZuuU&I{_4@Vx zYgevltY`RI^>_EwsiKb#2hTq*{<-2#NmZ3k;{nOrJ2#v@%^)i;fArZiox0t3r8G1( zIj2pZe*8(%P9@G41r~K7;o<*v^z{C@{n-&?{p9;^gT0?vm>9X(njb!U_DnxDHPvzb z_1|Wk+ji{8m^F87o!Qyr7`u)pCH1&1KJrue^WnqJk80e)!^2muTDemaRQhYuWJ z`1<`j_tx6l+ACMDsy<^#j13L_su;We6@;(y@dqfI&qo7qJ3145!+UK{%>0|PJq4!Oa6?}EpvAM0*jkYYIGd20Ta zV{zWz-2rhC5f%Ees)2$GS6NwEpDHUWFACh*S@?d%#*Kjz&o(Sws%o+!er;HK`mgzS zpD_y-<>lpBt6Sx4jXGL7Yt}5GaL)3=%F3BKVyE+$2K`hK)+m(!zpR}hdux<(_#5lz r>63-`oqJ{X^!fAGKi_mM`agT|TJ1IKZEP7B7#KWV{an^LB{Ts56ZWUE literal 0 HcmV?d00001