Fixed look 'n feel to be like okeanos (except menus)
[pithos-web-client] / src / gr / grnet / pithos / web / client / FileUploadDialog.java
1 /*
2  * Copyright 2011 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35 package gr.grnet.pithos.web.client;
36
37 import gr.grnet.pithos.web.client.foldertree.File;
38 import gr.grnet.pithos.web.client.foldertree.Folder;
39
40 import com.google.gwt.core.client.GWT;
41 import com.google.gwt.dom.client.NativeEvent;
42 import com.google.gwt.event.dom.client.ClickEvent;
43 import com.google.gwt.event.dom.client.ClickHandler;
44 import com.google.gwt.event.dom.client.KeyCodes;
45 import com.google.gwt.user.client.Command;
46 import com.google.gwt.user.client.Cookies;
47 import com.google.gwt.user.client.Event.NativePreviewEvent;
48 import com.google.gwt.user.client.Window;
49 import com.google.gwt.user.client.ui.Button;
50 import com.google.gwt.user.client.ui.DialogBox;
51 import com.google.gwt.user.client.ui.FileUpload;
52 import com.google.gwt.user.client.ui.FormPanel;
53 import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
54 import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
55 import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
56 import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;
57 import com.google.gwt.user.client.ui.Anchor;
58 import com.google.gwt.user.client.ui.Grid;
59 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
60 import com.google.gwt.user.client.ui.Hidden;
61 import com.google.gwt.user.client.ui.HorizontalPanel;
62 import com.google.gwt.user.client.ui.Label;
63 import com.google.gwt.user.client.ui.VerticalPanel;
64
65 /**
66  * The 'File upload' dialog box implementation.
67  */
68 public class FileUploadDialog extends DialogBox {
69
70     public static final boolean DONE = true;
71
72         /**
73          * The Form element that performs the file upload.
74          */
75     protected final FormPanel form = new FormPanel();
76
77         private final FileUpload upload = new FileUpload();
78
79         private final Label filenameLabel = new Label();
80
81     private final Label foldernameLabel = new Label();
82
83     private Button submit;
84
85         protected Folder folder;
86
87     protected Pithos app;
88
89         /**
90          * The widget's constructor.
91          */
92         public FileUploadDialog() {
93                 Anchor close = new Anchor();
94                 close.addStyleName("close");
95                 close.addClickHandler(new ClickHandler() {
96                         
97                         @Override
98                         public void onClick(ClickEvent event) {
99                                 hide();
100                         }
101                 });
102                 // Set the dialog's caption.
103                 setText("File upload");
104                 setAnimationEnabled(true);
105                 setGlassEnabled(true);
106                 setStyleName("pithos-DialogBox");
107                 // Since we're going to add a FileUpload widget, we'll need to set the
108                 // form to use the POST method, and multipart MIME encoding.
109                 form.setEncoding(FormPanel.ENCODING_MULTIPART);
110                 form.setMethod(FormPanel.METHOD_POST);
111
112                 // Create a panel to hold all of the form widgets.
113                 VerticalPanel panel = new VerticalPanel();
114                 panel.add(close);
115                 form.setWidget(panel);
116
117                 VerticalPanel inner = new VerticalPanel();
118                 inner.addStyleName("inner");
119
120         final Hidden auth = new Hidden("X-Auth-Token", "");
121         inner.add(auth);
122                 upload.setName("X-Object-Data");
123                 filenameLabel.setText("");
124                 filenameLabel.setVisible(false);
125                 filenameLabel.setStyleName("props-labels");
126                 HorizontalPanel fileUploadPanel = new HorizontalPanel();
127                 fileUploadPanel.add(filenameLabel);
128                 fileUploadPanel.add(upload);
129                 Grid generalTable = new Grid(2, 2);
130                 generalTable.setText(0, 0, "Folder");
131         generalTable.setWidget(0, 1, foldernameLabel);
132                 generalTable.setText(1, 0, "File");
133                 generalTable.setWidget(1, 1, fileUploadPanel);
134                 generalTable.getCellFormatter().setStyleName(0, 0, "props-labels");
135         generalTable.getCellFormatter().setStyleName(0, 1, "props-values");
136                 generalTable.getCellFormatter().setStyleName(1, 0, "props-labels");
137                 generalTable.getCellFormatter().setStyleName(1, 1, "props-values");
138                 generalTable.setCellSpacing(4);
139
140                 inner.add(generalTable);
141
142                 // Create the 'upload' button, along with a listener that submits the
143                 // form.
144                 submit = new Button("Upload", new ClickHandler() {
145                         @Override
146                         public void onClick(@SuppressWarnings("unused") ClickEvent event) {
147                                 prepareAndSubmit();
148                         }
149                 });
150                 submit.addStyleName("button");
151                 inner.add(submit);
152
153                 // Add an event handler to the form.
154                 form.addSubmitHandler(new SubmitHandler() {
155
156                         @Override
157                         public void onSubmit(@SuppressWarnings("unused") SubmitEvent event) {
158                 auth.setValue(app.getToken()); //This is done here because the app object is not available in the constructor
159                 Cookies.setCookie("X-Auth-Token", app.getToken(), null, Window.Location.getHostName(), app.getApiPath(), false);
160                         }
161                 });
162                 form.addSubmitCompleteHandler(new SubmitCompleteHandler() {
163
164                         @Override
165                         public void onSubmitComplete(SubmitCompleteEvent event) {
166                                 // When the form submission is successfully completed, this
167                                 // event is fired. Assuming the service returned a response
168                                 // of type text/html, we can get the result text here (see
169                                 // the FormPanel documentation for further explanation).
170                                 String results = event.getResults();
171
172                                 // Unfortunately the results are never empty, even in
173                                 // the absense of errors, so we have to check for '<pre></pre>'.
174                                 if (results != null && results.length() > 0 && !results.equalsIgnoreCase("<pre></pre>")) {
175                                         GWT.log(results, null);
176                                         app.displayError(results);
177                                 }
178                                 if (app.getSelectedTree().equals(app.getFolderTreeView()))
179                                         app.updateFolder(folder, true, new Command() {
180                                                 
181                                                 @Override
182                                                 public void execute() {
183                                                         app.updateStatistics();
184                                                 }
185                                         });
186                                 else
187                                         app.updateOtherSharedFolder(folder, true);
188                                 hide();
189                         }
190                 });
191
192                 panel.add(inner);
193                 panel.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
194                 
195                 setWidget(form);
196         }
197
198         @Override
199         protected void onPreviewNativeEvent(NativePreviewEvent preview) {
200                 super.onPreviewNativeEvent(preview);
201
202                 NativeEvent evt = preview.getNativeEvent();
203                 if (evt.getType().equals("keydown"))
204                         // Use the popup's key preview hooks to close the dialog when either
205                         // enter or escape is pressed.
206                         switch (evt.getKeyCode()) {
207                                 case KeyCodes.KEY_ENTER:
208                                         prepareAndSubmit();
209                                         break;
210                                 case KeyCodes.KEY_ESCAPE:
211                                         hide();
212                                         break;
213                         }
214         }
215
216         /**
217          * Make any last minute checks and start the upload.
218          */
219         protected void prepareAndSubmit() {
220         if (upload.getFilename().length() == 0) {
221             app.displayError("You must select a file!");
222             return;
223         }
224         final String fname = getFilename(upload.getFilename());
225         String apath = app.getApiPath() + folder.getOwner() + folder.getUri() + "/" + fname;
226         form.setAction(apath);
227         submit.setEnabled(false);
228         upload.setVisible(false);
229         filenameLabel.setText(fname);
230         filenameLabel.setVisible(true);
231
232                 if (getFileForName(fname) == null) {
233             form.submit();
234                 }
235                 else {
236                         // We are going to update an existing file, so show a confirmation dialog.
237                         ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " +
238                                         "you want to update " + fname + "?", "Update") {
239
240                                 @Override
241                                 public void cancel() {
242                                         FileUploadDialog.this.hide();
243                                 }
244
245                                 @Override
246                                 public void confirm() {
247                                         form.submit();
248                                 }
249
250                         };
251                         confirm.center();
252                 }
253         }
254
255     /**
256          * Returns the file name from a potential full path argument. Apparently IE
257          * insists on sending the full path name of a file when uploading, forcing
258          * us to trim the extra path info. Since this is only observed on Windows we
259          * get to check for a single path separator value.
260          *
261          * @param name the potentially full path name of a file
262          * @return the file name without extra path information
263          */
264         protected String getFilename(String name) {
265                 int pathSepIndex = name.lastIndexOf("\\");
266                 if (pathSepIndex == -1) {
267                         pathSepIndex = name.lastIndexOf("/");
268                         if (pathSepIndex == -1)
269                                 return name;
270                 }
271                 return name.substring(pathSepIndex + 1);
272         }
273
274         protected File getFileForName(String name){
275                 for (File f : folder.getFiles())
276                         if (f.getName().equals(name))
277                                 return f;
278                 return null;
279         }
280
281     public void setApp(Pithos app) {
282         this.app = app;
283     }
284
285     public void setFolder(Folder folder) {
286         this.folder = folder;
287         foldernameLabel.setText(folder.getName());
288     }
289 }