reset sorting when updating file list
[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
21 import static com.google.gwt.query.client.GQuery.$;
22 import gr.ebs.gss.client.rest.GetCommand;
23 import gr.ebs.gss.client.rest.RestCommand;
24 import gr.ebs.gss.client.rest.resource.FileResource;
25 import gr.ebs.gss.client.rest.resource.OtherUserResource;
26 import gr.ebs.gss.client.rest.resource.OthersFolderResource;
27 import gr.ebs.gss.client.rest.resource.RestResource;
28 import gr.ebs.gss.client.rest.resource.RestResourceWrapper;
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 import gr.ebs.gss.client.rest.resource.UserSearchResource;
33 import gwtquery.plugins.draggable.client.DraggableOptions;
34 import gwtquery.plugins.draggable.client.StopDragException;
35 import gwtquery.plugins.draggable.client.DraggableOptions.DragFunction;
36 import gwtquery.plugins.draggable.client.DraggableOptions.RevertOption;
37 import gwtquery.plugins.draggable.client.events.DragContext;
38 import gwtquery.plugins.draggable.client.events.DragStartEvent;
39 import gwtquery.plugins.draggable.client.events.DragStopEvent;
40 import gwtquery.plugins.draggable.client.events.DragStartEvent.DragStartEventHandler;
41 import gwtquery.plugins.draggable.client.events.DragStopEvent.DragStopEventHandler;
42 import gwtquery.plugins.droppable.client.gwt.DragAndDropCellTable;
43 import gwtquery.plugins.droppable.client.gwt.DragAndDropColumn;
44
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.Comparator;
48 import java.util.Iterator;
49 import java.util.List;
50
51 import com.google.gwt.cell.client.AbstractCell;
52 import com.google.gwt.cell.client.ImageResourceCell;
53 import com.google.gwt.cell.client.SafeHtmlCell;
54 import com.google.gwt.cell.client.TextCell;
55 import com.google.gwt.cell.client.ValueUpdater;
56 import com.google.gwt.cell.client.Cell.Context;
57 import com.google.gwt.core.client.GWT;
58 import com.google.gwt.core.client.Scheduler;
59 import com.google.gwt.core.client.Scheduler.RepeatingCommand;
60 import com.google.gwt.dom.client.Element;
61 import com.google.gwt.dom.client.NativeEvent;
62 import com.google.gwt.dom.client.Style.Cursor;
63 import com.google.gwt.event.dom.client.KeyCodes;
64 import com.google.gwt.http.client.URL;
65 import com.google.gwt.i18n.client.DateTimeFormat;
66 import com.google.gwt.resources.client.ClientBundle;
67 import com.google.gwt.resources.client.ImageResource;
68 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
69 import com.google.gwt.safehtml.shared.SafeHtml;
70 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
71 import com.google.gwt.user.cellview.client.CellTable;
72 import com.google.gwt.user.cellview.client.Column;
73 import com.google.gwt.user.cellview.client.SimplePager;
74 import com.google.gwt.user.cellview.client.TextColumn;
75 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
76 import com.google.gwt.user.client.DOM;
77 import com.google.gwt.user.client.DeferredCommand;
78 import com.google.gwt.user.client.Event;
79 import com.google.gwt.user.client.Window;
80 import com.google.gwt.user.client.ui.AbstractImagePrototype;
81 import com.google.gwt.user.client.ui.Composite;
82 import com.google.gwt.user.client.ui.HTML;
83 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
84 import com.google.gwt.user.client.ui.HorizontalPanel;
85 import com.google.gwt.user.client.ui.VerticalPanel;
86 import com.google.gwt.view.client.ListDataProvider;
87 import com.google.gwt.view.client.MultiSelectionModel;
88 import com.google.gwt.view.client.ProvidesKey;
89 import com.google.gwt.view.client.SelectionChangeEvent;
90 import com.google.gwt.view.client.SelectionChangeEvent.Handler;
91
92 /**
93  * A composite that displays the list of files in a particular folder.
94  */
95 public class FileList extends Composite {
96         ListDataProvider<FileResource> provider = new ListDataProvider<FileResource>();
97         interface TableResources extends DragAndDropCellTable.Resources {
98             @Source({CellTable.Style.DEFAULT_CSS, "GssCellTable.css"})
99             TableStyle cellTableStyle();
100           }
101         
102         static interface Templates extends SafeHtmlTemplates {
103             Templates INSTANCE = GWT.create(Templates.class);
104
105             @Template("<div id='dragHelper' style='border:1px solid black; background-color:#ffffff; color:black; width:150px;z-index:100'></div>")
106             SafeHtml outerHelper();
107           }
108         
109         
110         /**
111            * The styles applied to the table.
112            */
113           interface TableStyle extends CellTable.Style {
114           }
115
116         private String showingStats = "";
117
118         private int startIndex = 0;
119
120         /**
121          * A constant that denotes the completion of an IncrementalCommand.
122          */
123         public static final boolean DONE = false;
124
125         
126         
127         private final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
128
129         /**
130          * Specifies that the images available for this composite will be the ones
131          * available in FileContextMenu.
132          */
133         public interface Images extends ClientBundle,FileContextMenu.Images, CellTreeView.Images {
134
135                 @Source("gr/ebs/gss/resources/blank.gif")
136                 ImageResource blank();
137
138                 @Source("gr/ebs/gss/resources/asc.png")
139                 ImageResource asc();
140
141                 @Source("gr/ebs/gss/resources/desc.png")
142                 ImageResource desc();
143
144                 @Source("gr/ebs/gss/resources/mimetypes/document_shared.png")
145                 ImageResource documentShared();
146
147                 @Source("gr/ebs/gss/resources/mimetypes/kcmfontinst.png")
148                 ImageResource wordprocessor();
149
150                 @Source("gr/ebs/gss/resources/mimetypes/log.png")
151                 ImageResource spreadsheet();
152
153                 @Source("gr/ebs/gss/resources/mimetypes/kpresenter_kpr.png")
154                 ImageResource presentation();
155
156                 @Source("gr/ebs/gss/resources/mimetypes/acroread.png")
157                 ImageResource pdf();
158
159                 @Source("gr/ebs/gss/resources/mimetypes/image.png")
160                 ImageResource image();
161
162                 @Source("gr/ebs/gss/resources/mimetypes/video2.png")
163                 ImageResource video();
164
165                 @Source("gr/ebs/gss/resources/mimetypes/knotify.png")
166                 ImageResource audio();
167
168                 @Source("gr/ebs/gss/resources/mimetypes/html.png")
169                 ImageResource html();
170
171                 @Source("gr/ebs/gss/resources/mimetypes/txt.png")
172                 ImageResource txt();
173
174                 @Source("gr/ebs/gss/resources/mimetypes/ark2.png")
175                 ImageResource zip();
176
177                 @Source("gr/ebs/gss/resources/mimetypes/kcmfontinst_shared.png")
178                 ImageResource wordprocessorShared();
179
180                 @Source("gr/ebs/gss/resources/mimetypes/log_shared.png")
181                 ImageResource spreadsheetShared();
182
183                 @Source("gr/ebs/gss/resources/mimetypes/kpresenter_kpr_shared.png")
184                 ImageResource presentationShared();
185
186                 @Source("gr/ebs/gss/resources/mimetypes/acroread_shared.png")
187                 ImageResource pdfShared();
188
189                 @Source("gr/ebs/gss/resources/mimetypes/image_shared.png")
190                 ImageResource imageShared();
191
192                 @Source("gr/ebs/gss/resources/mimetypes/video2_shared.png")
193                 ImageResource videoShared();
194
195                 @Source("gr/ebs/gss/resources/mimetypes/knotify_shared.png")
196                 ImageResource audioShared();
197
198                 @Source("gr/ebs/gss/resources/mimetypes/html_shared.png")
199                 ImageResource htmlShared();
200
201                 @Source("gr/ebs/gss/resources/mimetypes/txt_shared.png")
202                 ImageResource txtShared();
203
204                 @Source("gr/ebs/gss/resources/mimetypes/ark2_shared.png")
205                 ImageResource zipShared();
206
207         }
208         
209         DragStopEventHandler dragStop = new DragStopEventHandler() {
210                 
211                 @Override
212                 public void onDragStop(DragStopEvent event) {
213                         GWT.log("DRAG STOPPED");
214                         
215                 }
216         };
217         
218         private static class ContactCell extends AbstractCell<gr.ebs.gss.client.rest.resource.FileResource> {
219
220             /**
221              * The html of the image used for contacts.
222              * 
223              */
224             private final String imageHtml;
225
226             public ContactCell(ImageResource image) {
227               this.imageHtml = AbstractImagePrototype.create(image).getHTML();
228             }
229
230             
231
232                 
233
234             @Override
235             public void render(Context context, FileResource value, SafeHtmlBuilder sb) {
236               // Value can be null, so do a null check..
237               if (value == null) {
238                 return;
239               }
240
241               sb.appendHtmlConstant("<table>");
242
243               // Add the contact image.
244               sb.appendHtmlConstant("<tr><td rowspan='3'>");
245               sb.appendHtmlConstant(imageHtml);
246               sb.appendHtmlConstant("</td>");
247
248               // Add the name and address.
249               DisplayHelper.log("value.getName()");
250               sb.appendHtmlConstant("<td style='font-size:95%;' id='"+value.getName()+"'>");
251               sb.appendEscaped(value.getName());
252               sb.appendHtmlConstant("</td></tr><tr><td>");
253               sb.appendEscaped(value.getFileSizeAsString());
254               sb.appendHtmlConstant("</td></tr></table>");
255             }
256
257
258           }
259         /**
260          * Retrieve the celltable.
261          *
262          * @return the celltable
263          */
264         public DragAndDropCellTable<FileResource> getCelltable() {
265                 return celltable;
266         }
267         
268         
269         /**
270          * The number of files in this folder.
271          */
272         int folderFileCount;
273
274         /**
275          * Total folder size
276          */
277         long folderTotalSize;
278
279         /**
280          * A cache of the files in the list.
281          */
282         private List<FileResource> files;
283
284         /**
285          * The widget's image bundle.
286          */
287         private final Images images;
288         
289         private FileContextMenu menuShowing;
290         private DragAndDropCellTable<FileResource> celltable;
291         private final MultiSelectionModel<FileResource> selectionModel;
292         private final List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
293         SortableHeader nameHeader;
294         SimplePager pager;
295         SimplePager pagerTop;
296         /**
297          * Construct the file list widget. This entails setting up the widget
298          * layout, fetching the number of files in the current folder from the
299          * server and filling the local file cache of displayed files with data from
300          * the server, as well.
301          *
302          * @param _images
303          */
304         public FileList(Images _images) {
305                 images = _images;
306                 DragAndDropCellTable.Resources resources = GWT.create(TableResources.class);
307                 ProvidesKey<FileResource> keyProvider = new ProvidesKey<FileResource>(){
308
309                         @Override
310                         public Object getKey(FileResource item) {
311                                 return item.getUri();
312                         }
313                         
314                 };
315                 celltable = new DragAndDropCellTable<FileResource>(GSS.VISIBLE_FILE_COUNT,resources,keyProvider);
316                 
317                 DragAndDropColumn<FileResource, ImageResource> status = new DragAndDropColumn<FileResource, ImageResource>(new ImageResourceCell(){
318                         @Override
319                   public boolean handlesSelection() {
320                             return false;
321                           }
322                 }) {
323                   @Override
324                   public ImageResource getValue(FileResource entity) {
325                     return getFileIcon(entity);
326                   }
327                   
328                };
329             celltable.addColumn(status,"");
330             
331             initDragOperation(status);
332                 final DragAndDropColumn<FileResource,SafeHtml> nameColumn = new DragAndDropColumn<FileResource,SafeHtml>(new SafeHtmlCell()) {
333
334
335                         @Override
336                         public SafeHtml getValue(FileResource object) {
337                                 SafeHtmlBuilder sb = new SafeHtmlBuilder();
338                                 if (object.getContentType().endsWith("png") || object.getContentType().endsWith("gif") || object.getContentType().endsWith("jpeg") ){                                   
339                                         sb.appendHtmlConstant("<span id='fileList."+ object.getName() +"'>");
340                                         sb.appendEscaped(object.getName());
341                                         sb.appendHtmlConstant("</span>");
342                                         sb.appendHtmlConstant(" <a href='" +
343                                 GSS.get().getTopPanel().getFileMenu().getDownloadURL(object) +
344                                 "' title='" + object.getOwner() + " : " + object.getPath() + object.getName() +
345                                 "' rel='lytebox[mnf]' " +
346                                 "onclick='myLytebox.start(this, false, false); return false;'>" +
347                                 "(view)" + "</a>");
348                                         
349                                         
350                                 }
351                                 else{                                   
352                                         sb.appendHtmlConstant("<span id='fileList."+ object.getName() +"'>");
353                                         sb.appendEscaped(object.getName());
354                                         sb.appendHtmlConstant("</span>");
355                                 }
356                                 
357                                 return sb.toSafeHtml();
358                         }
359                         
360                 };
361                 initDragOperation(nameColumn);
362                 celltable.addColumn(nameColumn,nameHeader = new SortableHeader("Name"));
363                 allHeaders.add(nameHeader);
364                 //nameHeader.setSorted(true);
365                 //nameHeader.toggleReverseSort();
366                 nameHeader.setUpdater(new FileValueUpdater(nameHeader, "name"));
367                 celltable.redrawHeaders();
368                 
369                 
370             
371             
372             SortableHeader aheader;
373             DragAndDropColumn<FileResource,String> aColumn;
374                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
375                         @Override
376                         public String getValue(FileResource object) {
377                                 return GSS.get().findUserFullName(object.getOwner());
378                         }                       
379                 },aheader = new SortableHeader("Owner"));
380                 initDragOperation(aColumn);
381                 allHeaders.add(aheader);
382                 aheader.setUpdater(new FileValueUpdater(aheader, "owner"));
383                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
384                         @Override
385                         public String getValue(FileResource object) {
386                                 // TODO Auto-generated method stub
387                                 return object.getPath();
388                         }                       
389                 },aheader = new SortableHeader("Path"));
390                 initDragOperation(aColumn);
391                 allHeaders.add(aheader);
392                 
393                 aheader.setUpdater(new FileValueUpdater(aheader, "path"));      
394                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
395                         @Override
396                         public String getValue(FileResource object) {
397                                 return object.getVersion().toString();
398                         }                       
399                 },aheader = new SortableHeader("Version"));
400                 initDragOperation(aColumn);
401                 allHeaders.add(aheader);
402                 aheader.setUpdater(new FileValueUpdater(aheader, "version"));
403                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
404                         @Override
405                         public String getValue(FileResource object) {
406                                 // TODO Auto-generated method stub
407                                 return object.getFileSizeAsString();
408                         }                       
409                 },aheader = new SortableHeader("Size"));
410                 initDragOperation(aColumn);
411                 allHeaders.add(aheader);
412                 aheader.setUpdater(new FileValueUpdater(aheader, "size"));      
413                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
414                         @Override
415                         public String getValue(FileResource object) {
416                                 return formatter.format(object.getModificationDate());
417                         }                       
418                 },aheader = new SortableHeader("Last Modified"));
419                 allHeaders.add(aheader);
420                 aheader.setUpdater(new FileValueUpdater(aheader, "date"));
421                
422                 
423                 provider.addDataDisplay(celltable);
424                 celltable.addDragStopHandler(dragStop);
425                 celltable.addDragStartHandler(new DragStartEventHandler() {
426
427                       public void onDragStart(DragStartEvent event) {
428                         FileResource value = event.getDraggableData();
429                         
430                         com.google.gwt.dom.client.Element helper = event.getHelper();
431                         SafeHtmlBuilder sb = new SafeHtmlBuilder();
432                         sb.appendHtmlConstant("<b>");
433                         DisplayHelper.log(value.getName());
434                         if(getSelectedFiles().size()==1)
435                                 sb.appendEscaped(value.getName());
436                         else
437                                 sb.appendEscaped(getSelectedFiles().size()+" files");
438                         sb.appendHtmlConstant("</b>");
439                         helper.setInnerHTML(sb.toSafeHtml().asString());
440
441                       }
442                     });
443                 
444                 
445                 
446                 
447                 
448                 
449                 VerticalPanel vp = new VerticalPanel();
450                 vp.setWidth("100%");
451                 pagerTop = new SimplePager(SimplePager.TextLocation.CENTER);
452                 pagerTop.setDisplay(celltable);
453                 vp.add(pagerTop);
454                 celltable.setWidth("100%");
455                 vp.add(celltable);
456                 pager = new SimplePager(SimplePager.TextLocation.CENTER);
457                 pager.setDisplay(celltable);
458                 
459                 vp.add(pager);
460                 vp.setCellWidth(celltable, "100%");
461                 
462                 initWidget(vp);
463                 pager.setVisible(false);
464                 pagerTop.setVisible(false);
465
466                 celltable.setStyleName("gss-List");
467                 selectionModel = new MultiSelectionModel<FileResource>();
468                 
469
470                  Handler selectionHandler = new SelectionChangeEvent.Handler() { 
471              @Override 
472              public void onSelectionChange(com.google.gwt.view.client.SelectionChangeEvent event) {
473                  if(getSelectedFiles().size()==1)
474                          GSS.get().setCurrentSelection(getSelectedFiles().get(0));
475                  else
476                          GSS.get().setCurrentSelection(getSelectedFiles());
477              }
478          };
479          selectionModel.addSelectionChangeHandler(selectionHandler);
480          
481                 celltable.setSelectionModel(selectionModel,GSSSelectionEventManager.<FileResource>createDefaultManager());
482                 celltable.setPageSize(GSS.VISIBLE_FILE_COUNT);
483                 celltable.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
484                 Scheduler.get().scheduleIncremental(new RepeatingCommand() {
485
486                         @Override
487                         public boolean execute() {
488                                 return fetchRootFolder();
489                         }
490                 });
491                 sinkEvents(Event.ONCONTEXTMENU);
492                 sinkEvents(Event.ONMOUSEUP);
493                 sinkEvents(Event.ONMOUSEDOWN);
494                 sinkEvents(Event.ONCLICK);
495                 sinkEvents(Event.ONKEYDOWN);
496                 sinkEvents(Event.ONDBLCLICK);
497                 GSS.preventIESelection();
498         }
499         
500         //public native void fireClickEvent(Element element) /*-{
501           //  var evObj = $doc.createEvent('MouseEvents');
502             //evObj.initEvent('click', true, true);
503             //element.dispatchEvent(evObj);
504         //}-*/;
505         
506         
507         
508          public List<FileResource> getSelectedFiles() {
509          return new ArrayList<FileResource>(selectionModel.getSelectedSet());
510          }
511         
512          private void initDragOperation(DragAndDropColumn<?, ?> column) {
513
514                     // retrieve draggableOptions on the column
515                     DraggableOptions draggableOptions = column.getDraggableOptions();
516                     // use template to construct the helper. The content of the div will be set
517                     // after
518                     draggableOptions.setHelper($(Templates.INSTANCE.outerHelper().asString()));
519                     //draggableOptions.setZIndex(100);
520                     // opacity of the helper
521                     draggableOptions.setAppendTo("body"); 
522                     //draggableOptions.setOpacity((float) 0.8);
523                     draggableOptions.setContainment("document");
524                     // cursor to use during the drag operation
525                     draggableOptions.setCursor(Cursor.MOVE);
526                     // set the revert option
527                     draggableOptions.setRevert(RevertOption.ON_INVALID_DROP);
528                     // prevents dragging when user click on the category drop-down list
529                     draggableOptions.setCancel("select");
530                     
531                     
532                     draggableOptions.setOnBeforeDragStart(new DragFunction() {
533                                 
534                                 @Override
535                                 public void f(DragContext context) {
536                                          FileResource value = context.getDraggableData();
537                                      if(!selectionModel.isSelected(value)){
538                                         throw new StopDragException();
539                                       }
540                                         
541                                 }
542                         });
543                   }
544         
545          public void showContextMenu(Event event){
546                  menuShowing = new FileContextMenu(images, false, true);
547                         menuShowing=menuShowing.onEmptyEvent(event);
548          }
549         @Override
550         public void onBrowserEvent(Event event) {
551                 
552                 if (files == null || files.size() == 0) {
553                         if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && getSelectedFiles().size() == 0) {
554                                 menuShowing = new FileContextMenu(images, false, true);
555                                 menuShowing=menuShowing.onEmptyEvent(event);
556                                 event.preventDefault();
557                                 event.cancelBubble(true);
558                         }
559                         return;
560                 }
561                 if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && getSelectedFiles().size() != 0) {
562                         GWT.log("*****GOING TO SHOW CONTEXT MENU ****", null);
563                         menuShowing =  new FileContextMenu(images, false, false);
564                         menuShowing=menuShowing.onEvent(event);
565                         event.cancelBubble(true);
566                         event.preventDefault();
567                 } else if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && getSelectedFiles().size() == 0) {
568                         menuShowing = new FileContextMenu(images, false, true);
569                         menuShowing=menuShowing.onEmptyEvent(event);
570                         event.cancelBubble(true);
571                         event.preventDefault();
572                 } else if (DOM.eventGetType(event) == Event.ONDBLCLICK)
573                         if (getSelectedFiles().size() == 1) {
574                                 GSS app = GSS.get();
575                                 FileResource file = getSelectedFiles().get(0);
576                                 String dateString = RestCommand.getDate();
577                                 String resource = file.getUri().substring(app.getApiPath().length() - 1, file.getUri().length());
578                                 String sig = app.getCurrentUserResource().getUsername() + " " +
579                                                 RestCommand.calculateSig("GET", dateString, resource,
580                                                 RestCommand.base64decode(app.getToken()));
581                                 Window.open(file.getUri() + "?Authorization=" + URL.encodeComponent(sig) + "&Date=" + URL.encodeComponent(dateString), "_blank", "");
582                                 event.preventDefault();
583                                 return;
584                         }
585                 super.onBrowserEvent(event);
586         }
587
588         /**
589          * Retrieve the root folder for the current user.
590          *
591          * @return true if the retrieval was successful
592          */
593         protected boolean fetchRootFolder() {
594                 UserResource user = GSS.get().getCurrentUserResource();
595                 if (user == null)
596                         return !DONE;
597                 // Update cache and clear selection.
598                 updateFileCache(true);
599                 return DONE;
600         }
601
602
603         /**
604          * Update the display of the file list.
605          */
606         void update(boolean sort) {
607                 int count = folderFileCount;
608                 int max = startIndex + GSS.VISIBLE_FILE_COUNT;
609                 if (max > count)
610                         max = count;
611                 folderTotalSize = 0;
612                 
613                 copyListAndContinue(files);
614                 for(FileResource f : files){
615                         folderTotalSize += f.getContentLength();
616                 }
617                 if (folderFileCount == 0) {
618                         showingStats = "no files";
619                 } else if (folderFileCount < GSS.VISIBLE_FILE_COUNT) {
620                         if (folderFileCount == 1)
621                                 showingStats = "1 file";
622                         else
623                                 showingStats = folderFileCount + " files";
624                         showingStats += " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
625                 } else {
626                         showingStats = "" + (startIndex + 1) + " - " + max + " of " + count + " files" + " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
627                 }
628                 showCellTable();
629                 updateCurrentlyShowingStats();
630
631         }
632
633         /**
634          * Return the proper icon based on the MIME type of the file.
635          *
636          * @param file
637          * @return the icon
638          */
639         private ImageResource getFileIcon(FileResource file) {
640                 String mimetype = file.getContentType();
641                 boolean shared = false;
642                 if(GSS.get().getTreeView().getSelection()!=null && (GSS.get().getTreeView().getSelection() instanceof OtherUserResource || GSS.get().getTreeView().getSelection() instanceof OthersFolderResource)){
643                         OtherUserResource otherUser = null;
644                         if(GSS.get().getTreeView().getSelection() instanceof OtherUserResource)
645                                 otherUser = (OtherUserResource) GSS.get().getTreeView().getSelection();
646                         else if (GSS.get().getTreeView().getSelection() instanceof OthersFolderResource){
647                                 otherUser = GSS.get().getTreeView().getOtherUserResourceOfOtherFolder((OthersFolderResource) GSS.get().getTreeView().getSelection());
648                         }
649                         if(otherUser ==null)
650                                 shared=false;
651                         else{
652                                 String uname = otherUser.getUsername();
653                                 if(uname==null)
654                                         uname = GSS.get().getTreeView().getOthers().getUsernameOfUri(otherUser.getUri());
655                                 if(uname != null)
656                                         shared = file.isShared();
657                         }
658                 }
659                 else
660                         shared = file.isShared();
661                 if (mimetype == null)
662                         return shared ? images.documentShared() : images.document();
663                 mimetype = mimetype.toLowerCase();
664                 if (mimetype.startsWith("application/pdf"))
665                         return shared ? images.pdfShared() : images.pdf();
666                 else if (mimetype.endsWith("excel"))
667                         return shared ? images.spreadsheetShared() : images.spreadsheet();
668                 else if (mimetype.endsWith("msword"))
669                         return shared ? images.wordprocessorShared() : images.wordprocessor();
670                 else if (mimetype.endsWith("powerpoint"))
671                         return shared ? images.presentationShared() : images.presentation();
672                 else if (mimetype.startsWith("application/zip") ||
673                                         mimetype.startsWith("application/gzip") ||
674                                         mimetype.startsWith("application/x-gzip") ||
675                                         mimetype.startsWith("application/x-tar") ||
676                                         mimetype.startsWith("application/x-gtar"))
677                         return shared ? images.zipShared() : images.zip();
678                 else if (mimetype.startsWith("text/html"))
679                         return shared ? images.htmlShared() : images.html();
680                 else if (mimetype.startsWith("text/plain"))
681                         return shared ? images.txtShared() : images.txt();
682                 else if (mimetype.startsWith("image/"))
683                         return shared ? images.imageShared() : images.image();
684                 else if (mimetype.startsWith("video/"))
685                         return shared ? images.videoShared() : images.video();
686                 else if (mimetype.startsWith("audio/"))
687                         return shared ? images.audioShared() : images.audio();
688                 return shared ? images.documentShared() : images.document();
689         }
690
691         /**
692          * Update status panel with currently showing file stats.
693          */
694         public void updateCurrentlyShowingStats() {
695                 GSS.get().getStatusPanel().updateCurrentlyShowing(showingStats);
696         }
697         
698         public void updateFileCache(boolean clearSelection){
699                 if(clearSelection)
700                         clearSelectedRows();
701                 final RestResource folderItem = GSS.get().getTreeView().getSelection();
702                 // Validation.
703                 if (folderItem == null || folderItem.equals(GSS.get().getTreeView().getOthers())) {
704                         setFiles(new ArrayList<FileResource>());
705                         update(true);
706                         return;
707                 }
708                 else if (folderItem instanceof RestResourceWrapper) {
709                         setFiles(((RestResourceWrapper) folderItem).getResource().getFiles());
710                         update(true);
711                 }
712                 else if (folderItem instanceof SharedResource) {
713                         setFiles(((SharedResource) folderItem).getFiles());
714                         update(true);
715                 }
716                 else if (folderItem instanceof OtherUserResource) {
717                         setFiles(((OtherUserResource) folderItem).getFiles());
718                         update(true);
719                 }
720                 else if (folderItem instanceof TrashResource) {
721                         setFiles(((TrashResource) folderItem).getFiles());
722                         update(true);
723                 }
724         }
725         
726
727         /**
728          * Fill the file cache with data.
729          */
730         public void setFiles(final List<FileResource> _files) {
731                 if (_files.size() > 0 && ! (GSS.get().getTreeView().getSelection() instanceof TrashResource)) {
732                         files = new ArrayList<FileResource>();
733                         for (FileResource fres : _files)
734                                 if (!fres.isDeleted())
735                                         files.add(fres);
736                 }
737                 else
738                         files = _files;
739                 Collections.sort(files, new Comparator<FileResource>() {
740
741                         @Override
742                         public int compare(FileResource arg0, FileResource arg1) {
743                                 return arg0.getName().compareTo(arg1.getName());
744                         }
745
746                 });
747                 folderFileCount = files.size();
748                 
749                 nameHeader.setSorted(true);
750                 nameHeader.toggleReverseSort();
751                 for (SortableHeader otherHeader : allHeaders) {
752                   if (otherHeader != nameHeader) {
753                     otherHeader.setSorted(false);
754                     otherHeader.setReverseSort(true);
755                   }
756                 }
757                 //
758         }
759
760         
761
762         
763         /**
764          * Does the list contains the requested filename
765          *
766          * @param fileName
767          * @return true/false
768          */
769         public boolean contains(String fileName) {
770                 for (int i = 0; i < files.size(); i++)
771                         if (files.get(i).getName().equals(fileName))
772                                 return true;
773                 return false;
774         }
775
776         public void clearSelectedRows() {
777                 Iterator<FileResource> it = selectionModel.getSelectedSet().iterator();
778                 while(it.hasNext()){
779                         selectionModel.setSelected(it.next(),false);
780                 }
781         }
782
783         /**
784          *
785          */
786         public void selectAllRows() {
787                 Iterator<FileResource> it = provider.getList().iterator();
788                 while(it.hasNext()){
789                         selectionModel.setSelected(it.next(),true);
790                 }
791
792
793         }
794
795         
796         private void sortFiles(final String sortingProperty, final boolean sortingType){
797                 Collections.sort(files, new Comparator<FileResource>() {
798
799             @Override
800             public int compare(FileResource arg0, FileResource arg1) {
801                     AbstractImagePrototype descPrototype = AbstractImagePrototype.create(images.desc());
802                     AbstractImagePrototype ascPrototype = AbstractImagePrototype.create(images.asc());
803                     if (sortingType){
804                             if (sortingProperty.equals("version")) {
805                                     return arg0.getVersion().compareTo(arg1.getVersion());
806                             } else if (sortingProperty.equals("owner")) {
807                                     return arg0.getOwner().compareTo(arg1.getOwner());
808                             } else if (sortingProperty.equals("date")) {
809                                     return arg0.getModificationDate().compareTo(arg1.getModificationDate());
810                             } else if (sortingProperty.equals("size")) {
811                                     return arg0.getContentLength().compareTo(arg1.getContentLength());
812                             } else if (sortingProperty.equals("name")) {
813                                     return arg0.getName().compareTo(arg1.getName());
814                             } else if (sortingProperty.equals("path")) {
815                                     return arg0.getUri().compareTo(arg1.getUri());
816                             } else {
817                                     return arg0.getName().compareTo(arg1.getName());
818                             }
819                     }
820                     else if (sortingProperty.equals("version")) {
821                             
822                             return arg1.getVersion().compareTo(arg0.getVersion());
823                     } else if (sortingProperty.equals("owner")) {
824                             
825                             return arg1.getOwner().compareTo(arg0.getOwner());
826                     } else if (sortingProperty.equals("date")) {
827                             
828                             return arg1.getModificationDate().compareTo(arg0.getModificationDate());
829                     } else if (sortingProperty.equals("size")) {
830                             
831                             return arg1.getContentLength().compareTo(arg0.getContentLength());
832                     } else if (sortingProperty.equals("name")) {
833                             
834                             return arg1.getName().compareTo(arg0.getName());
835                     } else if (sortingProperty.equals("path")) {
836                             
837                             return arg1.getUri().compareTo(arg0.getUri());
838                     } else {
839                             
840                             return arg1.getName().compareTo(arg0.getName());
841                     }
842             }
843
844                 });
845         }
846         
847         final class FileValueUpdater implements ValueUpdater<String>{
848                 private String property;
849                 private SortableHeader header;
850                 /**
851                  * 
852                  */
853                 public FileValueUpdater(SortableHeader header,String property) {
854                         this.property=property;
855                         this.header=header;
856                 }
857                 @Override
858                 public void update(String value) {
859                         header.setSorted(true);
860                         header.toggleReverseSort();
861
862                 for (SortableHeader otherHeader : allHeaders) {
863                   if (otherHeader != header) {
864                     otherHeader.setSorted(false);
865                     otherHeader.setReverseSort(true);
866                   }
867                 }
868                 celltable.redrawHeaders();
869                 sortFiles(property, header.getReverseSort());
870                 FileList.this.update(true);                     
871                 }
872                 
873         }
874         /**
875          * Creates a new ArrayList<FileResources> from the given files ArrayList 
876          * in order that the input files remain untouched 
877          * and continues to find user's full names of each FileResource element
878          * in the new ArrayList
879          *    
880          * @param filesInput
881          */
882         private void copyListAndContinue(List<FileResource> filesInput){
883                 List<FileResource> copiedFiles = new ArrayList<FileResource>();         
884                 for(FileResource file : filesInput) {
885                         copiedFiles.add(file);
886                 }
887                 handleFullNames(copiedFiles);
888         }
889         
890         /**
891          * Examines whether or not the user's full name exists in the 
892          * userFullNameMap in the GSS.java for every element of the input list.
893          * If the user's full name does not exist in the map then a command is being made.  
894          * 
895          * @param filesInput
896          */
897         private void handleFullNames(List<FileResource> filesInput){            
898                 if(filesInput.size() == 0){
899                         showCellTable();
900                         return;
901                 }               
902
903                 if(GSS.get().findUserFullName(filesInput.get(0).getOwner()) == null){
904                         findFullNameAndUpdate(filesInput);              
905                         return;
906                 }
907                                 
908                 if(filesInput.size() >= 1){
909                         filesInput.remove(filesInput.get(0));
910                         if(filesInput.isEmpty()){
911                                 showCellTable();                                
912                         }else{
913                                 handleFullNames(filesInput);
914                         }
915                 }               
916         }
917         
918         /**
919          * Makes a command to search for full name from a given username. 
920          * Only after the completion of the command the celltable is shown
921          * or the search for the next full name continues.
922          *  
923          * @param filesInput
924          */
925         private void findFullNameAndUpdate(final List<FileResource> filesInput){                
926                 String aUserName = filesInput.get(0).getOwner();
927                 String path = GSS.get().getApiPath() + "users/" + aUserName; 
928
929                 GetCommand<UserSearchResource> gg = new GetCommand<UserSearchResource>(UserSearchResource.class, path, false,null) {
930                         @Override
931                         public void onComplete() {
932                                 final UserSearchResource result = getResult();
933                                 for (UserResource user : result.getUsers()){
934                                         String username = user.getUsername();
935                                         String userFullName = user.getName();
936                                         GSS.get().putUserToMap(username, userFullName);
937                                         if(filesInput.size() >= 1){
938                                                 filesInput.remove(filesInput.get(0));
939                                                 if(filesInput.isEmpty()){
940                                                         showCellTable();
941                                                 }else{
942                                                         handleFullNames(filesInput);
943                                                 }                                                                                               
944                                         }                                                                       
945                                 }
946                         }
947                         @Override
948                         public void onError(Throwable t) {
949                                 GWT.log("", t);
950                                 GSS.get().displayError("Unable to fetch user's full name from the given username " + filesInput.get(0).getOwner());
951                                 if(filesInput.size() >= 1){
952                                         filesInput.remove(filesInput.get(0));
953                                         handleFullNames(filesInput);                                    
954                                 }
955                         }
956                 };
957                 DeferredCommand.addCommand(gg);
958         
959         }
960         /**
961          * Shows the files in the cellTable 
962          */
963
964         private void showCellTable(){
965                 if(files.size()>=GSS.VISIBLE_FILE_COUNT){
966                         pager.setVisible(true);
967                         pagerTop.setVisible(true);
968                 }
969                 else{
970                         pagerTop.setVisible(false);
971                         pager.setVisible(false);
972                 }
973                 provider.setList(files);
974                 provider.refresh();
975                 //celltable.redraw();
976                 celltable.redrawHeaders();              
977         }
978
979         
980 }