Merge branch 'master' into packaging
[pithos-web-client] / src / gr / grnet / pithos / web / client / FileList.java
index e9db15b..bcd0cd2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 GRNET S.A. All rights reserved.
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or
  * without modification, are permitted provided that the following
 
 package gr.grnet.pithos.web.client;
 
-import com.google.gwt.event.dom.client.ContextMenuEvent;
-import com.google.gwt.event.dom.client.ContextMenuHandler;
-
-import com.google.gwt.user.cellview.client.Column;
-import gr.grnet.pithos.web.client.commands.UploadFileCommand;
 import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
 import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
@@ -49,34 +44,37 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
+import com.google.gwt.cell.client.Cell.Context;
 import com.google.gwt.cell.client.ImageResourceCell;
 import com.google.gwt.cell.client.SafeHtmlCell;
 import com.google.gwt.cell.client.TextCell;
 import com.google.gwt.cell.client.ValueUpdater;
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style.Cursor;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ContextMenuEvent;
+import com.google.gwt.event.dom.client.ContextMenuHandler;
+import com.google.gwt.http.client.URL;
 import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.resources.client.ClientBundle;
 import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.resources.client.ClientBundle.Source;
+import com.google.gwt.resources.client.ImageResource.ImageOptions;
+import com.google.gwt.resources.client.ImageResource.RepeatStyle;
 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
 import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
 import com.google.gwt.user.cellview.client.CellTable;
-import com.google.gwt.user.cellview.client.GssSimplePager;
+import com.google.gwt.user.cellview.client.Column;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.view.client.ListDataProvider;
 import com.google.gwt.view.client.MultiSelectionModel;
 import com.google.gwt.view.client.ProvidesKey;
 import com.google.gwt.view.client.SelectionChangeEvent;
