NewPage.java
001 /*
002  *  NewPage.java
003  *  Copyright (c) 1998-2008, The University of Sheffield.
004  *
005  *  This code is from the GATE project (http://gate.ac.uk/) and is free
006  *  software licenced under the GNU General Public License version 3. It is
007  *  distributed without any warranty. For more details see COPYING.txt in the
008  *  top level directory (or at http://gatewiki.sf.net/COPYING.txt).
009  */
010 
011 package gate.cow.gwt.client;
012 
013 import com.google.gwt.core.client.EntryPoint;
014 import com.google.gwt.core.client.GWT;
015 
016 import com.google.gwt.user.client.rpc.AsyncCallback;
017 import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
018 import com.google.gwt.user.client.rpc.InvocationException;
019 import com.google.gwt.user.client.rpc.ServiceDefTarget;
020 
021 import com.google.gwt.user.client.*;
022 import com.google.gwt.user.client.ui.*;
023 
024 import com.google.gwt.json.client.JSONObject;
025 import com.google.gwt.json.client.JSONParser;
026 import com.google.gwt.json.client.JSONString;
027 import com.google.gwt.json.client.JSONValue;
028 import com.google.gwt.json.client.JSONException;
029 
030 
031 /**
032  * GUI for creating a new page or directory.
033  *
034  * Get information from the server with javascript variables
035  * in the show view and use PageService methods to check the name and
036  * create the page or directory.
037  */
038 public class NewPage implements EntryPoint, HistoryListener {
039   private PageServiceAsync pageService;
040   private VerticalPanel vPanel;
041   private Label messageLabel;
042   private Button createButton;
043   private Button create2Button;
044   private String id;
045   private String pathDir;
046   private String uploadLink;
047   private Timer timer;
048   private TextBox pageNameTextBox;
049 
050   /**
051    * Called when the javascript file is loaded in a web page.
052    */
053   public void onModuleLoad() {
054 
055     if (RootPanel.get("gwt-newpage"== null) {
056       // if no link with id equal to gwt-newpage then don't load
057       return;
058     }
059 
060     Hyperlink link = new Hyperlink("New page (GWT)""gwt-newpage");
061     link.setStyleName("inline");
062     RootPanel.get("gwt-newpage").add(link);
063     RootPanel.detachOnWindowClose(link);
064     id = getId();
065     pathDir = getPathDir();
066     uploadLink = getUploadLink();
067 
068     // initialize connection with page service
069     pageService = (PageServiceAsyncGWT.create(PageService.class);
070     ServiceDefTarget endpoint = (ServiceDefTargetpageService;
071     String moduleRelativeUrl = GWT.getModuleBaseURL() "rpc";
072     endpoint.setServiceEntryPoint(moduleRelativeUrl);
073 
074     // main vertical panel
075     vPanel = new VerticalPanel();
076     vPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
077     vPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
078     vPanel.setSpacing(0);
079 
080     // horizontal panel for text box and button
081     HorizontalPanel hPanel = new HorizontalPanel();
082     hPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
083     hPanel.setSpacing(5);
084     vPanel.add(hPanel);
085 
086     // label and text box for page name
087     Label pageNameLabel = new Label("Page name:");
088     pageNameLabel.setStyleName("pageLink");
089     hPanel.add(pageNameLabel);
090     pageNameTextBox = new TextBox();
091     pageNameTextBox.setWidth("15em");
092     pageNameTextBox.ensureDebugId("pageNameTextBox");
093     hPanel.add(pageNameTextBox);
094 
095     // buttons to create the page
096     createButton = new Button("Create");
097     createButton.setEnabled(false);
098     createButton.ensureDebugId("createButton");
099     createButton.setStyleName("button");
100     hPanel.add(createButton);
101     create2Button = new Button("Create and Edit");
102     create2Button.setEnabled(false);
103     create2Button.ensureDebugId("create2Button");
104     create2Button.setStyleName("button");
105     hPanel.add(create2Button);
106     Button cancelButton = new Button("Cancel");
107     cancelButton.ensureDebugId("cancelButton");
108     cancelButton.setStyleName("button");
109     hPanel.add(cancelButton);
110 
111     // label for messages
112     messageLabel = new Label();
113     messageLabel.setHeight("3em");
114     messageLabel.ensureDebugId("messageLabel");
115     vPanel.add(messageLabel);
116 
117     // listeners
118     pageNameTextBox.addKeyboardListener(new KeyboardListenerAdapter() {
119       public void onKeyUp(Widget widget, final char c, int i) {
120         createButton.setEnabled(false);
121         create2Button.setEnabled(false);
122         super.onKeyUp(widget, c, i);
123         // avoid calling checkName to fast
124         if (timer != null) {
125           timer.cancel();
126         }
127         timer = new Timer() {
128           public void run() {
129             checkName(pageNameTextBox.getText(), c);
130             timer = null;
131           }
132         };
133         timer.schedule(500);
134       }
135     });
136     createButton.addClickListener(new ClickListener() {
137       public void onClick(Widget sender) {
138         create(pageNameTextBox.getText()"normal");
139       }
140     });
141     create2Button.addClickListener(new ClickListener() {
142       public void onClick(Widget sender) {
143         create(pageNameTextBox.getText()"special");
144       }
145     });
146 
147     cancelButton.addClickListener(new ClickListener() {
148       public void onClick(Widget sender) {
149         setLocation(uploadLink.replaceFirst("upload""show""?type=dir");
150       }
151     });
152 
153     History.addHistoryListener(this);
154   }
155 
156   /**
157    * Called when a GWT link is clicked.
158    @param s anchor value of the link
159    */
160   public void onHistoryChanged(String s) {
161     if (History.getToken().equals("gwt-newpage")) {
162       clear(RootPanel.get("topPageSpecific").getElement());
163       RootPanel.get("topPageSpecific").add(vPanel);
164       // get the default message
165       checkName(""'a');
166       pageNameTextBox.setFocus(true);
167     }
168   }
169 
170   /**
171    * Check the validity of a page name before its creation.
172    @param pageName page name to check
173    @param c last character entered in the text box to be used with
174    *   {@link #pageNameTextBoxKeyboardEvent(String, char)} 
175    */
176   private void checkName(final String pageName, final char c) {
177     pageService.checkName(pageName, id, pathDir, new AsyncCallback<String>() {
178       String error = "A very very unexpected exception.";
179 
180       public void onFailure(Throwable caught) {
181         try {
182           throw caught;
183         catch (IncompatibleRemoteServiceException e) {
184           error = "This client is not compatible with the "+
185             "server. Please cleanup and refresh the browser.";
186         catch (InvocationException e) {
187           error = "The call didn't complete cleanly.";
188         catch (Throwable e) {
189           error = "A very unexpected exception. Is the server ready? " +
190           "Please wait few seconds before trying again.";
191         finally {
192           Window.alert(error);
193         }
194       }
195 
196       public void onSuccess(String result) {
197         JSONValue jsonValue;
198         try {
199           jsonValue = JSONParser.parse(result);
200         catch (JSONException e) {
201           error = "Failed to parse JSON response: " + result;
202           Window.alert(error);
203           return;
204         }
205         JSONObject jsonObject;
206         JSONString jsonString;
207         // parse the object to get the message
208         if ((jsonObject = jsonValue.isObject()) != null
209         && jsonObject.containsKey("message")
210         && (jsonString = jsonObject.get("message").isString()) != null) {
211           String message = jsonString.stringValue();
212           messageLabel.setText(message);
213           createButton.setTitle(message);
214           create2Button.setTitle(message);
215           if (message.startsWith("A new HTML file")) {
216             createButton.setEnabled(true);
217             create2Button.setText("Create and Edit");
218             create2Button.setEnabled(true);
219           else if (message.startsWith("A new directory")) {
220             createButton.setEnabled(true);
221             create2Button.setText("Create and Go");
222             create2Button.setEnabled(true);
223           else {
224             createButton.setEnabled(false);
225             create2Button.setEnabled(false);
226           }
227           pageNameTextBoxKeyboardEvent(pageName, c);
228         else {
229           Window.alert("Message missing!");  
230         }
231       }
232     });
233   }
234 
235   /**
236    * Create a page.
237    @param pageName page to create
238    @param action type of action 'normal', 'special' or 'none' to do
239    *   after the page is created.
240    */
241   private void create(final String pageName, final String action) {
242     pageService.create(pageName, id, pathDir, new AsyncCallback<String>() {
243       String error = "A very very unexpected exception.";
244 
245       public void onFailure(Throwable caught) {
246         try {
247           throw caught;
248         catch (IncompatibleRemoteServiceException e) {
249           error = "This client is not compatible with the "+
250             "server. Please cleanup and refresh the browser.";
251         catch (InvocationException e) {
252           error = "The call didn't complete cleanly.";
253         catch (Throwable e) {
254           error = "A very unexpected exception. Is the server ready? " +
255           "Please wait few seconds before trying again.";
256         finally {
257           Window.alert(error);
258         }
259       }
260 
261       public void onSuccess(String result) {
262         JSONValue jsonValue;
263         try {
264           jsonValue = JSONParser.parse(result);
265         catch (JSONException e) {
266           error = "Failed to parse JSON response: " + result;
267           Window.alert(error);
268           return;
269         }
270         JSONObject jsonObject;
271         JSONString jsonString;
272         // parse the object to get the message
273         if ((jsonObject = jsonValue.isObject()) != null
274         && jsonObject.containsKey("message")
275         && (jsonString = jsonObject.get("message").isString()) != null) {
276           String message = jsonString.stringValue();
277           messageLabel.setText(message);
278           String newPageName = pageName;
279           if (jsonObject.containsKey("pagename")
280           && (jsonString = jsonObject.get("pagename").isString()) != null) {
281             newPageName = jsonString.stringValue();
282           }
283           String edit = uploadLink.replaceFirst("upload""edit");
284           String show = uploadLink.replaceFirst("upload""show");
285           if (action.equals("normal")) {
286             // show the updated current directory listing
287             setLocation(show + "?type=dir");
288           else if (action.equals("special")) {
289             if (message.startsWith("Page ")) {
290               // edit the new page
291               setLocation(edit + newPageName);
292             else if (message.startsWith("Directory ")) {
293               // go into the new directory
294               setLocation(show + newPageName + '/' "?type=dir");
295             }
296           }
297         else {
298           Window.alert("Message missing!");
299         }
300       }
301     });
302   }
303 
304   /**
305    * Detect special keys like Enter in the page name text box.
306    @param fileName file name to create
307    @param c Key typed
308    */
309   private void pageNameTextBoxKeyboardEvent(String fileName, char c) {
310     String message = messageLabel.getText();
311     if (c == (charKeyboardListener.KEY_ENTER) {
312       if (message.startsWith("A new ")) {
313         create(fileName, "normal");
314       }
315     }
316   }
317 
318   /**
319    * Removes all of the element's children.
320    *
321    @param parent a DOM element
322    @throws IllegalArgumentException if <code>parent</code> is null
323    */
324   public static void clear(Element parent) {
325     if (parent == null) {
326       throw new IllegalArgumentException();
327     }
328     Element firstChild;
329     while((firstChild = DOM.getFirstChild(parent)) != null) {
330       DOM.removeChild(parent, firstChild);
331     }
332   }
333 
334   /**
335    * Set the location of the current web page and thus leave this module.
336    @param location url of the new web page to load
337    */
338   private native void setLocation(String location/*-{
339      $wnd.location.href = location;
340   }-*/;
341 
342   /**
343    * Get the value of the id javascript variable.
344    @return value of the id javascript variable.
345    */
346   private native String getId() /*-{
347     return $wnd.id;
348   }-*/;
349 
350   /**
351    * Get the value of the pathDir javascript variable.
352    @return value of the pathDir javascript variable.
353    */
354   private native String getPathDir() /*-{
355     return $wnd.pathDir;
356   }-*/;
357 
358   /**
359    * Get the value of the uploadLink javascript variable.
360    @return value of the uploadLink javascript variable.
361    */
362   private native String getUploadLink() /*-{
363     return $wnd.uploadLink;
364   }-*/;
365 
366 }