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