-import com.google.gwt.view.client.SelectionChangeEvent.Handler;
 
 /**
  * A composite that displays the list of files in a particular folder.
@@ -89,11 +87,17 @@ public class FileList extends Composite {
        * The styles applied to the table.
        */
     interface TableStyle extends CellTable.Style {
+       String cellTableFirstColumnShared();
     }
 
        interface TableResources extends CellTable.Resources {
-           @Source({CellTable.Style.DEFAULT_CSS, "GssCellTable.css"})
+           @Override
+               @Source({CellTable.Style.DEFAULT_CSS, "PithosCellTable.css"})
            TableStyle cellTableStyle();
+           
+           @Source("share.png")
+           @ImageOptions(repeatStyle = RepeatStyle.None)
+           ImageResource cellTableSharedIcon();
        }
        
        static interface Templates extends SafeHtmlTemplates {
@@ -115,22 +119,13 @@ public class FileList extends Composite {
         public SafeHtml spanWithIdAndClass(String id, String cssClass, String content);
        }
 
-    private String showingStats = "";
-
-       private int startIndex = 0;
-
-       /**
-        * A constant that denotes the completion of an IncrementalCommand.
-        */
-       public static final boolean DONE = false;
-
-       private final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
+       protected final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
 
        /**
         * Specifies that the images available for this composite will be the ones
         * available in FileContextMenu.
         */
-       public interface Images extends ClientBundle,FileContextMenu.Images, FolderTreeView.Images {
+       public interface Images extends FolderTreeView.Images {
 
                @Source("gr/grnet/pithos/resources/blank.gif")
                ImageResource blank();
@@ -224,27 +219,21 @@ public class FileList extends Composite {
        /**
         * The widget's image bundle.
         */
-       private final Images images;
+       protected final Images images;
        
-       private CellTable<File> celltable;
+       protected CellTable<File> celltable;
 
        private final MultiSelectionModel<File> selectionModel;
 
-       private final List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
-
-       SortableHeader nameHeader;
-
-       GssSimplePager pagerBottom;
+       Column<File, String> pathColumn;
 
-       GssSimplePager pagerTop;
+       protected final List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
 
-       Button uploadButtonBottom;
-
-       Button uploadButtonTop;
+       SortableHeader nameHeader;
 
-    FolderTreeView treeView;
+       SortableHeader pathHeader;
 
-    private Pithos app;
+    protected Pithos app;
 
     /**
         * Construct the file list widget. This entails setting up the widget
@@ -254,12 +243,11 @@ public class FileList extends Composite {
         *
         * @param _images
         */
-       public FileList(final Pithos _app, Images _images, FolderTreeView _treeView) {
+       public FileList(final Pithos _app, Images _images) {
         app = _app;
                images = _images;
-        this.treeView = _treeView;
 
-        CellTable.Resources resources = GWT.create(TableResources.class);
+        final CellTable.Resources resources = GWT.create(TableResources.class);
 
         ProvidesKey<File> keyProvider = new ProvidesKey<File>(){
 
@@ -269,7 +257,7 @@ public class FileList extends Composite {
                        }
                };
 
-               celltable = new CellTable<File>(Pithos.VISIBLE_FILE_COUNT, resources, keyProvider);
+               celltable = new CellTable<File>(10, resources, keyProvider);
         celltable.setWidth("100%");
         celltable.setStyleName("pithos-List");
 
@@ -284,6 +272,13 @@ public class FileList extends Composite {
                 public ImageResource getValue(File entity) {
                     return getFileIcon(entity);
                 }
+
+                       @Override
+                       public String getCellStyleNames(Context context, File object) {
+                               if (!object.getPermissions().isEmpty() && !object.isPublished())
+                                       return ((TableStyle) resources.cellTableStyle()).cellTableFirstColumnShared();
+                               return super.getCellStyleNames(context, object);
+                       }
            };
            celltable.addColumn(status,"");
 
@@ -292,155 +287,128 @@ public class FileList extends Composite {
                        @Override
                        public SafeHtml getValue(File object) {
                                SafeHtmlBuilder sb = new SafeHtmlBuilder();
-                sb.append(Templates.INSTANCE.filenameSpan(object.getName()));
-                               if (object.getContentType().endsWith("png") || object.getContentType().endsWith("gif") || object.getContentType().endsWith("jpeg")) {
+                               sb.append(Templates.INSTANCE.filenameSpan(object.getName()));
+                               if (object.getContentType() != null && (object.getContentType().endsWith("png") || object.getContentType().endsWith("gif") || object.getContentType().endsWith("jpeg"))) {
                                sb.appendHtmlConstant("&nbsp;")
-                      .append(Templates.INSTANCE.viewLink(object.getUri(), object.getOwner() + " : " + object.getPath() + object.getName()));
+                      .append(Templates.INSTANCE.viewLink(app.getApiPath() + object.getOwner() + object.getUri(), object.getName()));
                                }
                                
                                return sb.toSafeHtml();
                        }
                        
                };
-        celltable.addColumn(nameColumn, nameHeader = new SortableHeader("Name"));
+        celltable.addColumn(nameColumn, nameHeader = new SortableHeader("Name", "name"));
                allHeaders.add(nameHeader);
-               nameHeader.setUpdater(new FileValueUpdater(nameHeader, "name"));
+               nameHeader.setUpdater(new FileValueUpdater(nameHeader));
+               nameHeader.setSorted(true);
+               nameHeader.setReverseSort(true);
 
                celltable.redrawHeaders();
                
-           Column<File,String> aColumn = new Column<File, String>(new TextCell()) {
-                       @Override
-                       public String getValue(File object) {
-                               return object.getOwner();
-                       }
-               };
-        SortableHeader aheader = new SortableHeader("Owner");
-               celltable.addColumn(aColumn, aheader);
-               allHeaders.add(aheader);
-        aheader.setUpdater(new FileValueUpdater(aheader, "owner"));
+               pathColumn = new Column<File, String>(new TextCell()) {
 
-        aColumn = new Column<File,String>(new TextCell()) {
                        @Override
-                       public String getValue(File object) {
-                               return object.getPath();
-                       }
-               };
-        aheader = new SortableHeader("Path");
-               celltable.addColumn(aColumn, aheader);
-               allHeaders.add(aheader);
-               aheader.setUpdater(new FileValueUpdater(aheader, "path"));
-
-        aColumn = new Column<File,String>(new TextCell()) {
-                       @Override
-                       public String getValue(File object) {
-                       return String.valueOf(object.getVersion());
+                       public String getValue(File f) {
+                               String path;
+                               if (!app.getSelectedTree().equals(app.mysharedTreeView)) {
+                                       path = f.getParent().getPrefix();
+                                       if (path.length() == 0)
+                                               path = "/";
+                               }
+                               else {
+                                       path = f.getPath();
+                                       if (path.lastIndexOf("/") != -1)
+                                               path = path.substring(0, path.lastIndexOf("/"));
+                                       else
+                                               path = "/";
+                               }
+                               return path;
                        }
                };
-        aheader = new SortableHeader("Version");
-               celltable.addColumn(aColumn, aheader);
-               allHeaders.add(aheader);
-               aheader.setUpdater(new FileValueUpdater(aheader, "version"));
-
-        aColumn = new Column<File,String>(new TextCell()) {
+               pathHeader = new SortableHeader("Path", "path");
+               celltable.addColumn(pathColumn, pathHeader);
+               allHeaders.add(pathHeader);
+               pathHeader.setUpdater(new FileValueUpdater(pathHeader));
+               
+        Column<File,String> aColumn = new Column<File,String>(new TextCell()) {
                        @Override
                        public String getValue(File object) {
-                               // TODO Auto-generated method stub
                                return object.getSizeAsString();
                        }
                };
-        aheader = new SortableHeader("Size");
+        SortableHeader aheader = new SortableHeader("Size", "size");
         celltable.addColumn(aColumn, aheader);
                allHeaders.add(aheader);
-               aheader.setUpdater(new FileValueUpdater(aheader, "size"));
+               aheader.setUpdater(new FileValueUpdater(aheader));
 
         aColumn = new Column<File,String>(new TextCell()) {
                        @Override
                        public String getValue(File object) {
-                               return formatter.format(object.getLastModified());
+                               return object.getLastModified() != null ? formatter.format(object.getLastModified()) : "";
                        }
                };
-        aheader = new SortableHeader("Last Modified");
+        aheader = new SortableHeader("Last Modified", "date");
                celltable.addColumn(aColumn, aheader);
                allHeaders.add(aheader);
-               aheader.setUpdater(new FileValueUpdater(aheader, "date"));
+               aheader.setUpdater(new FileValueUpdater(aheader));
               
                provider.addDataDisplay(celltable);
 
                VerticalPanel vp = new VerticalPanel();
                vp.setWidth("100%");
-
-               pagerTop = new GssSimplePager(GssSimplePager.TextLocation.CENTER);
-        pagerTop.setVisible(false);
-               pagerTop.setDisplay(celltable);
-               uploadButtonTop = new Button("<span id='topMenu.file.upload'>" + AbstractImagePrototype.create(images.fileUpdate()).getHTML() + "&nbsp;Upload</span>");
-               uploadButtonTop.addClickHandler(new ClickHandler() {
-                       
-                       @Override
-                       public void onClick(ClickEvent event) {
-                               new UploadFileCommand(app, null, treeView.getSelection()).execute();
-                       }
-               });
-               HorizontalPanel topPanel = new HorizontalPanel();
-               topPanel.add(pagerTop);
-               topPanel.add(uploadButtonTop);
-               vp.add(topPanel);
+               vp.addStyleName("pithos-FileListContainer");
 
         vp.add(celltable);
 
-               pagerBottom = new GssSimplePager(GssSimplePager.TextLocation.CENTER);
-        pagerBottom.setVisible(false);
-               pagerBottom.setDisplay(celltable);
-               uploadButtonBottom=new Button("<span id='topMenu.file.upload'>" + AbstractImagePrototype.create(images.fileUpdate()).getHTML() + "&nbsp;Upload</span>");
-               uploadButtonBottom.addClickHandler(new ClickHandler() {
-                       
-                       @Override
-                       public void onClick(ClickEvent event) {
-                               new UploadFileCommand(app, null, treeView.getSelection()).execute();
-                       }
-               });
-        HorizontalPanel bottomPanel = new HorizontalPanel();
-        bottomPanel.add(pagerBottom);
-               bottomPanel.add(uploadButtonBottom);
-
-               vp.add(bottomPanel);
                vp.setCellWidth(celltable, "100%");
         vp.addHandler(new ContextMenuHandler() {
             @Override
-            public void onContextMenu(ContextMenuEvent event) {
-                Folder selectedFolder = treeView.getSelection();
-                if (!selectedFolder.isTrash()) {
-                    FileContextMenu contextMenu = new FileContextMenu(app, images, selectedFolder, getSelectedFiles(), false);
-                    int x = event.getNativeEvent().getClientX();
-                    int y = event.getNativeEvent().getClientY();
-                    contextMenu.setPopupPosition(x, y);
-                    contextMenu.show();
-                }
+            public void onContextMenu(final ContextMenuEvent event) {
+               final TreeView tree = app.getSelectedTree();
+               if (tree != null) {
+                       final int x = event.getNativeEvent().getClientX();
+                       final int y = event.getNativeEvent().getClientY();
+                       final Folder selectedFolder = app.getSelection();
+                       app.scheduleFolderHeadCommand(selectedFolder, new Command() {
+                                               
+                                               @Override
+                                               public void execute() {
+                                                       final List<File> selectedFiles = getSelectedFiles();
+                                                       Iterator<File> iter = selectedFiles.iterator();
+                                                       iterateFilesHeadCommand(iter, new Command() {
+                                                               
+                                                               @Override
+                                                               public void execute() {
+                                                       FileContextMenu contextMenu = new FileContextMenu(app, images, tree, selectedFolder, selectedFiles);
+                                                       contextMenu.setPopupPosition(x, y);
+                                                       contextMenu.show();
+                                                               }
+                                                       });
+                                               }
+                                       });
+               }
             }
         }, ContextMenuEvent.getType());
                initWidget(vp);
 
                selectionModel = new MultiSelectionModel<File>(keyProvider);
-
-                Handler selectionHandler = new SelectionChangeEvent.Handler() {
-             @Override 
-             public void onSelectionChange(SelectionChangeEvent event) {
-                if(getSelectedFiles().size() == 1)
-                        app.setCurrentSelection(getSelectedFiles().get(0));
-                else
-                        app.setCurrentSelection(getSelectedFiles());
-             }
-         };
-         selectionModel.addSelectionChangeHandler(selectionHandler);
-         
-               celltable.setSelectionModel(selectionModel, GSSSelectionEventManager.<File> createDefaultManager());
-               celltable.setPageSize(Pithos.VISIBLE_FILE_COUNT);
+               selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
+                       
+                       @Override
+                       public void onSelectionChange(SelectionChangeEvent event) {
+                               app.showRelevantToolbarButtons();
+                       }
+               });
+               
+               celltable.setSelectionModel(selectionModel, PithosSelectionEventManager.<File> createDefaultManager());
+//             celltable.setPageSize(Pithos.VISIBLE_FILE_COUNT);
                
                sinkEvents(Event.ONCONTEXTMENU);
 //             sinkEvents(Event.ONMOUSEUP);
 //             sinkEvents(Event.ONMOUSEDOWN);
 //             sinkEvents(Event.ONCLICK);
 //             sinkEvents(Event.ONKEYDOWN);
-//             sinkEvents(Event.ONDBLCLICK);
+               sinkEvents(Event.ONDBLCLICK);
                Pithos.preventIESelection();
        }
 
@@ -448,9 +416,9 @@ public class FileList extends Composite {
         return new ArrayList<File>(selectionModel.getSelectedSet());
        }
        
-//     @Override
-//     public void onBrowserEvent(Event event) {
-//
+       @Override
+       public void onBrowserEvent(Event event) {
+
 //             if (files == null || files.size() == 0) {
 //                     if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && getSelectedFiles().size() == 0) {
 //                             contextMenu = new FileContextMenu(images, false, true);
@@ -471,44 +439,22 @@ public class FileList extends Composite {
 //                     contextMenu = contextMenu.onEmptyEvent(event);
 //                     event.cancelBubble(true);
 //                     event.preventDefault();
-//             } else if (DOM.eventGetType(event) == Event.ONDBLCLICK)
-//                     if (getSelectedFiles().size() == 1) {
-//                             Pithos app = app;
-//                             File file = getSelectedFiles().get(0);
-//                             Window.open(file.getUri(), "_blank", "");
-//                             event.preventDefault();
-//                             return;
-//                     }
-//             super.onBrowserEvent(event);
-//     }
+//             } else 
+               if (DOM.eventGetType(event) == Event.ONDBLCLICK)
+                       if (getSelectedFiles().size() == 1) {
+                               File file = getSelectedFiles().get(0);
+                               Window.open(app.getApiPath() + file.getOwner() + file.getUri(), "_blank", "");
+                               event.preventDefault();
+                               return;
+                       }
+               super.onBrowserEvent(event);
+       }
 
        /**
         * Update the display of the file list.
         */
-       void update(boolean sort) {
-               int count = folderFileCount;
-               int max = startIndex + Pithos.VISIBLE_FILE_COUNT;
-               if (max > count)
-                       max = count;
-               folderTotalSize = 0;
-               
-               for(File f : files){
-                       folderTotalSize += f.getBytes();
-               }
-               if (folderFileCount == 0) {
-                       showingStats = "no files";
-               } else if (folderFileCount < Pithos.VISIBLE_FILE_COUNT) {
-                       if (folderFileCount == 1)
-                               showingStats = "1 file";
-                       else
-                               showingStats = folderFileCount + " files";
-//                     showingStats += " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
-               } else {
-//                     showingStats = "" + (startIndex + 1) + " - " + max + " of " + count + " files" + " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
-               }
+       void update() {
                showCellTable();
-               updateCurrentlyShowingStats();
-
        }
 
        /**
@@ -517,85 +463,75 @@ public class FileList extends Composite {
         * @param file
         * @return the icon
         */
-       private ImageResource getFileIcon(File file) {
+       protected ImageResource getFileIcon(File file) {
                String mimetype = file.getContentType();
-               boolean shared = file.isShared();
+               boolean published = file.isPublished();
                if (mimetype == null)
-                       return shared ? images.documentShared() : images.document();
+                       return published ? images.documentShared() : images.document();
                mimetype = mimetype.toLowerCase();
                if (mimetype.startsWith("application/pdf"))
-                       return shared ? images.pdfShared() : images.pdf();
+                       return published ? images.pdfShared() : images.pdf();
                else if (mimetype.endsWith("excel"))
-                       return shared ? images.spreadsheetShared() : images.spreadsheet();
+                       return published ? images.spreadsheetShared() : images.spreadsheet();
                else if (mimetype.endsWith("msword"))
-                       return shared ? images.wordprocessorShared() : images.wordprocessor();
+                       return published ? images.wordprocessorShared() : images.wordprocessor();
                else if (mimetype.endsWith("powerpoint"))
-                       return shared ? images.presentationShared() : images.presentation();
+                       return published ? images.presentationShared() : images.presentation();
                else if (mimetype.startsWith("application/zip") ||
                                        mimetype.startsWith("application/gzip") ||
                                        mimetype.startsWith("application/x-gzip") ||
                                        mimetype.startsWith("application/x-tar") ||
                                        mimetype.startsWith("application/x-gtar"))
-                       return shared ? images.zipShared() : images.zip();
+                       return published ? images.zipShared() : images.zip();
                else if (mimetype.startsWith("text/html"))
-                       return shared ? images.htmlShared() : images.html();
+                       return published ? images.htmlShared() : images.html();
                else if (mimetype.startsWith("text/plain"))
-                       return shared ? images.txtShared() : images.txt();
+                       return published ? images.txtShared() : images.txt();
                else if (mimetype.startsWith("image/"))
-                       return shared ? images.imageShared() : images.image();
+                       return published ? images.imageShared() : images.image();
                else if (mimetype.startsWith("video/"))
-                       return shared ? images.videoShared() : images.video();
+                       return published ? images.videoShared() : images.video();
                else if (mimetype.startsWith("audio/"))
-                       return shared ? images.audioShared() : images.audio();
-               return shared ? images.documentShared() : images.document();
+                       return published ? images.audioShared() : images.audio();
+               return published ? images.documentShared() : images.document();
        }
 
        /**
-        * Update status panel with currently showing file stats.
-        */
-       public void updateCurrentlyShowingStats() {
-               app.getStatusPanel().updateCurrentlyShowing(showingStats);
-       }
-       
-       /**
         * Fill the file cache with data.
         */
        public void setFiles(final List<File> _files) {
+               if (!app.getSelectedTree().equals(app.mysharedTreeView)) {
+                       if (celltable.getColumnIndex(pathColumn) != -1)
+                               celltable.removeColumn(pathColumn);
+               }
+               else {
+                       if (celltable.getColumnIndex(pathColumn) == -1)
+                               celltable.insertColumn(2, pathColumn, pathHeader);
+               }
                files = new ArrayList<File>();
-       for (File fres : _files)
-               if (!fres.isInTrash())
-                               files.add(fres);
-               Collections.sort(files, new Comparator<File>() {
-
-                       @Override
-                       public int compare(File arg0, File arg1) {
-                               return arg0.getName().compareTo(arg1.getName());
-                       }
-
-               });
+       for (File fres : _files) {
+                       files.add(fres);
+       }
+       
                folderFileCount = files.size();
                
-               nameHeader.setSorted(true);
-               nameHeader.toggleReverseSort();
-               for (SortableHeader otherHeader : allHeaders) {
-               if (otherHeader != nameHeader) {
-                   otherHeader.setSorted(false);
-                   otherHeader.setReverseSort(true);
-               }
-           }
-
-        if(files.size() > Pithos.VISIBLE_FILE_COUNT){
-            pagerBottom.setVisible(true);
-            pagerTop.setVisible(true);
-        }
-        else{
-            pagerTop.setVisible(false);
-            pagerBottom.setVisible(false);
-        }
-        Folder selectedItem = treeView.getSelection();
+               for (SortableHeader header : allHeaders) {
+                       if (header.isSorted())
+                               sortFiles(header.getProperty(), header.getReverseSort());
+               }
+               
+               List<File> previousSelection = getSelectedFiles(); //Keep the previous selection
 
+               provider.getList().clear();
         provider.setList(files);
         selectionModel.clear();
+       for (File f : files) {
+               if (previousSelection.contains(f))
+                       selectionModel.setSelected(f, true);
+       }
+        
+        app.showFolderStatistics(folderFileCount);
+        celltable.setPageSize(folderFileCount);
        }
 
        /**
@@ -628,20 +564,20 @@ public class FileList extends Composite {
                }
        }
 
-       private void sortFiles(final String sortingProperty, final boolean sortingType){
+       protected void sortFiles(final String sortingProperty, final boolean sortingType){
                Collections.sort(files, new Comparator<File>() {
 
             @Override
             public int compare(File arg0, File arg1) {
-                    AbstractImagePrototype descPrototype = AbstractImagePrototype.create(images.desc());
-                    AbstractImagePrototype ascPrototype = AbstractImagePrototype.create(images.asc());
                     if (sortingType){
                             if (sortingProperty.equals("version")) {
                                     return arg0.getVersion() - arg1.getVersion();
                             } else if (sortingProperty.equals("owner")) {
                                     return arg0.getOwner().compareTo(arg1.getOwner());
                             } else if (sortingProperty.equals("date")) {
-                                    return arg0.getLastModified().compareTo(arg1.getLastModified());
+                                       if (arg0.getLastModified() != null && arg1.getLastModified() != null)
+                                               return arg0.getLastModified().compareTo(arg1.getLastModified());
+                                       return 0;
                             } else if (sortingProperty.equals("size")) {
                                     return (int) (arg0.getBytes() - arg1.getBytes());
                             } else if (sortingProperty.equals("name")) {
@@ -679,13 +615,11 @@ public class FileList extends Composite {
        }
        
        final class FileValueUpdater implements ValueUpdater<String>{
-               private String property;
                private SortableHeader header;
                /**
                 * 
                 */
-               public FileValueUpdater(SortableHeader header,String property) {
-                       this.property=property;
+               public FileValueUpdater(SortableHeader header) {
                        this.header=header;
                }
                @Override
@@ -700,8 +634,8 @@ public class FileList extends Composite {
                  }
                }
                celltable.redrawHeaders();
-               sortFiles(property, header.getReverseSort());
-               FileList.this.update(true);                     
+               sortFiles(header.getProperty(), header.getReverseSort());
+               FileList.this.update();                 
                }
                
        }
@@ -710,14 +644,6 @@ public class FileList extends Composite {
         * Shows the files in the cellTable 
      */
        private void showCellTable(){
-               if(files.size()> Pithos.VISIBLE_FILE_COUNT){
-                       pagerBottom.setVisible(true);
-                       pagerTop.setVisible(true);
-               }
-               else{
-                       pagerTop.setVisible(false);
-                       pagerBottom.setVisible(false);
-               }
                provider.setList(files);
                
                provider.refresh();
@@ -725,14 +651,38 @@ public class FileList extends Composite {
                //celltable.redraw();
                celltable.redrawHeaders();              
        }
+       
+       void iterateFilesHeadCommand(final Iterator<File> iter, final Command callback) {
+               if (iter.hasNext()) {
+                       File f = iter.next();
+                       app.scheduleFileHeadCommand(f, new Command() {
+                               
+                               @Override
+                               public void execute() {
+                                       iterateFilesHeadCommand(iter, callback);
+                               }
+                       });
+               }
+               else if (callback != null)
+                       callback.execute();
+       }
 
-    public void showTrash() {
-        uploadButtonBottom.setVisible(false);
-        uploadButtonTop.setVisible(false);
-    }
-
-    public void showFiles() {
-        uploadButtonBottom.setVisible(true);
-        uploadButtonTop.setVisible(true);
-    }
+       public void selectByUrl(List<String> selectedUrls) {
+               Set<File> previous = selectionModel.getSelectedSet();
+               for (File f : previous)
+                       selectionModel.setSelected(f, false);
+               
+               int i = 0;
+               boolean scrolled = false;
+               for (File f : files) {
+                       if (selectedUrls.contains(app.getApiPath() + f.getOwner() + f.getUri())) {
+                               selectionModel.setSelected(f, true);
+                               if (!scrolled) {
+                                       celltable.getRowElement(i).getCells().getItem(0).scrollIntoView();
+                                       scrolled = true;
+                               }
+                       }
+                       i++;
+               }
+       }
 }