- Add "Save file as" menu that forces browser to download file instead of opening...
[pithos] / src / gr / ebs / gss / client / FileMenu.java
1 /*\r
2  * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.\r
3  *\r
4  * This file is part of GSS.\r
5  *\r
6  * GSS is free software: you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation, either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * GSS is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with GSS.  If not, see <http://www.gnu.org/licenses/>.\r
18  */\r
19 package gr.ebs.gss.client;\r
20 \r
21 import gr.ebs.gss.client.commands.EmptyTrashCommand;\r
22 import gr.ebs.gss.client.commands.NewFolderCommand;\r
23 import gr.ebs.gss.client.commands.PropertiesCommand;\r
24 import gr.ebs.gss.client.commands.RefreshCommand;\r
25 import gr.ebs.gss.client.commands.UploadFileCommand;\r
26 import gr.ebs.gss.client.rest.RestCommand;\r
27 import gr.ebs.gss.client.rest.resource.FileResource;\r
28 import gr.ebs.gss.client.rest.resource.FolderResource;\r
29 import gr.ebs.gss.client.rest.resource.GroupUserResource;\r
30 \r
31 import com.google.gwt.http.client.URL;\r
32 import com.google.gwt.user.client.Command;\r
33 import com.google.gwt.user.client.ui.AbstractImagePrototype;\r
34 import com.google.gwt.user.client.ui.ClickListener;\r
35 import com.google.gwt.user.client.ui.MenuBar;\r
36 import com.google.gwt.user.client.ui.PopupPanel;\r
37 import com.google.gwt.user.client.ui.TreeItem;\r
38 import com.google.gwt.user.client.ui.Widget;\r
39 \r
40 /**\r
41  * The 'File' menu implementation.\r
42  */\r
43 public class FileMenu extends PopupPanel implements ClickListener {\r
44 \r
45         /**\r
46          * The widget's images.\r
47          */\r
48         private final Images images;\r
49 \r
50         /**\r
51          * An image bundle for this widgets images.\r
52          */\r
53         public interface Images extends FilePropertiesDialog.Images {\r
54 \r
55                 @Resource("gr/ebs/gss/resources/folder_new.png")\r
56                 AbstractImagePrototype folderNew();\r
57 \r
58                 @Resource("gr/ebs/gss/resources/folder_outbox.png")\r
59                 AbstractImagePrototype fileUpdate();\r
60 \r
61                 @Resource("gr/ebs/gss/resources/view_text.png")\r
62                 AbstractImagePrototype viewText();\r
63 \r
64                 @Resource("gr/ebs/gss/resources/folder_inbox.png")\r
65                 AbstractImagePrototype download();\r
66 \r
67                 @Resource("gr/ebs/gss/resources/trashcan_empty.png")\r
68                 AbstractImagePrototype emptyTrash();\r
69 \r
70                 @Resource("gr/ebs/gss/resources/internet.png")\r
71                 AbstractImagePrototype sharing();\r
72 \r
73                 @Resource("gr/ebs/gss/resources/refresh.png")\r
74                 AbstractImagePrototype refresh();\r
75 }\r
76 \r
77         final MenuBar contextMenu = new MenuBar(true);\r
78 \r
79         /**\r
80          * The widget's constructor.\r
81          *\r
82          * @param _images the image bundle passed on by the parent object\r
83          */\r
84         public FileMenu(final Images _images) {\r
85                 // The popup's constructor's argument is a boolean specifying that it\r
86                 // auto-close itself when the user clicks outside of it.\r
87                 super(true);\r
88                 setAnimationEnabled(true);\r
89                 images = _images;\r
90                 add(contextMenu);\r
91 \r
92         }\r
93 \r
94         public void onClick(final Widget sender) {\r
95                 final FileMenu menu = new FileMenu(images);\r
96                 final int left = sender.getAbsoluteLeft();\r
97                 final int top = sender.getAbsoluteTop() + sender.getOffsetHeight();\r
98                 menu.setPopupPosition(left, top);\r
99 \r
100                 menu.show();\r
101         }\r
102 \r
103         /**\r
104          * Do some validation before downloading a file.\r
105          */\r
106         void preDownloadCheck() {\r
107                 Object selection = GSS.get().getCurrentSelection();\r
108                 if (selection == null || !(selection instanceof FileResource)) {\r
109                         GSS.get().displayError("You have to select a file first");\r
110                         return;\r
111                 }\r
112         }\r
113 \r
114         /**\r
115          * Create a download link for the respective menu item, if the currently\r
116          * selected object is a file.\r
117          *\r
118          * @param link a String array with two elements that is modified so that the\r
119          *            first position contains the opening tag and the second one the\r
120          *            closing tag\r
121          * @param forceDownload If true, link will be such that browser should ask for filename\r
122          *                              and save location\r
123          */\r
124         void createDownloadLink(String[] link, boolean forceDownload) {\r
125                 GSS app = GSS.get();\r
126                 Object selection = app.getCurrentSelection();\r
127                 if (selection != null && selection instanceof FileResource) {\r
128                         FileResource file = (FileResource) selection;\r
129                         String dateString = RestCommand.getDate();\r
130                         String resource = file.getUri().substring(app.getApiPath().length()-1,file.getUri().length());\r
131                         String sig = app.getCurrentUserResource().getUsername()+" "+RestCommand.calculateSig("GET", dateString, resource, RestCommand.base64decode(app.getToken()));\r
132                         link[0] = "<a class='hidden-link' href='" + file.getUri() + "?Authorization=" + URL.encodeComponent(sig) + "&Date="+URL.encodeComponent(dateString)\r
133                                         + (forceDownload ? "&dl=1" : "") + "' target='_blank'>";\r
134                         link[1] = "</a>";\r
135                 }\r
136         }\r
137 \r
138         public MenuBar createMenu() {\r
139                 contextMenu.clearItems();\r
140                 contextMenu.setAutoOpen(false);\r
141                 final Command downloadCmd = new Command() {\r
142 \r
143                         public void execute() {\r
144                                 hide();\r
145                                 preDownloadCheck();\r
146                         }\r
147                 };\r
148                 Folders folders = GSS.get().getFolders();\r
149                 TreeItem selectedItem = folders.getCurrent();\r
150                 boolean downloadVisible = GSS.get().getCurrentSelection() != null && GSS.get().getCurrentSelection() instanceof FileResource;\r
151                 boolean uploadVisible = GSS.get().getFolders().getCurrent().getUserObject() instanceof FolderResource;\r
152                 boolean propertiesNotVisible = selectedItem != null && (folders.isTrash(selectedItem) || folders.isMyShares(selectedItem) || folders.isOthersShared(selectedItem) || selectedItem.getUserObject() instanceof GroupUserResource);\r
153                 contextMenu.addItem("<span>" + images.folderNew().getHTML() + "&nbsp;New Folder</span>", true, new NewFolderCommand(this, images));\r
154                 if (uploadVisible) contextMenu.addItem("<span>" + images.fileUpdate().getHTML() + "&nbsp;Upload</span>", true, new UploadFileCommand(this, images));\r
155                 if (downloadVisible) {\r
156                         String[] link = {"", ""};\r
157                         createDownloadLink(link, false);\r
158                         contextMenu.addItem("<span>" + link[0] + images.download().getHTML() + "&nbsp;Download" + link[1] + "</span>", true, downloadCmd);\r
159                         createDownloadLink(link, true);\r
160                         contextMenu.addItem("<span>" + link[0] + images.download().getHTML() + "&nbsp;Save file as" + link[1] + "</span>", true, downloadCmd);\r
161                 }\r
162                 contextMenu.addItem("<span>" + images.emptyTrash().getHTML() + "&nbsp;Empty Trash</span>", true, new EmptyTrashCommand(this));\r
163                 contextMenu.addItem("<span>" + images.refresh().getHTML() + "&nbsp;Refresh</span>", true, new RefreshCommand(this, images));\r
164                 contextMenu.addItem("<span>" + images.sharing().getHTML() + "&nbsp;Sharing</span>", true, new PropertiesCommand(this, images, 1))\r
165                                         .setVisible(!propertiesNotVisible);\r
166                 contextMenu.addItem("<span>" + images.viewText().getHTML() + "&nbsp;Properties</span>", true, new PropertiesCommand(this, images, 0))\r
167                                         .setVisible(!propertiesNotVisible);\r
168                 return contextMenu;\r
169         }\r
170 \r
171 }\r