Added ids to folder context menu for trash folder after a wrong merge.
[pithos] / src / gr / ebs / gss / client / SearchResults.java
index cf9c3b9..e619048 100644 (file)
-/*\r
- * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.\r
- *\r
- * This file is part of GSS.\r
- *\r
- * GSS is free software: you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation, either version 3 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * GSS is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with GSS.  If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-package gr.ebs.gss.client;\r
-\r
-import gr.ebs.gss.client.dnd.DnDFocusPanel;\r
-import gr.ebs.gss.client.rest.GetCommand;\r
-import gr.ebs.gss.client.rest.RestCommand;\r
-import gr.ebs.gss.client.rest.RestException;\r
-import gr.ebs.gss.client.rest.resource.FileResource;\r
-import gr.ebs.gss.client.rest.resource.SearchResource;\r
-import gr.ebs.gss.client.rest.resource.UserResource;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.List;\r
-\r
-import com.google.gwt.core.client.GWT;\r
-import com.google.gwt.http.client.URL;\r
-import com.google.gwt.i18n.client.DateTimeFormat;\r
-import com.google.gwt.user.client.DOM;\r
-import com.google.gwt.user.client.DeferredCommand;\r
-import com.google.gwt.user.client.Event;\r
-import com.google.gwt.user.client.IncrementalCommand;\r
-import com.google.gwt.user.client.Window;\r
-import com.google.gwt.user.client.ui.AbstractImagePrototype;\r
-import com.google.gwt.user.client.ui.ClickListener;\r
-import com.google.gwt.user.client.ui.Composite;\r
-import com.google.gwt.user.client.ui.Grid;\r
-import com.google.gwt.user.client.ui.HTML;\r
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
-import com.google.gwt.user.client.ui.HorizontalPanel;\r
-import com.google.gwt.user.client.ui.SourcesTableEvents;\r
-import com.google.gwt.user.client.ui.TableListener;\r
-import com.google.gwt.user.client.ui.VerticalPanel;\r
-import com.google.gwt.user.client.ui.Widget;\r
-\r
-/**\r
- * A composite that displays a list of search results for a particular query on\r
- * files.\r
- */\r
-public class SearchResults extends Composite implements TableListener, ClickListener {\r
-\r
-       private HTML prevButton = new HTML("<a href='javascript:;'>&lt; Previous</a>", true);\r
-\r
-       private HTML nextButton = new HTML("<a href='javascript:;'>Next &gt;</a>", true);\r
-\r
-       private String showingStats = "";\r
-\r
-       private int startIndex = 0;\r
-\r
-       /**\r
-        * A constant that denotes the completion of an IncrementalCommand.\r
-        */\r
-       public static final boolean DONE = false;\r
-\r
-       private boolean clickControl = false;\r
-\r
-       private boolean clickShift = false;\r
-\r
-       private int firstShift = -1;\r
-\r
-       private ArrayList<Integer> selectedRows = new ArrayList<Integer>();\r
-\r
-       /**\r
-        * The context menu for the selected file.\r
-        */\r
-       final DnDFocusPanel contextMenu;\r
-\r
-       /**\r
-        * Specifies that the images available for this composite will be the ones\r
-        * available in FileContextMenu.\r
-        */\r
-       public interface Images extends FileContextMenu.Images, Folders.Images {\r
-\r
-               @Resource("gr/ebs/gss/resources/blank.gif")\r
-               AbstractImagePrototype blank();\r
-\r
-               @Resource("gr/ebs/gss/resources/asc.png")\r
-               AbstractImagePrototype asc();\r
-\r
-               @Resource("gr/ebs/gss/resources/desc.png")\r
-               AbstractImagePrototype desc();\r
-       }\r
-\r
-       /**\r
-        * A label with the number of files in this folder.\r
-        */\r
-       private HTML countLabel = new HTML();\r
-\r
-       /**\r
-        * The table widget with the file list.\r
-        */\r
-       private Grid table;\r
-\r
-       /**\r
-        * The navigation bar for paginating the results.\r
-        */\r
-       private HorizontalPanel navBar = new HorizontalPanel();\r
-\r
-       /**\r
-        * The number of files in the search results\r
-        */\r
-       private int folderFileCount;\r
-\r
-       /**\r
-        * Total search results size\r
-        */\r
-       private long folderTotalSize;\r
-\r
-       /**\r
-        * A cache of the files in the list.\r
-        */\r
-       private List<FileResource> files;\r
-\r
-       /**\r
-        * The widget's image bundle.\r
-        */\r
-       private final Images images;\r
-\r
-       private String sortingProperty = "name";\r
-\r
-       private boolean sortingType = true;\r
-\r
-       private HTML nameLabel;\r
-\r
-       private HTML versionLabel;\r
-\r
-       private HTML sizeLabel;\r
-\r
-       private HTML dateLabel;\r
-\r
-       private HTML ownerLabel;\r
-\r
-       private HTML pathLabel;\r
-\r
-       private HTML searchResults = new HTML("Results for search:");\r
-\r
-       /**\r
-        * Construct the file list widget. This entails setting up the widget\r
-        * layout, fetching the number of files in the current folder from the\r
-        * server and filling the local file cache of displayed files with data from\r
-        * the server, as well.\r
-        *\r
-        * @param _images\r
-        */\r
-       public SearchResults(final Images _images) {\r
-               images = _images;\r
-               final GSS app = GSS.get();\r
-               table = new Grid(GSS.VISIBLE_FILE_COUNT + 1, 8) {\r
-\r
-                       @Override\r
-                       public void onBrowserEvent(Event event) {\r
-                               if (files == null || files.size() == 0)\r
-                                       return;\r
-                               if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() != 0) {\r
-                                       FileContextMenu fm = new FileContextMenu(images, false, false);\r
-                                       fm.onClick(contextMenu);\r
-                               }\r
-                               else if (DOM.eventGetType(event) == Event.ONDBLCLICK)\r
-                                       if(getSelectedFiles().size() == 1){\r
-                                               FileResource file = getSelectedFiles().get(0);\r
-                                               String dateString = RestCommand.getDate();\r
-                                               String resource = file.getUri().substring(app.getApiPath().length()-1,file.getUri().length());\r
-                                               String sig = app.getCurrentUserResource().getUsername()+" "+RestCommand.calculateSig("GET", dateString, resource, RestCommand.base64decode(GSS.get().getToken()));\r
-                                               Window.open(file.getUri() + "?Authorization=" + URL.encodeComponent(sig) + "&Date="+URL.encodeComponent(dateString), "_blank", "");\r
-                                       }\r
-                               if (DOM.eventGetType(event) == Event.ONCLICK) {\r
-                                       if (DOM.eventGetCtrlKey(event))\r
-                                               clickControl = true;\r
-                                       else\r
-                                               clickControl = false;\r
-                                       if (DOM.eventGetShiftKey(event)) {\r
-                                               clickShift = true;\r
-                                               if (selectedRows.size() == 1)\r
-                                                       firstShift = selectedRows.get(0) - startIndex;\r
-                                               //event.preventDefault();\r
-                                       } else {\r
-                                               clickShift = false;\r
-                                               firstShift = -1;\r
-                                               //event.preventDefault();\r
-                                       }\r
-                               }\r
-\r
-                               super.onBrowserEvent(event);\r
-                       }\r
-               };\r
-               prevButton.addClickListener(this);\r
-               nextButton.addClickListener(this);\r
-\r
-               contextMenu = new DnDFocusPanel(new HTML(images.fileContextMenu().getHTML()));\r
-               contextMenu.addClickListener(new FileContextMenu(images, false, false));\r
-               app.getDragController().makeDraggable(contextMenu);\r
-\r
-               // Setup the table.\r
-               table.setCellSpacing(0);\r
-               table.setCellPadding(2);\r
-               table.setWidth("100%");\r
-\r
-               // Hook up events.\r
-               table.addTableListener(this);\r
-\r
-               // Create the 'navigation' bar at the upper-right.\r
-               HorizontalPanel innerNavBar = new HorizontalPanel();\r
-               innerNavBar.setStyleName("gss-ListNavBar");\r
-               innerNavBar.setSpacing(8);\r
-               innerNavBar.add(prevButton);\r
-               innerNavBar.add(countLabel);\r
-               innerNavBar.add(nextButton);\r
-               navBar.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);\r
-               navBar.add(innerNavBar);\r
-               navBar.setWidth("100%");\r
-               VerticalPanel vp = new VerticalPanel();\r
-               vp.add(searchResults);\r
-               searchResults.addStyleName("gss-searchlabel");\r
-               vp.add(table);\r
-               initWidget(vp);\r
-               table.setStyleName("gss-List");\r
-               initTable();\r
-               DeferredCommand.addCommand(new IncrementalCommand() {\r
-\r
-                       public boolean execute() {\r
-                               return fetchRootFolder();\r
-                       }\r
-               });\r
-               table.sinkEvents(Event.ONCONTEXTMENU);\r
-               table.sinkEvents(Event.ONMOUSEUP);\r
-               table.sinkEvents(Event.ONCLICK);\r
-               table.sinkEvents(Event.ONKEYDOWN);\r
-               table.sinkEvents(Event.ONDBLCLICK);\r
-               preventIESelection();\r
-       }\r
-\r
-       public void onClick(Widget sender) {\r
-               if (sender == nextButton) {\r
-                       // Move forward a page.\r
-                       clearSelectedRows();\r
-                       startIndex += GSS.VISIBLE_FILE_COUNT;\r
-                       if (startIndex >= folderFileCount)\r
-                               startIndex -= GSS.VISIBLE_FILE_COUNT;\r
-                       else\r
-                               update();\r
-               } else if (sender == prevButton) {\r
-                       clearSelectedRows();\r
-                       // Move back a page.\r
-                       startIndex -= GSS.VISIBLE_FILE_COUNT;\r
-                       if (startIndex < 0)\r
-                               startIndex = 0;\r
-                       else\r
-                               update();\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Retrieve the root folder for the current user.\r
-        *\r
-        * @return true if the retrieval was successful\r
-        */\r
-       protected boolean fetchRootFolder() {\r
-               UserResource user = GSS.get().getCurrentUserResource();\r
-               if (user == null)\r
-                       return !DONE;\r
-               updateFileCache("");\r
-               return DONE;\r
-       }\r
-\r
-       public void onCellClicked(SourcesTableEvents sender, int row, int cell) {\r
-               // Select the row that was clicked (-1 to account for header row).\r
-               if (row > folderFileCount)\r
-                       return;\r
-               if (clickShift) {\r
-                       GWT.log("ROW is:" + row + " fs:" + firstShift, null);\r
-                       if (firstShift == -1)\r
-                               firstShift = row;\r
-                       else if (row > firstShift) {\r
-                               clearSelectedRows();\r
-                               for (int i = firstShift; i < row; i++) {\r
-                                       selectedRows.add(startIndex + i);\r
-                                       styleRow(i, true);\r
-                               }\r
-                               GSS.get().setCurrentSelection(getSelectedFiles());\r
-                               //contextMenu.setFiles(getSelectedFiles());\r
-                               table.setWidget(row, 0, contextMenu);\r
-                       } else if (row != -1 && row == firstShift) {\r
-                               selectedRows.add(row);\r
-                               selectedRows.add(row - 1);\r
-                               styleRow(row, true);\r
-                               styleRow(row - 1, true);\r
-                       } else if (row < firstShift) {\r
-                               GWT.log("ROW is:" + row + " fs:" + firstShift, null);\r
-                               clearSelectedRows();\r
-\r
-                               for (int i = firstShift; i >= row - 1; i--) {\r
-                                       selectedRows.add(startIndex + i);\r
-                                       styleRow(i, true);\r
-                               }\r
-                               GSS.get().setCurrentSelection(getSelectedFiles());\r
-                               table.setWidget(row, 0, contextMenu);\r
-                               //contextMenu.setFiles(getSelectedFiles());\r
-                       }\r
-\r
-               } else if (row > 0)\r
-                       selectRow(row - 1);\r
-\r
-       }\r
-\r
-       /**\r
-        * Initializes the table so that it contains enough rows for a full page of\r
-        * files.\r
-        */\r
-       private void initTable() {\r
-\r
-               nameLabel = new HTML("Name");\r
-               nameLabel.addClickListener(new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               sortFiles("name");\r
-                               update();\r
-\r
-                       }\r
-\r
-               });\r
-               versionLabel = new HTML("Version");\r
-               versionLabel.addClickListener(new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               sortFiles("version");\r
-                               update();\r
-\r
-                       }\r
-\r
-               });\r
-               sizeLabel = new HTML("Size");\r
-               sizeLabel.addClickListener(new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               sortFiles("size");\r
-                               update();\r
-\r
-                       }\r
-\r
-               });\r
-               dateLabel = new HTML("Date");\r
-               dateLabel.addClickListener(new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               sortFiles("date");\r
-                               update();\r
-\r
-                       }\r
-\r
-               });\r
-               ownerLabel = new HTML("Owner");\r
-               ownerLabel.addClickListener(new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               sortFiles("owner");\r
-                               update();\r
-\r
-                       }\r
-\r
-               });\r
-\r
-               pathLabel = new HTML("Path");\r
-               pathLabel.addClickListener(new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               sortFiles("path");\r
-                               update();\r
-\r
-                       }\r
-\r
-               });\r
-               // Create the header row.\r
-               table.setText(0, 0, "");\r
-               // table.setText(0, 1, "Name");\r
-               table.setWidget(0, 1, nameLabel);\r
-               table.setWidget(0, 2, ownerLabel);\r
-               // table.setText(0, 3, "Version");\r
-               table.setWidget(0, 3, pathLabel);\r
-               table.setWidget(0, 4, versionLabel);\r
-               // table.setText(0, 4, "Size");\r
-               table.setWidget(0, 5, sizeLabel);\r
-               // table.setText(0, 5, "Date");\r
-               table.setWidget(0, 6, dateLabel);\r
-               table.setWidget(0, 7, navBar);\r
-               table.getRowFormatter().setStyleName(0, "gss-ListHeader");\r
-\r
-               // Initialize the rest of the rows.\r
-               for (int i = 1; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
-                       table.setText(i, 0, "");\r
-                       table.setText(i, 1, "");\r
-                       table.setText(i, 2, "");\r
-                       table.setText(i, 3, "");\r
-                       table.setText(i, 4, "");\r
-                       table.setText(i, 5, "");\r
-                       table.setText(i, 6, "");\r
-                       table.getCellFormatter().setWordWrap(i, 0, false);\r
-                       table.getCellFormatter().setWordWrap(i, 1, false);\r
-                       table.getCellFormatter().setWordWrap(i, 2, false);\r
-                       table.getCellFormatter().setWordWrap(i, 3, false);\r
-                       table.getCellFormatter().setWordWrap(i, 4, false);\r
-                       table.getCellFormatter().setWordWrap(i, 5, false);\r
-                       table.getCellFormatter().setWordWrap(i, 6, false);\r
-                       table.getCellFormatter().setHorizontalAlignment(i, 4, HasHorizontalAlignment.ALIGN_CENTER);\r
-               }\r
-               prevButton.setVisible(false);\r
-               nextButton.setVisible(false);\r
-       }\r
-\r
-       /**\r
-        * Selects the given row (relative to the current page).\r
-        *\r
-        * @param row the row to be selected\r
-        */\r
-       private void selectRow(final int row) {\r
-               if (row < folderFileCount) {\r
-                       if (clickControl)\r
-                               if (selectedRows.contains(row)) {\r
-                                       int i = selectedRows.indexOf(startIndex + row);\r
-                                       selectedRows.remove(i);\r
-                                       styleRow(row, false);\r
-                               } else {\r
-                                       for (int r : selectedRows) {\r
-                                               int prow = r - startIndex;\r
-                                               table.setWidget(prow + 1, 0, images.document().createImage());\r
-                                       }\r
-                                       selectedRows.add(startIndex + row);\r
-                                       styleRow(row, true);\r
-                               }\r
-                       else {\r
-                               clearSelectedRows();\r
-                               selectedRows.add(startIndex + row);\r
-                               styleRow(row, true);\r
-                       }\r
-                       if (selectedRows.size() == 1)\r
-                               GSS.get().setCurrentSelection(files.get(selectedRows.get(0)));\r
-                       else\r
-                               GSS.get().setCurrentSelection(getSelectedFiles());\r
-                       //contextMenu.setFiles(getSelectedFiles());\r
-                       table.setWidget(row + 1, 0, contextMenu);\r
-               }\r
-       }\r
-\r
-       public List<FileResource> getSelectedFiles() {\r
-               List<FileResource> result = new ArrayList();\r
-               for (int i : selectedRows)\r
-                       result.add(files.get(i));\r
-               return result;\r
-       }\r
-\r
-       /**\r
-        * Make the specified row look like selected or not, according to the\r
-        * <code>selected</code> flag.\r
-        *\r
-        * @param row\r
-        * @param selected\r
-        */\r
-       void styleRow(final int row, final boolean selected) {\r
-               if (row != -1 && row >= 0)\r
-                       if (selected)\r
-                               table.getRowFormatter().addStyleName(row + 1, "gss-SelectedRow");\r
-                       else\r
-                               table.getRowFormatter().removeStyleName(row + 1, "gss-SelectedRow");\r
-       }\r
-\r
-       /**\r
-        * Update the display of the file list.\r
-        */\r
-       void update() {\r
-               int count = folderFileCount;\r
-               int max = startIndex + GSS.VISIBLE_FILE_COUNT;\r
-               if (max > count)\r
-                       max = count;\r
-               folderTotalSize = 0;\r
-\r
-               // Show the selected files.\r
-               int i = 1;\r
-               for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
-                       // Don't read past the end.\r
-                       // if (i > folderFileCount)\r
-                       // break;\r
-                       if (startIndex + i > folderFileCount)\r
-                               break;\r
-                       // Add a new row to the table, then set each of its columns to the\r
-                       // proper values.\r
-                       table.setWidget(i, 0, images.document().createImage());\r
-                       FileResource fileHeader = files.get(startIndex + i - 1);\r
-                       table.getRowFormatter().addStyleName(i, "gss-fileRow");\r
-                       table.setHTML(i, 1, fileHeader.getName());\r
-                       table.setText(i, 2, fileHeader.getOwner());\r
-                       table.setText(i, 3, fileHeader.getPath());\r
-                       table.setText(i, 4, String.valueOf(fileHeader.getVersion()));\r
-                       table.setText(i, 5, String.valueOf(fileHeader.getFileSizeAsString()));\r
-                       final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");\r
-                       table.setText(i, 6, formatter.format(fileHeader.getCreationDate()));\r
-                       folderTotalSize += fileHeader.getContentLength();\r
-               }\r
-\r
-               // Clear any remaining slots.\r
-               for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
-                       table.setHTML(i, 0, "&nbsp;");\r
-                       table.setHTML(i, 1, "&nbsp;");\r
-                       table.setHTML(i, 2, "&nbsp;");\r
-                       table.setHTML(i, 3, "&nbsp;");\r
-                       table.setHTML(i, 4, "&nbsp;");\r
-                       table.setHTML(i, 5, "&nbsp;");\r
-                       table.setHTML(i, 6, "&nbsp;");\r
-                       table.setHTML(i, 7, "&nbsp;");\r
-               }\r
-\r
-               if (folderFileCount == 0) {\r
-                       showingStats = "no files";\r
-                       prevButton.setVisible(false);\r
-                       nextButton.setVisible(false);\r
-               } else if (folderFileCount < GSS.VISIBLE_FILE_COUNT) {\r
-                       if (folderFileCount == 1)\r
-                               showingStats = "1 file";\r
-                       else\r
-                               showingStats = folderFileCount + " files";\r
-                       showingStats += " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";\r
-                       prevButton.setVisible(false);\r
-                       nextButton.setVisible(false);\r
-               } else {\r
-                       showingStats = "" + (startIndex + 1) + " - " + max + " of " + count + " files" + " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";\r
-                       prevButton.setVisible(startIndex != 0);\r
-                       nextButton.setVisible(startIndex + GSS.VISIBLE_FILE_COUNT < count);\r
-               }\r
-               updateCurrentlyShowingStats();\r
-       }\r
-\r
-       /**\r
-        *  update status panel with currently showing file stats\r
-        */\r
-       public void updateCurrentlyShowingStats() {\r
-               GSS.get().getStatusPanel().updateCurrentlyShowing(showingStats);\r
-       }\r
-\r
-       /**\r
-        * Adjust the height of the table by adding and removing rows as necessary.\r
-        *\r
-        * @param newHeight the new height to reach\r
-        */\r
-       void resizeTableHeight(final int newHeight) {\r
-               GWT.log("Panel: " + newHeight + ", parent: " + table.getParent().getOffsetHeight(), null);\r
-               // Fill the rest with empty slots.\r
-               if (newHeight > table.getOffsetHeight())\r
-                       while (newHeight > table.getOffsetHeight()) {\r
-                               // table.setHTML(table.getRowCount(), 5, "&nbsp;");\r
-                               table.resizeRows(table.getRowCount() + 1);\r
-                               GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);\r
-                       }\r
-               else\r
-                       while (newHeight < table.getOffsetHeight()) {\r
-                               // table.setHTML(table.getRowCount(), 5, "&nbsp;");\r
-                               table.resizeRows(table.getRowCount() - 1);\r
-                               GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);\r
-                       }\r
-       }\r
-\r
-       /**\r
-        * Update the file cache with data from the server.\r
-        */\r
-       public void updateFileCache(String query) {\r
-               final GSS app = GSS.get();\r
-               clearSelectedRows();\r
-               sortingProperty = "name";\r
-               clearLabels();\r
-               nameLabel.setHTML("Name&nbsp;" + images.desc().getHTML());\r
-               sortingType = true;\r
-               startIndex = 0;\r
-               app.showLoadingIndicator();\r
-               if (query == null || query.trim().equals("")) {\r
-                       searchResults.setHTML("You must specify a query");\r
-                       setFiles(new ArrayList());\r
-                       update();\r
-                       app.hideLoadingIndicator();\r
-               } else{\r
-                       searchResults.setHTML("Search results for " + query);\r
-\r
-                       GetCommand<SearchResource> eg = new GetCommand<SearchResource>(SearchResource.class,\r
-                                               app.getApiPath() + "search/" + URL.encodeComponent(query)) {\r
-\r
-                               @Override\r
-                               public void onComplete() {\r
-                                       SearchResource s = getResult();\r
-                                       setFiles(s.getFiles());\r
-                                       update();\r
-                               }\r
-\r
-                               @Override\r
-                               public void onError(Throwable t) {\r
-                                       if(t instanceof RestException)\r
-                                               app.displayError("Unable to perform search:"+((RestException)t).getHttpStatusText());\r
-                                       else\r
-                                               app.displayError("System error performing search:"+t.getMessage());\r
-                                       updateFileCache("");\r
-                               }\r
-\r
-                       };\r
-                       DeferredCommand.addCommand(eg);\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Fill the file cache with data.\r
-        *\r
-        * @param _files\r
-        * @param filePaths the files to set\r
-        */\r
-       private void setFiles(List<FileResource> _files) {\r
-               files = _files;\r
-               Collections.sort(files, new Comparator<FileResource>() {\r
-\r
-                       public int compare(FileResource arg0, FileResource arg1) {\r
-                               return arg0.getName().compareTo(arg1.getName());\r
-                       }\r
-\r
-               });\r
-               folderFileCount = files.size();\r
-               GWT.log("File count:" + folderFileCount, null);\r
-       }\r
-\r
-       private void sortFiles(final String sortProperty) {\r
-               if (sortProperty.equals(sortingProperty))\r
-                       sortingType = !sortingType;\r
-               else {\r
-                       sortingProperty = sortProperty;\r
-                       sortingType = true;\r
-               }\r
-               clearLabels();\r
-               clearSelectedRows();\r
-               if (files == null || files.size() == 0)\r
-                       return;\r
-               Collections.sort(files, new Comparator<FileResource>() {\r
-\r
-                       public int compare(FileResource arg0, FileResource arg1) {\r
-                               if (sortingType)\r
-                                       if (sortProperty.equals("version")) {\r
-                                               versionLabel.setHTML("Version&nbsp;" + images.desc().getHTML());\r
-                                               return new Integer(arg0.getVersion()).compareTo(new Integer(arg1.getVersion()));\r
-                                       } else if (sortProperty.equals("owner")) {\r
-                                               ownerLabel.setHTML("Owner&nbsp;" + images.desc().getHTML());\r
-                                               GWT.log(arg0.getOwner() + "/" + arg1.getOwner(), null);\r
-                                               return arg0.getOwner().compareTo(arg1.getOwner());\r
-                                       } else if (sortProperty.equals("date")) {\r
-                                               dateLabel.setHTML("Date&nbsp;" + images.desc().getHTML());\r
-                                               return arg0.getCreationDate().compareTo(arg1.getCreationDate());\r
-                                       } else if (sortProperty.equals("size")) {\r
-                                               sizeLabel.setHTML("Size&nbsp;" + images.desc().getHTML());\r
-                                               return new Long(arg0.getContentLength()).compareTo(new Long(arg1.getContentLength()));\r
-                                       } else if (sortProperty.equals("name")) {\r
-                                               nameLabel.setHTML("Name&nbsp;" + images.desc().getHTML());\r
-                                               return arg0.getName().compareTo(arg1.getName());\r
-                                       } else if (sortProperty.equals("path")) {\r
-                                               pathLabel.setHTML("Path&nbsp;" + images.desc().getHTML());\r
-                                               return arg0.getUri().compareTo(arg1.getUri());\r
-                                       } else {\r
-                                               nameLabel.setHTML("Name&nbsp;" + images.desc().getHTML());\r
-                                               return arg0.getName().compareTo(arg1.getName());\r
-                                       }\r
-                               else if (sortProperty.equals("version")) {\r
-                                       versionLabel.setHTML("Version&nbsp;" + images.asc().getHTML());\r
-                                       return new Integer(arg1.getVersion()).compareTo(new Integer(arg0.getVersion()));\r
-                               } else if (sortProperty.equals("owner")) {\r
-                                       ownerLabel.setHTML("Owner&nbsp;" + images.asc().getHTML());\r
-                                       return arg1.getOwner().compareTo(arg0.getOwner());\r
-                               } else if (sortProperty.equals("date")) {\r
-                                       dateLabel.setHTML("Date&nbsp;" + images.asc().getHTML());\r
-                                       return arg1.getCreationDate().compareTo(arg0.getCreationDate());\r
-                               } else if (sortProperty.equals("size")) {\r
-                                       sizeLabel.setHTML("Size&nbsp;" + images.asc().getHTML());\r
-                                       return new Long(arg1.getContentLength()).compareTo(new Long(arg0.getContentLength()));\r
-                               } else if (sortProperty.equals("name")) {\r
-                                       nameLabel.setHTML("Name&nbsp;" + images.asc().getHTML());\r
-                                       return arg1.getName().compareTo(arg0.getName());\r
-                               } else if (sortProperty.equals("path")) {\r
-                                       pathLabel.setHTML("Path&nbsp;" + images.asc().getHTML());\r
-                                       return arg1.getUri().compareTo(arg0.getUri());\r
-                               } else {\r
-                                       nameLabel.setHTML("Name&nbsp;" + images.asc().getHTML());\r
-                                       return arg1.getName().compareTo(arg0.getName());\r
-                               }\r
-                       }\r
-\r
-               });\r
-       }\r
-\r
-       private void clearLabels() {\r
-               nameLabel.setText("Name");\r
-               versionLabel.setText("Version");\r
-               sizeLabel.setText("Size");\r
-               dateLabel.setText("Date");\r
-               ownerLabel.setText("Owner");\r
-               pathLabel.setText("Path");\r
-       }\r
-\r
-       /**\r
-        * Retrieve the table.\r
-        *\r
-        * @return the table\r
-        */\r
-       Grid getTable() {\r
-               return table;\r
-       }\r
-\r
-       /**\r
-        * Does the list contains the requested filename\r
-        *\r
-        * @param fileName\r
-        * @return true/false\r
-        */\r
-       public boolean contains(String fileName) {\r
-               for (int i = 0; i < files.size(); i++)\r
-                       if (files.get(i).getName().equals(fileName))\r
-                               return true;\r
-               return false;\r
-       }\r
-\r
-       public void clearSelectedRows() {\r
-               for (int r : selectedRows) {\r
-                       int row = r - startIndex;\r
-                       styleRow(row, false);\r
-                       table.setWidget(row + 1, 0, images.document().createImage());\r
-               }\r
-               selectedRows.clear();\r
-               Object sel = GSS.get().getCurrentSelection();\r
-               if (sel instanceof FileResource || sel instanceof List)\r
-                       GSS.get().setCurrentSelection(null);\r
-       }\r
-\r
-       public static native void preventIESelection() /*-{\r
-            $doc.body.onselectstart = function () { return false; };\r
-        }-*/;\r
-\r
-       public static native void enableIESelection() /*-{\r
-        if ($doc.body.onselectstart != null)\r
-            $doc.body.onselectstart = null;\r
-        }-*/;\r
-\r
-       public void selectAllRows() {\r
-               clearSelectedRows();\r
-               int count = folderFileCount;\r
-               if (count == 0)\r
-                       return;\r
-               int max = startIndex + GSS.VISIBLE_FILE_COUNT;\r
-               if (max > count)\r
-                       max = count;\r
-               int i = 1;\r
-               for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {\r
-                       // Don't read past the end.\r
-                       // if (i > folderFileCount)\r
-                       // break;\r
-                       if (startIndex + i > folderFileCount)\r
-                               break;\r
-                       selectedRows.add(startIndex + i - 1);\r
-                       styleRow(i - 1, true);\r
-               }\r
-               GSS.get().setCurrentSelection(getSelectedFiles());\r
-               //contextMenu.setFiles(getSelectedFiles());\r
-               table.setWidget(i - 1, 0, contextMenu);\r
-       }\r
-\r
-}\r
+/*
+ * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.client;
+
+
+import gr.ebs.gss.client.rest.GetCommand;
+import gr.ebs.gss.client.rest.RestCommand;
+import gr.ebs.gss.client.rest.RestException;
+import gr.ebs.gss.client.rest.resource.FileResource;
+import gr.ebs.gss.client.rest.resource.SearchResource;
+import gr.ebs.gss.client.rest.resource.UserResource;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+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.user.client.DOM;
+import com.google.gwt.user.client.DeferredCommand;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.IncrementalCommand;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.HTMLTable.Cell;
+
+/**
+ * A composite that displays a list of search results for a particular query on
+ * files.
+ */
+public class SearchResults extends Composite implements  ClickHandler {
+
+       private HTML prevButton = new HTML("<a href='javascript:;'>&lt; Previous</a>", true);
+
+       private HTML nextButton = new HTML("<a href='javascript:;'>Next &gt;</a>", true);
+
+       private String showingStats = "";
+
+       private int startIndex = 0;
+
+       /**
+        * A constant that denotes the completion of an IncrementalCommand.
+        */
+       public static final boolean DONE = false;
+
+       private boolean clickControl = false;
+
+       private boolean clickShift = false;
+
+       private int firstShift = -1;
+
+       private ArrayList<Integer> selectedRows = new ArrayList<Integer>();
+
+       
+
+       /**
+        * Specifies that the images available for this composite will be the ones
+        * available in FileContextMenu.
+        */
+       public interface Images extends ClientBundle,FileContextMenu.Images, CellTreeView.Images {
+
+               @Source("gr/ebs/gss/resources/blank.gif")
+               ImageResource blank();
+
+               @Source("gr/ebs/gss/resources/asc.png")
+               ImageResource asc();
+
+               @Source("gr/ebs/gss/resources/desc.png")
+               ImageResource desc();
+       }
+
+       /**
+        * A label with the number of files in this folder.
+        */
+       private HTML countLabel = new HTML();
+
+       /**
+        * The table widget with the file list.
+        */
+       private FileTable table;
+
+       /**
+        * The navigation bar for paginating the results.
+        */
+       private HorizontalPanel navBar = new HorizontalPanel();
+
+       /**
+        * The number of files in the search results
+        */
+       private int folderFileCount;
+
+       /**
+        * Total search results size
+        */
+       private long folderTotalSize;
+
+       /**
+        * A cache of the files in the list.
+        */
+       private List<FileResource> files;
+
+       /**
+        * The widget's image bundle.
+        */
+       private final Images images;
+
+       private String sortingProperty = "name";
+
+       private boolean sortingType = true;
+
+       private HTML nameLabel;
+
+       private HTML versionLabel;
+
+       private HTML sizeLabel;
+
+       private HTML dateLabel;
+
+       private HTML ownerLabel;
+
+       private HTML pathLabel;
+
+       private HTML searchResults = new HTML("Results for search:");
+
+       /**
+        * Construct the file list widget. This entails setting up the widget
+        * layout, fetching the number of files in the current folder from the
+        * server and filling the local file cache of displayed files with data from
+        * the server, as well.
+        *
+        * @param _images
+        */
+       public SearchResults(final Images _images) {
+               images = _images;
+               final GSS app = GSS.get();
+               table = new FileTable(GSS.VISIBLE_FILE_COUNT + 1, 8) {
+
+                       @Override
+                       public void onBrowserEvent(Event event) {
+                               if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && DOM.eventGetButton(event) == NativeEvent.BUTTON_RIGHT){
+                                       if (DOM.eventGetCtrlKey(event))
+                                               clickControl = true;
+                                       else
+                                               clickControl = false;
+                                       if (DOM.eventGetShiftKey(event)) {
+                                               clickShift = true;
+                                               if (selectedRows.size() == 1)
+                                                       firstShift = selectedRows.get(0) - startIndex;
+                                               //event.preventDefault();
+                                       } else {
+                                               clickShift = false;
+                                               firstShift = -1;
+                                               //event.preventDefault();
+                                       }
+                                       int ri = table.getRowForEvent2(event);
+                                       if(ri != -1)
+                                               if(!selectedRows.contains(ri-1))
+                                                       onRowClicked(ri, false);
+                               }
+
+                               if (files == null || files.size() == 0) {
+                                       if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() == 0) {
+                                               FileContextMenu fm = new FileContextMenu(images, false, true);
+                                               fm.onEmptyEvent(event);
+                                       }
+                                       return;
+                               }
+                               if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() != 0) {
+                                       FileContextMenu fm = new FileContextMenu(images, false, false);
+                                       fm.onEvent(event);
+                               } else if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() == 0) {
+                                       FileContextMenu fm = new FileContextMenu(images, false, true);
+                                       fm.onEmptyEvent(event);
+                               } else if (DOM.eventGetType(event) == Event.ONDBLCLICK)
+                                       if (getSelectedFiles().size() == 1) {
+                                               FileResource file = getSelectedFiles().get(0);
+                                               String dateString = RestCommand.getDate();
+                                               String resource = file.getUri().substring(app.getApiPath().length() - 1, file.getUri().length());
+                                               String sig = app.getCurrentUserResource().getUsername() + " " +
+                                                               RestCommand.calculateSig("GET", dateString, resource,
+                                                               RestCommand.base64decode(app.getToken()));
+                                               Window.open(file.getUri() + "?Authorization=" + URL.encodeComponent(sig) + "&Date=" + URL.encodeComponent(dateString), "_blank", "");
+                                               event.preventDefault();
+                                               return;
+                                       }
+                               if (DOM.eventGetType(event) == Event.ONCLICK) {
+                                       if (DOM.eventGetCtrlKey(event))
+                                               clickControl = true;
+                                       else
+                                               clickControl = false;
+                                       if (DOM.eventGetShiftKey(event)) {
+                                               clickShift = true;
+                                               if (selectedRows.size() == 1)
+                                                       firstShift = selectedRows.get(0) - startIndex;
+                                               //event.preventDefault();
+                                       } else {
+                                               clickShift = false;
+                                               firstShift = -1;
+                                               //event.preventDefault();
+                                       }
+                               }
+                               super.onBrowserEvent(event);
+                       }
+               };
+               prevButton.addClickHandler(this);
+               nextButton.addClickHandler(this);
+
+               
+               // Setup the table.
+               table.setCellSpacing(0);
+               table.setCellPadding(2);
+               table.setWidth("100%");
+
+               // Hook up events.
+               table.addClickHandler(new ClickHandler() {
+
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               Cell cell = table.getCellForEvent(event);
+                               onRowClicked(cell.getRowIndex(),true);
+                       }
+               });
+
+               // Create the 'navigation' bar at the upper-right.
+               HorizontalPanel innerNavBar = new HorizontalPanel();
+               innerNavBar.setStyleName("gss-ListNavBar");
+               innerNavBar.setSpacing(8);
+               innerNavBar.add(prevButton);
+               innerNavBar.add(countLabel);
+               innerNavBar.add(nextButton);
+               navBar.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
+               navBar.add(innerNavBar);
+               navBar.setWidth("100%");
+               VerticalPanel vp = new VerticalPanel();
+               vp.add(searchResults);
+               searchResults.addStyleName("gss-searchLabel");
+               vp.add(table);
+               initWidget(vp);
+               table.setStyleName("gss-List");
+               initTable();
+               DeferredCommand.addCommand(new IncrementalCommand() {
+
+                       @Override
+                       public boolean execute() {
+                               return fetchRootFolder();
+                       }
+               });
+               table.sinkEvents(Event.ONCONTEXTMENU);
+               table.sinkEvents(Event.ONMOUSEUP);
+               table.sinkEvents(Event.ONMOUSEDOWN);
+               table.sinkEvents(Event.ONCLICK);
+               table.sinkEvents(Event.ONKEYDOWN);
+               table.sinkEvents(Event.ONDBLCLICK);
+               preventIESelection();
+       }
+
+       @Override
+       public void onClick(ClickEvent event) {
+               if (event.getSource() == nextButton) {
+                       // Move forward a page.
+                       clearSelectedRows();
+                       startIndex += GSS.VISIBLE_FILE_COUNT;
+                       if (startIndex >= folderFileCount)
+                               startIndex -= GSS.VISIBLE_FILE_COUNT;
+                       else
+                               update(false);
+               } else if (event.getSource() == prevButton) {
+                       clearSelectedRows();
+                       // Move back a page.
+                       startIndex -= GSS.VISIBLE_FILE_COUNT;
+                       if (startIndex < 0)
+                               startIndex = 0;
+                       else
+                               update(false);
+               }
+       }
+
+       /**
+        * Retrieve the root folder for the current user.
+        *
+        * @return true if the retrieval was successful
+        */
+       protected boolean fetchRootFolder() {
+               UserResource user = GSS.get().getCurrentUserResource();
+               if (user == null)
+                       return !DONE;
+               updateFileCache("");
+               return DONE;
+       }
+
+       public void onRowClicked(int row, boolean toggleSelection) {
+               // Select the row that was clicked (-1 to account for header row).
+               if (row > folderFileCount)
+                       return;
+               if (clickShift) {
+                       GWT.log("ROW is:" + row + " fs:" + firstShift, null);
+                       if (firstShift == -1)
+                               firstShift = row;
+                       else if (row > firstShift) {
+                               clearSelectedRows();
+                               for (int i = firstShift; i < row; i++) {
+                                       selectedRows.add(startIndex + i);
+                                       styleRow(i, true);
+                               }
+                               GSS.get().setCurrentSelection(getSelectedFiles());
+                               //contextMenu.setFiles(getSelectedFiles());
+                               //table.setWidget(row, 0, contextMenu);
+                       } else if (row != -1 && row == firstShift) {
+                               selectedRows.add(row);
+                               selectedRows.add(row - 1);
+                               styleRow(row, true);
+                               styleRow(row - 1, true);
+                       } else if (row < firstShift) {
+                               GWT.log("ROW is:" + row + " fs:" + firstShift, null);
+                               clearSelectedRows();
+
+                               for (int i = firstShift; i >= row - 1; i--) {
+                                       selectedRows.add(startIndex + i);
+                                       styleRow(i, true);
+                               }
+                               GSS.get().setCurrentSelection(getSelectedFiles());
+                               //table.setWidget(row, 0, contextMenu);
+                               //contextMenu.setFiles(getSelectedFiles());
+                       }
+
+               } else if (row > 0)
+                       selectRow(row - 1, toggleSelection);
+
+       }
+
+       /**
+        * Initializes the table so that it contains enough rows for a full page of
+        * files.
+        */
+       private void initTable() {
+
+               nameLabel = new HTML("Name");
+               nameLabel.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               sortFiles("name");
+                       }
+
+               });
+               versionLabel = new HTML("Version");
+               versionLabel.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               sortFiles("version");
+                       }
+
+               });
+               sizeLabel = new HTML("Size");
+               sizeLabel.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               sortFiles("size");
+                       }
+
+               });
+               dateLabel = new HTML("Last modified");
+               dateLabel.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               sortFiles("date");
+                       }
+
+               });
+               ownerLabel = new HTML("Owner");
+               ownerLabel.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               sortFiles("owner");
+                       }
+
+               });
+
+               pathLabel = new HTML("Path");
+               pathLabel.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               sortFiles("path");
+                       }
+
+               });
+               // Create the header row.
+               table.setText(0, 0, "");
+               // table.setText(0, 1, "Name");
+               table.setWidget(0, 1, nameLabel);
+               table.setWidget(0, 2, ownerLabel);
+               // table.setText(0, 3, "Version");
+               table.setWidget(0, 3, pathLabel);
+               table.setWidget(0, 4, versionLabel);
+               // table.setText(0, 4, "Size");
+               table.setWidget(0, 5, sizeLabel);
+               // table.setText(0, 5, "Last modified");
+               table.setWidget(0, 6, dateLabel);
+               table.setWidget(0, 7, navBar);
+               table.getRowFormatter().setStyleName(0, "gss-ListHeader");
+
+               // Initialize the rest of the rows.
+               for (int i = 1; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
+                       table.setText(i, 0, "");
+                       table.setText(i, 1, "");
+                       table.setText(i, 2, "");
+                       table.setText(i, 3, "");
+                       table.setText(i, 4, "");
+                       table.setText(i, 5, "");
+                       table.setText(i, 6, "");
+                       table.getCellFormatter().setWordWrap(i, 0, false);
+                       table.getCellFormatter().setWordWrap(i, 1, false);
+                       table.getCellFormatter().setWordWrap(i, 2, false);
+                       table.getCellFormatter().setWordWrap(i, 3, false);
+                       table.getCellFormatter().setWordWrap(i, 4, false);
+                       table.getCellFormatter().setWordWrap(i, 5, false);
+                       table.getCellFormatter().setWordWrap(i, 6, false);
+                       table.getCellFormatter().setHorizontalAlignment(i, 4, HasHorizontalAlignment.ALIGN_CENTER);
+               }
+               prevButton.setVisible(false);
+               nextButton.setVisible(false);
+       }
+
+       /**
+        * Selects the given row (relative to the current page).
+        *
+        * @param row the row to be selected
+        */
+       private void selectRow(final int row, boolean toggleSelection) {
+               if (row < folderFileCount) {
+                       if (clickControl)
+                               if (selectedRows.contains(row) && toggleSelection) {
+                                       int i = selectedRows.indexOf(startIndex + row);
+                                       selectedRows.remove(i);
+                                       styleRow(row, false);
+                               } else {
+                                       for (int r : selectedRows) {
+                                               int prow = r - startIndex;
+                                               table.setWidget(prow + 1, 0, AbstractImagePrototype.create(images.document()).createImage());
+                                       }
+                                       selectedRows.add(startIndex + row);
+                                       styleRow(row, true);
+                               }
+                       else {
+                               clearSelectedRows();
+                               selectedRows.add(startIndex + row);
+                               styleRow(row, true);
+                       }
+                       if (selectedRows.size() == 1)
+                               GSS.get().setCurrentSelection(files.get(selectedRows.get(0)));
+                       else
+                               GSS.get().setCurrentSelection(getSelectedFiles());
+                       //contextMenu.setFiles(getSelectedFiles());
+                       //table.setWidget(row + 1, 0, contextMenu);
+               }
+       }
+
+       public List<FileResource> getSelectedFiles() {
+               List<FileResource> result = new ArrayList();
+               for (int i : selectedRows)
+                       result.add(files.get(i));
+               return result;
+       }
+
+       /**
+        * Make the specified row look like selected or not, according to the
+        * <code>selected</code> flag.
+        *
+        * @param row
+        * @param selected
+        */
+       void styleRow(final int row, final boolean selected) {
+               if (row != -1 && row >= 0)
+                       if (selected)
+                               table.getRowFormatter().addStyleName(row + 1, "gss-SelectedRow");
+                       else
+                               table.getRowFormatter().removeStyleName(row + 1, "gss-SelectedRow");
+       }
+
+       /**
+        * Update the display of the file list.
+        */
+       void update(boolean sort) {
+               int count = folderFileCount;
+               int max = startIndex + GSS.VISIBLE_FILE_COUNT;
+               if (max > count)
+                       max = count;
+               folderTotalSize = 0;
+
+               if (sort && files != null && files.size() != 0) {
+                       clearLabels();
+                       clearSelectedRows();
+
+                       Collections.sort(files, new Comparator<FileResource>() {
+
+                               @Override
+                               public int compare(FileResource arg0, FileResource arg1) {
+                                       AbstractImagePrototype descPrototype = AbstractImagePrototype.create(images.desc());
+                                       AbstractImagePrototype ascPrototype = AbstractImagePrototype.create(images.asc());
+                                       if (sortingType)
+                                               if (sortingProperty.equals("version")) {
+                                                       versionLabel.setHTML("Version&nbsp;" + descPrototype.getHTML());
+                                                       return arg0.getVersion().compareTo(arg1.getVersion());
+                                               } else if (sortingProperty.equals("owner")) {
+                                                       ownerLabel.setHTML("Owner&nbsp;" + descPrototype.getHTML());
+                                                       return arg0.getOwner().compareTo(arg1.getOwner());
+                                               } else if (sortingProperty.equals("date")) {
+                                                       dateLabel.setHTML("Last modified&nbsp;" + descPrototype.getHTML());
+                                                       return arg0.getModificationDate().compareTo(arg1.getModificationDate());
+                                               } else if (sortingProperty.equals("size")) {
+                                                       sizeLabel.setHTML("Size&nbsp;" + descPrototype.getHTML());
+                                                       return arg0.getContentLength().compareTo(arg1.getContentLength());
+                                               } else if (sortingProperty.equals("name")) {
+                                                       nameLabel.setHTML("Name&nbsp;" + descPrototype.getHTML());
+                                                       return arg0.getName().compareTo(arg1.getName());
+                                               } else if (sortingProperty.equals("path")) {
+                                                       pathLabel.setHTML("Path&nbsp;" + descPrototype.getHTML());
+                                                       return arg0.getUri().compareTo(arg1.getUri());
+                                               } else {
+                                                       nameLabel.setHTML("Name&nbsp;" + descPrototype.getHTML());
+                                                       return arg0.getName().compareTo(arg1.getName());
+                                               }
+                                       else if (sortingProperty.equals("version")) {
+                                               versionLabel.setHTML("Version&nbsp;" + ascPrototype.getHTML());
+                                               return arg1.getVersion().compareTo(arg0.getVersion());
+                                       } else if (sortingProperty.equals("owner")) {
+                                               ownerLabel.setHTML("Owner&nbsp;" + ascPrototype.getHTML());
+                                               return arg1.getOwner().compareTo(arg0.getOwner());
+                                       } else if (sortingProperty.equals("date")) {
+                                               dateLabel.setHTML("Last modified&nbsp;" + ascPrototype.getHTML());
+                                               return arg1.getModificationDate().compareTo(arg0.getModificationDate());
+                                       } else if (sortingProperty.equals("size")) {
+                                               sizeLabel.setHTML("Size&nbsp;" + ascPrototype.getHTML());
+                                               return arg1.getContentLength().compareTo(arg0.getContentLength());
+                                       } else if (sortingProperty.equals("name")) {
+                                               nameLabel.setHTML("Name&nbsp;" + ascPrototype.getHTML());
+                                               return arg1.getName().compareTo(arg0.getName());
+                                       } else if (sortingProperty.equals("path")) {
+                                               pathLabel.setHTML("Path&nbsp;" + ascPrototype.getHTML());
+                                               return arg1.getUri().compareTo(arg0.getUri());
+                                       } else {
+                                               nameLabel.setHTML("Name&nbsp;" + ascPrototype.getHTML());
+                                               return arg1.getName().compareTo(arg0.getName());
+                                       }
+                               }
+
+                       });
+
+               }
+               // Show the selected files.
+               int i = 1;
+               for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
+                       // Don't read past the end.
+                       // if (i > folderFileCount)
+                       // break;
+                       if (startIndex + i > folderFileCount)
+                               break;
+                       // Add a new row to the table, then set each of its columns to the
+                       // proper values.
+                       table.setWidget(i, 0, AbstractImagePrototype.create(images.document()).createImage());
+                       FileResource fileHeader = files.get(startIndex + i - 1);
+                       table.getRowFormatter().addStyleName(i, "gss-fileRow");
+                       table.setHTML(i, 1, fileHeader.getName());
+                       table.setText(i, 2, fileHeader.getOwner());
+                       table.setText(i, 3, fileHeader.getPath());
+                       table.setText(i, 4, String.valueOf(fileHeader.getVersion()));
+                       table.setText(i, 5, String.valueOf(fileHeader.getFileSizeAsString()));
+                       final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
+                       table.setText(i, 6, formatter.format(fileHeader.getModificationDate()));
+                       folderTotalSize += fileHeader.getContentLength();
+               }
+
+               // Clear any remaining slots.
+               for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
+                       table.setHTML(i, 0, "&nbsp;");
+                       table.setHTML(i, 1, "&nbsp;");
+                       table.setHTML(i, 2, "&nbsp;");
+                       table.setHTML(i, 3, "&nbsp;");
+                       table.setHTML(i, 4, "&nbsp;");
+                       table.setHTML(i, 5, "&nbsp;");
+                       table.setHTML(i, 6, "&nbsp;");
+                       table.setHTML(i, 7, "&nbsp;");
+               }
+
+               if (folderFileCount == 0) {
+                       showingStats = "no files";
+                       prevButton.setVisible(false);
+                       nextButton.setVisible(false);
+               } else if (folderFileCount < GSS.VISIBLE_FILE_COUNT) {
+                       if (folderFileCount == 1)
+                               showingStats = "1 file";
+                       else
+                               showingStats = folderFileCount + " files";
+                       showingStats += " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
+                       prevButton.setVisible(false);
+                       nextButton.setVisible(false);
+               } else {
+                       showingStats = "" + (startIndex + 1) + " - " + max + " of " + count + " files" + " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
+                       prevButton.setVisible(startIndex != 0);
+                       nextButton.setVisible(startIndex + GSS.VISIBLE_FILE_COUNT < count);
+               }
+               updateCurrentlyShowingStats();
+       }
+
+       /**
+        *  update status panel with currently showing file stats
+        */
+       public void updateCurrentlyShowingStats() {
+               GSS.get().getStatusPanel().updateCurrentlyShowing(showingStats);
+       }
+
+       /**
+        * Adjust the height of the table by adding and removing rows as necessary.
+        *
+        * @param newHeight the new height to reach
+        */
+       void resizeTableHeight(final int newHeight) {
+               GWT.log("Panel: " + newHeight + ", parent: " + table.getParent().getOffsetHeight(), null);
+               // Fill the rest with empty slots.
+               if (newHeight > table.getOffsetHeight())
+                       while (newHeight > table.getOffsetHeight()) {
+                               // table.setHTML(table.getRowCount(), 5, "&nbsp;");
+                               table.resizeRows(table.getRowCount() + 1);
+                               GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);
+                       }
+               else
+                       while (newHeight < table.getOffsetHeight()) {
+                               // table.setHTML(table.getRowCount(), 5, "&nbsp;");
+                               table.resizeRows(table.getRowCount() - 1);
+                               GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);
+                       }
+       }
+
+       /**
+        * Update the file cache with data from the server.
+        */
+       public void updateFileCache(String query) {
+               final GSS app = GSS.get();
+               clearSelectedRows();
+               clearLabels();
+               startIndex = 0;
+               app.showLoadingIndicator();
+               if (query == null || query.trim().equals("")) {
+                       searchResults.setHTML("You must specify a query.");
+                       setFiles(new ArrayList());
+                       update(true);
+                       app.hideLoadingIndicator();
+               } else if (!GSS.isValidResourceName(query)) {
+                       searchResults.setHTML("The query was invalid. Try to use words that appear in the file's name, contents or tags.");
+                       setFiles(new ArrayList());
+                       update(true);
+                       app.hideLoadingIndicator();
+               } else{
+                       searchResults.setHTML("Search results for " + query);
+
+                       GetCommand<SearchResource> eg = new GetCommand<SearchResource>(SearchResource.class,
+                                               app.getApiPath() + "search/" + URL.encodeComponent(query), null) {
+
+                               @Override
+                               public void onComplete() {
+                                       SearchResource s = getResult();
+                                       setFiles(s.getFiles());
+                                       update(true);
+                               }
+
+                               @Override
+                               public void onError(Throwable t) {
+                                       if(t instanceof RestException)
+                                               app.displayError("Unable to perform search:"+((RestException)t).getHttpStatusText());
+                                       else
+                                               app.displayError("System error performing search:"+t.getMessage());
+                                       updateFileCache("");
+                               }
+
+                       };
+                       DeferredCommand.addCommand(eg);
+               }
+       }
+
+       /**
+        * Fill the file cache with data.
+        *
+        * @param _files
+        * @param filePaths the files to set
+        */
+       private void setFiles(List<FileResource> _files) {
+               files = _files;
+               Collections.sort(files, new Comparator<FileResource>() {
+
+                       @Override
+                       public int compare(FileResource arg0, FileResource arg1) {
+                               return arg0.getName().compareTo(arg1.getName());
+                       }
+
+               });
+               folderFileCount = files.size();
+               GWT.log("File count:" + folderFileCount, null);
+       }
+
+       private void sortFiles(final String sortProperty) {
+               if (sortProperty.equals(sortingProperty))
+                       sortingType = !sortingType;
+               else {
+                       sortingProperty = sortProperty;
+                       sortingType = true;
+               }
+               update(true);
+       }
+
+       private void clearLabels() {
+               nameLabel.setText("Name");
+               versionLabel.setText("Version");
+               sizeLabel.setText("Size");
+               dateLabel.setText("Last modified");
+               ownerLabel.setText("Owner");
+               pathLabel.setText("Path");
+       }
+
+       /**
+        * Retrieve the table.
+        *
+        * @return the table
+        */
+       Grid getTable() {
+               return table;
+       }
+
+       /**
+        * Does the list contains the requested filename
+        *
+        * @param fileName
+        * @return true/false
+        */
+       public boolean contains(String fileName) {
+               for (int i = 0; i < files.size(); i++)
+                       if (files.get(i).getName().equals(fileName))
+                               return true;
+               return false;
+       }
+
+       public void clearSelectedRows() {
+               for (int r : selectedRows) {
+                       int row = r - startIndex;
+                       styleRow(row, false);
+                       table.setWidget(row + 1, 0, AbstractImagePrototype.create(images.document()).createImage());
+               }
+               selectedRows.clear();
+               Object sel = GSS.get().getCurrentSelection();
+               if (sel instanceof FileResource || sel instanceof List)
+                       GSS.get().setCurrentSelection(null);
+       }
+
+       public static native void preventIESelection() /*-{
+            $doc.body.onselectstart = function () { return false; };
+        }-*/;
+
+       public static native void enableIESelection() /*-{
+        if ($doc.body.onselectstart != null)
+            $doc.body.onselectstart = null;
+        }-*/;
+
+       public void selectAllRows() {
+               clearSelectedRows();
+               int count = folderFileCount;
+               if (count == 0)
+                       return;
+               int max = startIndex + GSS.VISIBLE_FILE_COUNT;
+               if (max > count)
+                       max = count;
+               int i = 1;
+               for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
+                       // Don't read past the end.
+                       // if (i > folderFileCount)
+                       // break;
+                       if (startIndex + i > folderFileCount)
+                               break;
+                       selectedRows.add(startIndex + i - 1);
+                       styleRow(i - 1, true);
+               }
+               GSS.get().setCurrentSelection(getSelectedFiles());
+               //contextMenu.setFiles(getSelectedFiles());
+               //table.setWidget(i - 1, 0, contextMenu);
+       }
+
+}