Merge branch 'master' into packaging
[pithos-web-client] / src / gr / grnet / pithos / web / client / FileList.java
index d614f30..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
@@ -44,7 +44,9 @@ 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;
@@ -52,19 +54,27 @@ import com.google.gwt.cell.client.ValueUpdater;
 import com.google.gwt.core.client.GWT;
 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.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.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.Window;
 import com.google.gwt.user.client.ui.Composite;
 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;
 
 /**
  * A composite that displays the list of files in a particular folder.
@@ -77,12 +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 {
            @Override
-               @Source({CellTable.Style.DEFAULT_CSS, "GssCellTable.css"})
+               @Source({CellTable.Style.DEFAULT_CSS, "PithosCellTable.css"})
            TableStyle cellTableStyle();
+           
+           @Source("share.png")
+           @ImageOptions(repeatStyle = RepeatStyle.None)
+           ImageResource cellTableSharedIcon();
        }
        
        static interface Templates extends SafeHtmlTemplates {
@@ -210,11 +225,13 @@ public class FileList extends Composite {
 
        private final MultiSelectionModel<File> selectionModel;
 
+       Column<File, String> pathColumn;
+
        protected final List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
 
        SortableHeader nameHeader;
 
-    FolderTreeView treeView;
+       SortableHeader pathHeader;
 
     protected Pithos app;
 
@@ -226,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>(){
 
@@ -256,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,"");
 
@@ -264,72 +287,120 @@ 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();
                
+               pathColumn = new Column<File, String>(new TextCell()) {
+
+                       @Override
+                       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;
+                       }
+               };
+               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();
                        }
                };
-        SortableHeader 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%");
+               vp.addStyleName("pithos-FileListContainer");
 
         vp.add(celltable);
 
                vp.setCellWidth(celltable, "100%");
         vp.addHandler(new ContextMenuHandler() {
             @Override
-            public void onContextMenu(ContextMenuEvent event) {
-               TreeView tree = app.getSelectedTree();
-               if (tree != null && (tree.equals(app.getFolderTreeView()) || tree.equals(app.getOtherSharedTreeView()))) {
-                       Folder selectedFolder = app.getSelection();
-                       FileContextMenu contextMenu = new FileContextMenu(app, images, tree, 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);
-
-               celltable.setSelectionModel(selectionModel, GSSSelectionEventManager.<File> createDefaultManager());
+               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);
@@ -337,7 +408,7 @@ public class FileList extends Composite {
 //             sinkEvents(Event.ONMOUSEDOWN);
 //             sinkEvents(Event.ONCLICK);
 //             sinkEvents(Event.ONKEYDOWN);
-//             sinkEvents(Event.ONDBLCLICK);
+               sinkEvents(Event.ONDBLCLICK);
                Pithos.preventIESelection();
        }
 
@@ -345,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);
@@ -368,21 +439,21 @@ 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(@SuppressWarnings("unused") boolean sort) {
+       void update() {
                showCellTable();
        }
 
@@ -394,65 +465,73 @@ public class FileList extends Composite {
         */
        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();
        }
 
        /**
         * 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)
+       for (File fres : _files) {
                        files.add(fres);
-               Collections.sort(files, new Comparator<File>() {
-
-                       @Override
-                       public int compare(File arg0, File arg1) {
-                               return arg0.getName().compareTo(arg1.getName());
-                       }
-
-               });
+       }
+       
                folderFileCount = files.size();
                
-               nameHeader.setSorted(true);
-               nameHeader.toggleReverseSort();
-               for (SortableHeader otherHeader : allHeaders) {
-               if (otherHeader != nameHeader) {
-                   otherHeader.setSorted(false);
-                   otherHeader.setReverseSort(true);
-               }
-           }
+               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);
        }
 
        /**
@@ -496,7 +575,9 @@ public class FileList extends Composite {
                             } 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")) {
@@ -534,17 +615,15 @@ 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
-               public void update(@SuppressWarnings("unused") String value) {
+               public void update(String value) {
                        header.setSorted(true);
                        header.toggleReverseSort();
 
@@ -555,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();                 
                }
                
        }
@@ -572,4 +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 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++;
+               }
+       }
 }