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