Merge with d1e79f3c8c8779d14ab5297049bdc0812f942654
[pithos] / src / gr / ebs / gss / client / FileList.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.dnd.DnDFocusPanel;\r
22 import gr.ebs.gss.client.dnd.DnDTreeItem;\r
23 import gr.ebs.gss.client.rest.GetCommand;\r
24 import gr.ebs.gss.client.rest.MultipleHeadCommand;\r
25 import gr.ebs.gss.client.rest.RestCommand;\r
26 import gr.ebs.gss.client.rest.RestException;\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.OtherUserResource;\r
30 import gr.ebs.gss.client.rest.resource.SharedResource;\r
31 import gr.ebs.gss.client.rest.resource.TrashResource;\r
32 import gr.ebs.gss.client.rest.resource.UserResource;\r
33 \r
34 import java.util.ArrayList;\r
35 import java.util.Collections;\r
36 import java.util.Comparator;\r
37 import java.util.List;\r
38 \r
39 import com.google.gwt.core.client.GWT;\r
40 import com.google.gwt.http.client.URL;\r
41 import com.google.gwt.i18n.client.DateTimeFormat;\r
42 import com.google.gwt.user.client.DOM;\r
43 import com.google.gwt.user.client.DeferredCommand;\r
44 import com.google.gwt.user.client.Event;\r
45 import com.google.gwt.user.client.IncrementalCommand;\r
46 import com.google.gwt.user.client.Window;\r
47 import com.google.gwt.user.client.ui.AbstractImagePrototype;\r
48 import com.google.gwt.user.client.ui.ClickListener;\r
49 import com.google.gwt.user.client.ui.Composite;\r
50 import com.google.gwt.user.client.ui.Grid;\r
51 import com.google.gwt.user.client.ui.HTML;\r
52 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
53 import com.google.gwt.user.client.ui.HorizontalPanel;\r
54 import com.google.gwt.user.client.ui.SourcesTableEvents;\r
55 import com.google.gwt.user.client.ui.TableListener;\r
56 import com.google.gwt.user.client.ui.TreeItem;\r
57 import com.google.gwt.user.client.ui.Widget;\r
58 \r
59 /**\r
60  * A composite that displays the list of files in a particular folder.\r
61  */\r
62 public class FileList extends Composite implements TableListener, ClickListener {\r
63 \r
64         private HTML prevButton = new HTML("<a href='javascript:;'>&lt; Previous</a>", true);\r
65 \r
66         private HTML nextButton = new HTML("<a href='javascript:;'>Next &gt;</a>", true);\r
67 \r
68         private String showingStats = "";\r
69 \r
70         private int startIndex = 0;\r
71 \r
72         /**\r
73          * A constant that denotes the completion of an IncrementalCommand.\r
74          */\r
75         public static final boolean DONE = false;\r
76 \r
77         private boolean clickControl = false;\r
78 \r
79         private boolean clickShift = false;\r
80 \r
81         private int firstShift = -1;\r
82 \r
83         private ArrayList<Integer> selectedRows = new ArrayList<Integer>();\r
84 \r
85         /**\r
86          * The context menu for the selected file.\r
87          */\r
88         final DnDFocusPanel contextMenu;\r
89 \r
90         /**\r
91          * Specifies that the images available for this composite will be the ones\r
92          * available in FileContextMenu.\r
93          */\r
94         public interface Images extends FileContextMenu.Images, Folders.Images {\r
95 \r
96                 @Resource("gr/ebs/gss/resources/blank.gif")\r
97                 AbstractImagePrototype blank();\r
98 \r
99                 @Resource("gr/ebs/gss/resources/asc.png")\r
100                 AbstractImagePrototype asc();\r
101 \r
102                 @Resource("gr/ebs/gss/resources/desc.png")\r
103                 AbstractImagePrototype desc();\r
104 \r
105                 @Resource("gr/ebs/gss/resources/mimetypes/document_shared.png")\r
106                 AbstractImagePrototype documentShared();\r
107 \r
108                 @Resource("gr/ebs/gss/resources/mimetypes/kcmfontinst.png")\r
109                 AbstractImagePrototype wordprocessor();\r
110 \r
111                 @Resource("gr/ebs/gss/resources/mimetypes/log.png")\r
112                 AbstractImagePrototype spreadsheet();\r
113 \r
114                 @Resource("gr/ebs/gss/resources/mimetypes/kpresenter_kpr.png")\r
115                 AbstractImagePrototype presentation();\r
116 \r
117                 @Resource("gr/ebs/gss/resources/mimetypes/acroread.png")\r
118                 AbstractImagePrototype pdf();\r
119 \r
120                 @Resource("gr/ebs/gss/resources/mimetypes/image.png")\r
121                 AbstractImagePrototype image();\r
122 \r
123                 @Resource("gr/ebs/gss/resources/mimetypes/video2.png")\r
124                 AbstractImagePrototype video();\r
125 \r
126                 @Resource("gr/ebs/gss/resources/mimetypes/knotify.png")\r
127                 AbstractImagePrototype audio();\r
128 \r
129                 @Resource("gr/ebs/gss/resources/mimetypes/html.png")\r
130                 AbstractImagePrototype html();\r
131 \r
132                 @Resource("gr/ebs/gss/resources/mimetypes/txt.png")\r
133                 AbstractImagePrototype txt();\r
134 \r
135                 @Resource("gr/ebs/gss/resources/mimetypes/ark2.png")\r
136                 AbstractImagePrototype zip();\r
137 \r
138                 @Resource("gr/ebs/gss/resources/mimetypes/kcmfontinst_shared.png")\r
139                 AbstractImagePrototype wordprocessorShared();\r
140 \r
141                 @Resource("gr/ebs/gss/resources/mimetypes/log_shared.png")\r
142                 AbstractImagePrototype spreadsheetShared();\r
143 \r
144                 @Resource("gr/ebs/gss/resources/mimetypes/kpresenter_kpr_shared.png")\r
145                 AbstractImagePrototype presentationShared();\r
146 \r
147                 @Resource("gr/ebs/gss/resources/mimetypes/acroread_shared.png")\r
148                 AbstractImagePrototype pdfShared();\r
149 \r
150                 @Resource("gr/ebs/gss/resources/mimetypes/image_shared.png")\r
151                 AbstractImagePrototype imageShared();\r
152 \r
153                 @Resource("gr/ebs/gss/resources/mimetypes/video2_shared.png")\r
154                 AbstractImagePrototype videoShared();\r
155 \r
156                 @Resource("gr/ebs/gss/resources/mimetypes/knotify_shared.png")\r
157                 AbstractImagePrototype audioShared();\r
158 \r
159                 @Resource("gr/ebs/gss/resources/mimetypes/html_shared.png")\r
160                 AbstractImagePrototype htmlShared();\r
161 \r
162                 @Resource("gr/ebs/gss/resources/mimetypes/txt_shared.png")\r
163                 AbstractImagePrototype txtShared();\r
164 \r
165                 @Resource("gr/ebs/gss/resources/mimetypes/ark2_shared.png")\r
166                 AbstractImagePrototype zipShared();\r
167 \r
168         }\r
169 \r
170         /**\r
171          * A label with the number of files in this folder.\r
172          */\r
173         private HTML countLabel = new HTML();\r
174 \r
175         /**\r
176          * The table widget with the file list.\r
177          */\r
178         private Grid table = new Grid(GSS.VISIBLE_FILE_COUNT + 1, 8);\r
179 \r
180         /**\r
181          * The navigation bar for paginating the results.\r
182          */\r
183         private HorizontalPanel navBar = new HorizontalPanel();\r
184 \r
185         /**\r
186          * The number of files in this folder.\r
187          */\r
188         int folderFileCount;\r
189 \r
190         /**\r
191          * Total folder size\r
192          */\r
193         long folderTotalSize;\r
194 \r
195         /**\r
196          * A cache of the files in the list.\r
197          */\r
198         private List<FileResource> files;\r
199 \r
200         /**\r
201          * The widget's image bundle.\r
202          */\r
203         private final Images images;\r
204 \r
205         private String sortingProperty = "name";\r
206 \r
207         private boolean sortingType = true;\r
208 \r
209         private HTML nameLabel;\r
210 \r
211         private HTML versionLabel;\r
212 \r
213         private HTML sizeLabel;\r
214 \r
215         private HTML dateLabel;\r
216 \r
217         private HTML ownerLabel;\r
218 \r
219         private HTML pathLabel;\r
220 \r
221         /**\r
222          * Construct the file list widget. This entails setting up the widget\r
223          * layout, fetching the number of files in the current folder from the\r
224          * server and filling the local file cache of displayed files with data from\r
225          * the server, as well.\r
226          *\r
227          * @param _images\r
228          */\r
229         public FileList(Images _images) {\r
230                 images = _images;\r
231 \r
232                 prevButton.addClickListener(this);\r
233                 nextButton.addClickListener(this);\r
234 \r
235                 contextMenu = new DnDFocusPanel(new HTML(images.fileContextMenu().getHTML()));\r
236                 contextMenu.addClickListener(new FileContextMenu(images, false, false));\r
237                 GSS.get().getDragController().makeDraggable(contextMenu);\r
238 \r
239                 // Setup the table.\r
240                 table.setCellSpacing(0);\r
241                 table.setCellPadding(2);\r
242                 table.setWidth("100%");\r
243 \r
244                 // Hook up events.\r
245                 table.addTableListener(this);\r
246 \r
247                 // Create the 'navigation' bar at the upper-right.\r
248                 HorizontalPanel innerNavBar = new HorizontalPanel();\r
249                 innerNavBar.setStyleName("gss-ListNavBar");\r
250                 innerNavBar.setSpacing(8);\r
251                 innerNavBar.add(prevButton);\r
252                 innerNavBar.add(countLabel);\r
253                 innerNavBar.add(nextButton);\r
254                 navBar.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);\r
255                 navBar.add(innerNavBar);\r
256                 navBar.setWidth("100%");\r
257 \r
258                 initWidget(table);\r
259                 setStyleName("gss-List");\r
260 \r
261                 initTable();\r
262                 DeferredCommand.addCommand(new IncrementalCommand() {\r
263 \r
264                         public boolean execute() {\r
265                                 return fetchRootFolder();\r
266                         }\r
267                 });\r
268                 sinkEvents(Event.ONCONTEXTMENU);\r
269                 sinkEvents(Event.ONMOUSEUP);\r
270                 sinkEvents(Event.ONCLICK);\r
271                 sinkEvents(Event.ONKEYDOWN);\r
272                 sinkEvents(Event.ONDBLCLICK);\r
273                 GSS.preventIESelection();\r
274         }\r
275 \r
276         public void onClick(Widget sender) {\r
277                 if (sender == nextButton) {\r
278                         // Move forward a page.\r
279                         clearSelectedRows();\r
280                         startIndex += GSS.VISIBLE_FILE_COUNT;\r
281                         if (startIndex >= folderFileCount)\r
282                                 startIndex -= GSS.VISIBLE_FILE_COUNT;\r
283                         else\r
284                                 update();\r
285                 } else if (sender == prevButton) {\r
286                         clearSelectedRows();\r
287                         // Move back a page.\r
288                         startIndex -= GSS.VISIBLE_FILE_COUNT;\r
289                         if (startIndex < 0)\r
290                                 startIndex = 0;\r
291                         else\r
292                                 update();\r
293                 }\r
294         }\r
295 \r
296         @Override\r
297         public void onBrowserEvent(Event event) {\r
298                 if (files == null || files.size() == 0) {\r
299                         if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() == 0) {\r
300                                 FileContextMenu fm = new FileContextMenu(images, false, true);\r
301                                 fm.onEmptyEvent(event);\r
302                         }\r
303                         return;\r
304                 }\r
305                 if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() != 0) {\r
306                         FileContextMenu fm = new FileContextMenu(images, false, false);\r
307                         fm.onEvent(event);\r
308                 } else if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() == 0) {\r
309                         FileContextMenu fm = new FileContextMenu(images, false, true);\r
310                         fm.onEmptyEvent(event);\r
311                 } else if (DOM.eventGetType(event) == Event.ONDBLCLICK)\r
312                         if (getSelectedFiles().size() == 1) {\r
313                                 GSS app = GSS.get();\r
314                                 FileResource file = getSelectedFiles().get(0);\r
315                                 String dateString = RestCommand.getDate();\r
316                                 String resource = file.getUri().substring(app.getApiPath().length() - 1, file.getUri().length());\r
317                                 String sig = app.getCurrentUserResource().getUsername() + " " +\r
318                                                 RestCommand.calculateSig("GET", dateString, resource,\r
319                                                 RestCommand.base64decode(app.getToken()));\r
320                                 Window.open(file.getUri() + "?Authorization=" + URL.encodeComponent(sig) + "&Date=" + URL.encodeComponent(dateString), "_blank", "");\r
321                                 event.preventDefault();\r
322                                 return;\r
323                         }\r
324                 if (DOM.eventGetType(event) == Event.ONCLICK) {\r
325                         if (DOM.eventGetCtrlKey(event))\r
326                                 clickControl = true;\r
327                         else\r
328                                 clickControl = false;\r
329                         if (DOM.eventGetShiftKey(event)) {\r
330                                 clickShift = true;\r
331                                 if (selectedRows.size() == 1)\r
332                                         firstShift = selectedRows.get(0) - startIndex;\r
333                                 event.preventDefault();\r
334                         } else {\r
335                                 clickShift = false;\r
336                                 firstShift = -1;\r
337                                 event.preventDefault();\r
338                         }\r
339                 }\r
340                 super.onBrowserEvent(event);\r
341         }\r
342 \r
343         /**\r
344          * Retrieve the root folder for the current user.\r
345          *\r
346          * @return true if the retrieval was successful\r
347          */\r
348         protected boolean fetchRootFolder() {\r
349                 UserResource user = GSS.get().getCurrentUserResource();\r
350                 if (user == null)\r
351                         return !DONE;\r
352                 // Update cache and clear selection.\r
353                 updateFileCache(true);\r
354                 return DONE;\r
355         }\r
356 \r
357         public void onCellClicked(SourcesTableEvents sender, int row, int cell) {\r
358                 // Select the row that was clicked (-1 to account for header row).\r
359                 if (row > folderFileCount)\r
360                         return;\r
361                 if (clickShift) {\r
362                         GWT.log("Row is: " + row + " fs: " + firstShift, null);\r
363                         if (firstShift == -1)\r
364                                 firstShift = row;\r
365                         else if (row > firstShift) {\r
366                                 clearSelectedRows();\r
367                                 for (int i = firstShift; i < row; i++) {\r
368                                         selectedRows.add(startIndex + i);\r
369                                         styleRow(i, true);\r
370                                 }\r
371                                 GSS.get().setCurrentSelection(getSelectedFiles());\r
372                                 contextMenu.setFiles(getSelectedFiles());\r
373                                 makeRowDraggable(row);\r
374                         } else if (row != -1 && row == firstShift) {\r
375                                 selectedRows.add(row - 1);\r
376                                 styleRow(row, true);\r
377                                 styleRow(row - 1, true);\r
378                                 GSS.get().setCurrentSelection(getSelectedFiles());\r
379                                 contextMenu.setFiles(getSelectedFiles());\r
380                                 makeRowDraggable(row);\r
381                         } else if (row < firstShift) {\r
382                                 GWT.log("Row is:" + row + " fs:" + firstShift, null);\r
383                                 clearSelectedRows();\r
384 \r
385                                 for (int i = firstShift; i >= row - 1; i--) {\r
386                                         selectedRows.add(startIndex + i);\r
387                                         styleRow(i, true);\r
388                                 }\r
389                                 GSS.get().setCurrentSelection(getSelectedFiles());\r
390                                 makeRowDraggable(row);\r
391                                 contextMenu.setFiles(getSelectedFiles());\r
392                         }\r
393                 } else if (row > 0)\r
394                         selectRow(row - 1);\r
395         }\r
396 \r
397         /**\r
398          * Initializes the table so that it contains enough rows for a full page of\r
399          * files.\r
400          */\r
401         private void initTable() {\r
402                 nameLabel = new HTML("Name");\r
403                 nameLabel.addClickListener(new ClickListener() {\r
404 \r
405                         public void onClick(Widget sender) {\r
406                                 sortFiles("name");\r
407                                 update();\r
408                         }\r
409 \r
410                 });\r
411                 versionLabel = new HTML("Version");\r
412                 versionLabel.addClickListener(new ClickListener() {\r
413 \r
414                         public void onClick(Widget sender) {\r
415                                 sortFiles("version");\r
416                                 update();\r
417                         }\r
418 \r
419                 });\r
420                 sizeLabel = new HTML("Size");\r
421                 sizeLabel.addClickListener(new ClickListener() {\r
422 \r
423                         public void onClick(Widget sender) {\r
424                                 sortFiles("size");\r
425                                 update();\r
426                         }\r
427 \r
428                 });\r
429                 dateLabel = new HTML("Date");\r
430                 dateLabel.addClickListener(new ClickListener() {\r
431 \r
432                         public void onClick(Widget sender) {\r
433                                 sortFiles("date");\r
434                                 update();\r
435                         }\r
436 \r
437                 });\r
438                 ownerLabel = new HTML("Owner");\r
439                 ownerLabel.addClickListener(new ClickListener() {\r
440 \r
441                         public void onClick(Widget sender) {\r
442                                 sortFiles("owner");\r
443                                 update();\r
444                         }\r
445 \r
446                 });\r
447                 pathLabel = new HTML("Path");\r
448                 pathLabel.addClickListener(new ClickListener() {\r
449 \r
450                         public void onClick(Widget sender) {\r
451                                 sortFiles("path");\r
452                                 update();\r
453                         }\r
454 \r
455                 });\r
456                 // Create the header row.\r
457                 table.setText(0, 0, "");\r
458                 table.setWidget(0, 1, nameLabel);\r
459                 table.setWidget(0, 2, ownerLabel);\r
460                 table.setWidget(0, 3, pathLabel);\r
461                 table.setWidget(0, 4, versionLabel);\r
462                 table.setWidget(0, 5, sizeLabel);\r
463                 table.setWidget(0, 6, dateLabel);\r
464                 table.setWidget(0, 7, navBar);\r
465                 table.getRowFormatter().setStyleName(0, "gss-ListHeader");\r
466 \r
467                 // Initialize the rest of the rows.\r
468                 for (int i = 1; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
469                         table.setText(i, 0, "");\r
470                         table.setText(i, 1, "");\r
471                         table.setText(i, 2, "");\r
472                         table.setText(i, 3, "");\r
473                         table.setText(i, 4, "");\r
474                         table.setText(i, 5, "");\r
475                         table.setText(i, 6, "");\r
476                         table.setText(i, 7, "");\r
477                         table.getCellFormatter().setWordWrap(i, 0, false);\r
478                         table.getCellFormatter().setWordWrap(i, 1, false);\r
479                         table.getCellFormatter().setWordWrap(i, 2, false);\r
480                         table.getCellFormatter().setWordWrap(i, 3, false);\r
481                         table.getCellFormatter().setWordWrap(i, 4, false);\r
482                         table.getCellFormatter().setWordWrap(i, 5, false);\r
483                         table.getCellFormatter().setWordWrap(i, 6, false);\r
484                         table.getCellFormatter().setWordWrap(i, 7, false);\r
485                         table.getCellFormatter().setHorizontalAlignment(i, 4, HasHorizontalAlignment.ALIGN_CENTER);\r
486                 }\r
487                 prevButton.setVisible(false);\r
488                 nextButton.setVisible(false);\r
489         }\r
490 \r
491         /**\r
492          * Selects the given row (relative to the current page).\r
493          *\r
494          * @param row the row to be selected\r
495          */\r
496         private void selectRow(final int row) {\r
497                 if (row < folderFileCount) {\r
498                         if (clickControl)\r
499                                 if (selectedRows.contains(row)) {\r
500                                         int i = selectedRows.indexOf(startIndex + row);\r
501                                         selectedRows.remove(i);\r
502                                         styleRow(row, false);\r
503                                 } else {\r
504                                         selectedRows.add(startIndex + row);\r
505                                         styleRow(row, true);\r
506                                 }\r
507                         else if (selectedRows.size() == 1 && selectedRows.contains(row)){\r
508                                 clearSelectedRows();\r
509                                 return;\r
510                         }\r
511                         else {\r
512                                 clearSelectedRows();\r
513                                 selectedRows.add(startIndex + row);\r
514                                 styleRow(row, true);\r
515                         }\r
516                         if (selectedRows.size() == 1)\r
517                                 GSS.get().setCurrentSelection(files.get(selectedRows.get(0)));\r
518                         else if(selectedRows.size() == 0)\r
519                                 GSS.get().setCurrentSelection(null);\r
520                         else\r
521                                 GSS.get().setCurrentSelection(getSelectedFiles());\r
522                         contextMenu.setFiles(getSelectedFiles());\r
523                         makeRowDraggable(row+1);\r
524                 }\r
525         }\r
526 \r
527         public List<FileResource> getSelectedFiles() {\r
528                 List<FileResource> result = new ArrayList();\r
529                 for (int i : selectedRows)\r
530                         result.add(files.get(i));\r
531                 return result;\r
532         }\r
533 \r
534         /**\r
535          * Make the specified row look like selected or not, according to the\r
536          * <code>selected</code> flag.\r
537          *\r
538          * @param row\r
539          * @param selected\r
540          */\r
541         void styleRow(final int row, final boolean selected) {\r
542                 if (row != -1 && row >= 0)\r
543                         if (selected)\r
544                                 table.getRowFormatter().addStyleName(row + 1, "gss-SelectedRow");\r
545                         else\r
546                                 table.getRowFormatter().removeStyleName(row + 1, "gss-SelectedRow");\r
547         }\r
548 \r
549         /**\r
550          * Update the display of the file list.\r
551          */\r
552         void update() {\r
553                 int count = folderFileCount;\r
554                 int max = startIndex + GSS.VISIBLE_FILE_COUNT;\r
555                 if (max > count)\r
556                         max = count;\r
557                 folderTotalSize = 0;\r
558 \r
559                 // Show the selected files.\r
560                 int i = 1;\r
561                 for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
562                         // Don't read past the end.\r
563                         // if (i > folderFileCount)\r
564                         // break;\r
565                         if (startIndex + i > folderFileCount)\r
566                                 break;\r
567                         // Add a new row to the table, then set each of its columns to the\r
568                         // proper values.\r
569                         FileResource file = files.get(startIndex + i - 1);\r
570                         table.setWidget(i, 0, getFileIcon(file).createImage());\r
571                         table.getRowFormatter().addStyleName(i, "gss-fileRow");\r
572 \r
573                         table.setHTML(i, 1, file.getName());\r
574                         table.setText(i, 2, file.getOwner());\r
575                         table.setText(i, 3, file.getPath());\r
576                         table.setText(i, 4, String.valueOf(file.getVersion()));\r
577                         table.setText(i, 5, String.valueOf(file.getFileSizeAsString()));\r
578                         final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");\r
579                         table.setText(i, 6, formatter.format(file.getCreationDate()));\r
580                         folderTotalSize += file.getContentLength();\r
581                 }\r
582 \r
583                 // Clear any remaining slots.\r
584                 for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
585                         table.setHTML(i, 0, "&nbsp;");\r
586                         table.setHTML(i, 1, "&nbsp;");\r
587                         table.setHTML(i, 2, "&nbsp;");\r
588                         table.setHTML(i, 3, "&nbsp;");\r
589                         table.setHTML(i, 4, "&nbsp;");\r
590                         table.setHTML(i, 5, "&nbsp;");\r
591                         table.setHTML(i, 6, "&nbsp;");\r
592                         table.setHTML(i, 7, "&nbsp;");\r
593                 }\r
594 \r
595                 if (folderFileCount == 0) {\r
596                         showingStats = "no files";\r
597                         prevButton.setVisible(false);\r
598                         nextButton.setVisible(false);\r
599                 } else if (folderFileCount < GSS.VISIBLE_FILE_COUNT) {\r
600                         if (folderFileCount == 1)\r
601                                 showingStats = "1 file";\r
602                         else\r
603                                 showingStats = folderFileCount + " files";\r
604                         showingStats += " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";\r
605                         prevButton.setVisible(false);\r
606                         nextButton.setVisible(false);\r
607                 } else {\r
608                         showingStats = "" + (startIndex + 1) + " - " + max + " of " + count + " files" + " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";\r
609                         prevButton.setVisible(startIndex != 0);\r
610                         nextButton.setVisible(startIndex + GSS.VISIBLE_FILE_COUNT < count);\r
611                 }\r
612                 updateCurrentlyShowingStats();\r
613 \r
614         }\r
615 \r
616         /**\r
617          * Return the proper icon based on the MIME type of the file.\r
618          *\r
619          * @param file\r
620          * @return the icon\r
621          */\r
622         private AbstractImagePrototype getFileIcon(FileResource file) {\r
623                 String mimetype = file.getContentType();\r
624                 boolean shared = file.isShared();\r
625                 if (mimetype == null)\r
626                         return shared ? images.documentShared() : images.document();\r
627                 mimetype = mimetype.toLowerCase();\r
628                 if (mimetype.startsWith("application/pdf"))\r
629                         return shared ? images.pdfShared() : images.pdf();\r
630                 else if (mimetype.startsWith("application/vnd.ms-excel"))\r
631                         return shared ? images.spreadsheetShared() : images.spreadsheet();\r
632                 else if (mimetype.startsWith("application/msword"))\r
633                         return shared ? images.wordprocessorShared() : images.wordprocessor();\r
634                 else if (mimetype.startsWith("application/vnd.ms-powerpoint"))\r
635                         return shared ? images.presentationShared() : images.presentation();\r
636                 else if (mimetype.startsWith("application/zip") ||\r
637                                         mimetype.startsWith("application/gzip") ||\r
638                                         mimetype.startsWith("application/x-gzip") ||\r
639                                         mimetype.startsWith("application/x-tar") ||\r
640                                         mimetype.startsWith("application/x-gtar"))\r
641                         return shared ? images.zipShared() : images.zip();\r
642                 else if (mimetype.startsWith("text/html"))\r
643                         return shared ? images.htmlShared() : images.html();\r
644                 else if (mimetype.startsWith("text/plain"))\r
645                         return shared ? images.txtShared() : images.txt();\r
646                 else if (mimetype.startsWith("image/"))\r
647                         return shared ? images.imageShared() : images.image();\r
648                 else if (mimetype.startsWith("video/"))\r
649                         return shared ? images.videoShared() : images.video();\r
650                 else if (mimetype.startsWith("audio/"))\r
651                         return shared ? images.audioShared() : images.audio();\r
652                 return shared ? images.documentShared() : images.document();\r
653         }\r
654 \r
655         /**\r
656          * Update status panel with currently showing file stats.\r
657          */\r
658         public void updateCurrentlyShowingStats() {\r
659                 GSS.get().getStatusPanel().updateCurrentlyShowing(showingStats);\r
660         }\r
661 \r
662         /**\r
663          * Adjust the height of the table by adding and removing rows as necessary.\r
664          *\r
665          * @param newHeight the new height to reach\r
666          */\r
667         void resizeTableHeight(final int newHeight) {\r
668                 GWT.log("Panel: " + newHeight + ", parent: " + table.getParent().getOffsetHeight(), null);\r
669                 // Fill the rest with empty slots.\r
670                 if (newHeight > table.getOffsetHeight())\r
671                         while (newHeight > table.getOffsetHeight()) {\r
672                                 table.resizeRows(table.getRowCount() + 1);\r
673                                 GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);\r
674                         }\r
675                 else\r
676                         while (newHeight < table.getOffsetHeight()) {\r
677                                 table.resizeRows(table.getRowCount() - 1);\r
678                                 GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);\r
679                         }\r
680         }\r
681 \r
682         public void updateFileCache(boolean updateSelectedFolder, final boolean clearSelection) {\r
683                 if (!updateSelectedFolder && !GSS.get().getFolders().getTrashItem().equals(GSS.get().getFolders().getCurrent()))\r
684                         updateFileCache(clearSelection);\r
685                 else if (GSS.get().getFolders().getCurrent() != null) {\r
686                         final DnDTreeItem folderItem = (DnDTreeItem) GSS.get().getFolders().getCurrent();\r
687                         if (folderItem.getFolderResource() != null) {\r
688                                 update();\r
689                                 GetCommand<FolderResource> gf = new GetCommand<FolderResource>(FolderResource.class, folderItem.getFolderResource().getUri()) {\r
690 \r
691                                                 @Override\r
692                                                 public void onComplete() {\r
693                                                         folderItem.setUserObject(getResult());\r
694                                                         if(GSS.get().getFolders().isFileItem(folderItem)){\r
695                                                                 String[] filePaths = new String[folderItem.getFolderResource().getFilePaths().size()];\r
696                                                                 int c=0;\r
697                                                                 for(String fpath : folderItem.getFolderResource().getFilePaths()){\r
698                                                                         filePaths[c] = fpath + "?" + Math.random();\r
699                                                                         c++;\r
700                                                                 }\r
701                                                                 MultipleHeadCommand<FileResource> getFiles = new MultipleHeadCommand<FileResource>(FileResource.class, filePaths){\r
702 \r
703                                                                         @Override\r
704                                                                         public void onComplete(){\r
705                                                                                 List<FileResource> result = getResult();\r
706                                                                                 //remove random from path\r
707                                                                                 for(FileResource r : result){\r
708                                                                                         String p = r.getUri();\r
709                                                                                         int indexOfQuestionMark = p.lastIndexOf('?');\r
710                                                                                         if(indexOfQuestionMark>0)\r
711                                                                                                 r.setUri(p.substring(0, indexOfQuestionMark));\r
712                                                                                 }\r
713                                                                                 folderItem.getFolderResource().setFiles(result);\r
714                                                                                 updateFileCache(clearSelection);\r
715                                                                         }\r
716 \r
717                                                                         @Override\r
718                                                                         public void onError(String p, Throwable throwable) {\r
719                                                                                 if(throwable instanceof RestException)\r
720                                                                                         GSS.get().displayError("Unable to retrieve file details:"+((RestException)throwable).getHttpStatusText());\r
721                                                                         }\r
722 \r
723                                                                         @Override\r
724                                                                         public void onError(Throwable t) {\r
725                                                                                 GWT.log("", t);\r
726                                                                                 GSS.get().displayError("Unable to fetch files for folder " + folderItem.getFolderResource().getName());\r
727                                                                         }\r
728 \r
729                                                                 };\r
730                                                                 DeferredCommand.addCommand(getFiles);\r
731                                                         }\r
732                                                         else\r
733                                                                 updateFileCache(clearSelection);\r
734                                                 }\r
735 \r
736                                                 @Override\r
737                                                 public void onError(Throwable t) {\r
738                                                         GWT.log("", t);\r
739                                                         GSS.get().displayError("Unable to fetch folder " + folderItem.getFolderResource().getName());\r
740                                                 }\r
741                                         };\r
742                                         DeferredCommand.addCommand(gf);\r
743                         } else if (folderItem.getTrashResource() != null) {\r
744                                 GetCommand<TrashResource> gt = new GetCommand<TrashResource>(TrashResource.class, folderItem.getTrashResource().getUri()) {\r
745 \r
746                                         @Override\r
747                                         public void onComplete() {\r
748                                                 folderItem.setUserObject(getResult());\r
749                                                 updateFileCache(clearSelection);\r
750                                         }\r
751 \r
752                                         @Override\r
753                                         public void onError(Throwable t) {\r
754                                                 if (t instanceof RestException && (((RestException) t).getHttpStatusCode() == 204 || ((RestException) t).getHttpStatusCode() == 1223)) {\r
755                                                         folderItem.setUserObject(new TrashResource(folderItem.getTrashResource().getUri()));\r
756                                                         updateFileCache(clearSelection);\r
757                                                 } else {\r
758                                                         GWT.log("", t);\r
759                                                         GSS.get().displayError("Unable to fetch trash resource");\r
760                                                 }\r
761                                         }\r
762                                 };\r
763                                 DeferredCommand.addCommand(gt);\r
764                         } else if (folderItem.getSharedResource() != null) {\r
765                                 GetCommand<SharedResource> gt = new GetCommand<SharedResource>(SharedResource.class, folderItem.getSharedResource().getUri()) {\r
766 \r
767                                         @Override\r
768                                         public void onComplete() {\r
769                                                 folderItem.setUserObject(getResult());\r
770                                                 updateFileCache(clearSelection);\r
771                                         }\r
772 \r
773                                         @Override\r
774                                         public void onError(Throwable t) {\r
775                                                 GWT.log("", t);\r
776                                                 GSS.get().displayError("Unable to fetch My Shares resource");\r
777                                         }\r
778                                 };\r
779                                 DeferredCommand.addCommand(gt);\r
780                         } else if (folderItem.getOtherUserResource() != null) {\r
781                                 GetCommand<OtherUserResource> gt = new GetCommand<OtherUserResource>(OtherUserResource.class, folderItem.getOtherUserResource().getUri()) {\r
782 \r
783                                         @Override\r
784                                         public void onComplete() {\r
785                                                 folderItem.setUserObject(getResult());\r
786                                                 updateFileCache(clearSelection);\r
787                                         }\r
788 \r
789                                         @Override\r
790                                         public void onError(Throwable t) {\r
791                                                 GWT.log("", t);\r
792                                                 GSS.get().displayError("Unable to fetch My Shares resource");\r
793                                         }\r
794                                 };\r
795                                 DeferredCommand.addCommand(gt);\r
796                         }\r
797                 } else\r
798                         updateFileCache(clearSelection);\r
799         }\r
800 \r
801         /**\r
802          * Update the file cache with data from the server.\r
803          *\r
804          * @param userId the ID of the current user\r
805          */\r
806         private void updateFileCache(boolean clearSelection) {\r
807                 if (clearSelection)\r
808                         clearSelectedRows();\r
809                 clearLabels();\r
810                 sortingProperty = "name";\r
811                 nameLabel.setHTML("Name&nbsp;" + images.desc().getHTML());\r
812                 sortingType = true;\r
813                 startIndex = 0;\r
814                 final TreeItem folderItem = GSS.get().getFolders().getCurrent();\r
815                 // Validation.\r
816                 if (folderItem == null || GSS.get().getFolders().isOthersShared(folderItem)) {\r
817                         setFiles(new ArrayList<FileResource>());\r
818                         update();\r
819                         return;\r
820                 }\r
821                 if (folderItem instanceof DnDTreeItem) {\r
822                         DnDTreeItem dnd = (DnDTreeItem) folderItem;\r
823                         if (dnd.getFolderResource() != null) {\r
824                                 if (GSS.get().getFolders().isTrashItem(dnd))\r
825                                         setFiles(new ArrayList<FileResource>());\r
826                                 else\r
827                                         setFiles(dnd.getFolderResource().getFiles());\r
828 \r
829                         } else if (dnd.getTrashResource() != null)\r
830                                 setFiles(dnd.getTrashResource().getFiles());\r
831                         else if (dnd.getSharedResource() != null)\r
832                                 setFiles(dnd.getSharedResource().getFiles());\r
833                         else if (dnd.getOtherUserResource() != null)\r
834                                 setFiles(dnd.getOtherUserResource().getFiles());\r
835                         else\r
836                                 setFiles(dnd.getFolderResource().getFiles());\r
837 \r
838                         update();\r
839                 }\r
840         }\r
841 \r
842         /**\r
843          * Fill the file cache with data.\r
844          */\r
845         public void setFiles(final List<FileResource> _files) {\r
846                 if (_files.size() > 0 && !GSS.get().getFolders().isTrash(GSS.get().getFolders().getCurrent())) {\r
847                         files = new ArrayList<FileResource>();\r
848                         for (FileResource fres : _files)\r
849                                 if (!fres.isDeleted())\r
850                                         files.add(fres);\r
851                 } else\r
852                         files = _files;\r
853                 Collections.sort(files, new Comparator<FileResource>() {\r
854 \r
855                         public int compare(FileResource arg0, FileResource arg1) {\r
856                                 return arg0.getName().compareTo(arg1.getName());\r
857                         }\r
858 \r
859                 });\r
860                 folderFileCount = files.size();\r
861         }\r
862 \r
863         private void sortFiles(final String sortProperty) {\r
864                 if (sortProperty.equals(sortingProperty))\r
865                         sortingType = !sortingType;\r
866                 else {\r
867                         sortingProperty = sortProperty;\r
868                         sortingType = true;\r
869                 }\r
870                 clearLabels();\r
871                 clearSelectedRows();\r
872                 if (files == null || files.size() == 0)\r
873                         return;\r
874                 Collections.sort(files, new Comparator<FileResource>() {\r
875 \r
876                         public int compare(FileResource arg0, FileResource arg1) {\r
877                                 if (sortingType)\r
878                                         if (sortProperty.equals("version")) {\r
879                                                 versionLabel.setHTML("Version&nbsp;" + images.desc().getHTML());\r
880                                                 return new Integer(arg0.getVersion()).compareTo(new Integer(arg1.getVersion()));\r
881                                         } else if (sortProperty.equals("owner")) {\r
882                                                 ownerLabel.setHTML("Owner&nbsp;" + images.desc().getHTML());\r
883                                                 return new Integer(arg0.getOwner()).compareTo(new Integer(arg1.getOwner()));\r
884                                         } else if (sortProperty.equals("date")) {\r
885                                                 dateLabel.setHTML("Date&nbsp;" + images.desc().getHTML());\r
886                                                 return arg0.getCreationDate().compareTo(arg1.getCreationDate());\r
887                                         } else if (sortProperty.equals("size")) {\r
888                                                 sizeLabel.setHTML("Size&nbsp;" + images.desc().getHTML());\r
889                                                 return new Long(arg0.getContentLength()).compareTo(new Long(arg1.getContentLength()));\r
890                                         } else if (sortProperty.equals("name")) {\r
891                                                 nameLabel.setHTML("Name&nbsp;" + images.desc().getHTML());\r
892                                                 return arg0.getName().compareTo(arg1.getName());\r
893                                         } else if (sortProperty.equals("path")) {\r
894                                                 pathLabel.setHTML("Path&nbsp;" + images.desc().getHTML());\r
895                                                 return arg0.getUri().compareTo(arg1.getUri());\r
896                                         } else {\r
897                                                 nameLabel.setHTML("Name&nbsp;" + images.desc().getHTML());\r
898                                                 return arg0.getName().compareTo(arg1.getName());\r
899                                         }\r
900                                 else if (sortProperty.equals("version")) {\r
901                                         versionLabel.setHTML("Version&nbsp;" + images.asc().getHTML());\r
902                                         return new Integer(arg1.getVersion()).compareTo(new Integer(arg0.getVersion()));\r
903                                 } else if (sortProperty.equals("owner")) {\r
904                                         ownerLabel.setHTML("Owner&nbsp;" + images.asc().getHTML());\r
905                                         return new Integer(arg1.getOwner()).compareTo(new Integer(arg0.getOwner()));\r
906                                 } else if (sortProperty.equals("date")) {\r
907                                         dateLabel.setHTML("Date&nbsp;" + images.asc().getHTML());\r
908                                         return arg1.getCreationDate().compareTo(arg0.getCreationDate());\r
909                                 } else if (sortProperty.equals("size")) {\r
910                                         sizeLabel.setHTML("Size&nbsp;" + images.asc().getHTML());\r
911                                         return new Long(arg1.getContentLength()).compareTo(new Long(arg0.getContentLength()));\r
912                                 } else if (sortProperty.equals("name")) {\r
913                                         nameLabel.setHTML("Name&nbsp;" + images.asc().getHTML());\r
914                                         return arg1.getName().compareTo(arg0.getName());\r
915                                 } else if (sortProperty.equals("path")) {\r
916                                         pathLabel.setHTML("Path&nbsp;" + images.asc().getHTML());\r
917                                         return arg1.getUri().compareTo(arg0.getUri());\r
918                                 } else {\r
919                                         nameLabel.setHTML("Name&nbsp;" + images.asc().getHTML());\r
920                                         return arg1.getName().compareTo(arg0.getName());\r
921                                 }\r
922                         }\r
923 \r
924                 });\r
925         }\r
926 \r
927         private void clearLabels() {\r
928                 nameLabel.setText("Name");\r
929                 versionLabel.setText("Version");\r
930                 sizeLabel.setText("Size");\r
931                 dateLabel.setText("Date");\r
932                 ownerLabel.setText("Owner");\r
933                 pathLabel.setText("Path");\r
934         }\r
935 \r
936         /**\r
937          * Retrieve the table.\r
938          *\r
939          * @return the table\r
940          */\r
941         Grid getTable() {\r
942                 return table;\r
943         }\r
944 \r
945         /**\r
946          * Does the list contains the requested filename\r
947          *\r
948          * @param fileName\r
949          * @return true/false\r
950          */\r
951         public boolean contains(String fileName) {\r
952                 for (int i = 0; i < files.size(); i++)\r
953                         if (files.get(i).getName().equals(fileName))\r
954                                 return true;\r
955                 return false;\r
956         }\r
957 \r
958         public void clearSelectedRows() {\r
959                 for (int r : selectedRows) {\r
960                         int row = r - startIndex;\r
961                         styleRow(row, false);\r
962                 }\r
963                 selectedRows.clear();\r
964                 Object sel = GSS.get().getCurrentSelection();\r
965                 if (sel instanceof FileResource || sel instanceof List)\r
966                         GSS.get().setCurrentSelection(null);\r
967         }\r
968 \r
969         /**\r
970          *\r
971          */\r
972         public void selectAllRows() {\r
973                 clearSelectedRows();\r
974                 int count = folderFileCount;\r
975                 if (count == 0)\r
976                         return;\r
977                 int max = startIndex + GSS.VISIBLE_FILE_COUNT;\r
978                 if (max > count)\r
979                         max = count;\r
980                 int i = 1;\r
981                 for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
982                         // Don't read past the end.\r
983                         // if (i > folderFileCount)\r
984                         // break;\r
985                         if (startIndex + i > folderFileCount)\r
986                                 break;\r
987                         selectedRows.add(startIndex + i - 1);\r
988                         styleRow(i - 1, true);\r
989                 }\r
990                 GSS.get().setCurrentSelection(getSelectedFiles());\r
991                 contextMenu.setFiles(getSelectedFiles());\r
992                 makeRowDraggable(i-1);\r
993 \r
994         }\r
995 \r
996         private void makeRowDraggable(int row){\r
997                 int contextRow = getWidgetRow(contextMenu, table);\r
998                 if (contextRow != -1)\r
999                         table.setWidget(contextRow, 0, getFileIcon(files.get(contextRow - 1)).createImage());\r
1000                 contextMenu.setWidget(new HTML(getFileIcon(files.get(row - 1)).getHTML()));\r
1001                 table.setWidget(row, 0, contextMenu);\r
1002         }\r
1003 \r
1004         private int getWidgetRow(Widget widget, Grid grid) {\r
1005                 for (int row = 0; row < grid.getRowCount(); row++)\r
1006                         for (int col = 0; col < grid.getCellCount(row); col++) {\r
1007                                 Widget w = table.getWidget(row, col);\r
1008                                 if (w == widget)\r
1009                                         return row;\r
1010                         }\r
1011                 return -1;\r
1012         }\r
1013 \r
1014 }\r