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 = (PageServiceAsync) GWT.create(PageService.class);
070 ServiceDefTarget endpoint = (ServiceDefTarget) pageService;
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 == (char) KeyboardListener.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 }
|