Fix of Revision: ec7b8d0b2c after code review. Added a check condition before remov...
[pithos] / src / gr / ebs / gss / client / SearchResults.java
1 /*
2  * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
3  *
4  * This file is part of GSS.
5  *
6  * GSS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 package gr.ebs.gss.client;
20
21 import gr.ebs.gss.client.dnd.DnDSimpleFocusPanel;
22 import gr.ebs.gss.client.rest.GetCommand;
23 import gr.ebs.gss.client.rest.RestCommand;
24 import gr.ebs.gss.client.rest.RestException;
25 import gr.ebs.gss.client.rest.resource.FileResource;
26 import gr.ebs.gss.client.rest.resource.SearchResource;
27 import gr.ebs.gss.client.rest.resource.UserResource;
28
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.List;
33
34 import com.google.gwt.core.client.GWT;
35 import com.google.gwt.dom.client.NativeEvent;
36 import com.google.gwt.event.dom.client.ClickEvent;
37 import com.google.gwt.event.dom.client.ClickHandler;
38 import com.google.gwt.http.client.URL;
39 import com.google.gwt.i18n.client.DateTimeFormat;
40 import com.google.gwt.resources.client.ClientBundle;
41 import com.google.gwt.resources.client.ImageResource;
42 import com.google.gwt.user.client.DOM;
43 import com.google.gwt.user.client.DeferredCommand;
44 import com.google.gwt.user.client.Event;
45 import com.google.gwt.user.client.IncrementalCommand;
46 import com.google.gwt.user.client.Window;
47 import com.google.gwt.user.client.ui.AbstractImagePrototype;
48 import com.google.gwt.user.client.ui.Composite;
49 import com.google.gwt.user.client.ui.Grid;
50 import com.google.gwt.user.client.ui.HTML;
51 import com.google.gwt.user.client.ui.HTMLTable.Cell;
52 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
53 import com.google.gwt.user.client.ui.HorizontalPanel;
54 import com.google.gwt.user.client.ui.VerticalPanel;
55
56 /**
57  * A composite that displays a list of search results for a particular query on
58  * files.
59  */
60 public class SearchResults extends Composite implements  ClickHandler {
61
62         private HTML prevButton = new HTML("<a href='javascript:;'>&lt; Previous</a>", true);
63
64         private HTML nextButton = new HTML("<a href='javascript:;'>Next &gt;</a>", true);
65
66         private String showingStats = "";
67
68         private int startIndex = 0;
69
70         /**
71          * A constant that denotes the completion of an IncrementalCommand.
72          */
73         public static final boolean DONE = false;
74
75         private boolean clickControl = false;
76
77         private boolean clickShift = false;
78
79         private int firstShift = -1;
80
81         private ArrayList<Integer> selectedRows = new ArrayList<Integer>();
82
83         /**
84          * The context menu for the selected file.
85          */
86         final DnDSimpleFocusPanel contextMenu;
87
88         /**
89          * Specifies that the images available for this composite will be the ones
90          * available in FileContextMenu.
91          */
92         public interface Images extends ClientBundle,FileContextMenu.Images, Folders.Images {
93
94                 @Source("gr/ebs/gss/resources/blank.gif")
95                 ImageResource blank();
96
97                 @Source("gr/ebs/gss/resources/asc.png")
98                 ImageResource asc();
99
100                 @Source("gr/ebs/gss/resources/desc.png")
101                 ImageResource desc();
102         }
103
104         /**
105          * A label with the number of files in this folder.
106          */
107         private HTML countLabel = new HTML();
108
109         /**
110          * The table widget with the file list.
111          */
112         private FileTable table;
113
114         /**
115          * The navigation bar for paginating the results.
116          */
117         private HorizontalPanel navBar = new HorizontalPanel();
118
119         /**
120          * The number of files in the search results
121          */
122         private int folderFileCount;
123
124         /**
125          * Total search results size
126          */
127         private long folderTotalSize;
128
129         /**
130          * A cache of the files in the list.
131          */
132         private List<FileResource> files;
133
134         /**
135          * The widget's image bundle.
136          */
137         private final Images images;
138
139         private String sortingProperty = "name";
140
141         private boolean sortingType = true;
142
143         private HTML nameLabel;
144
145         private HTML versionLabel;
146
147         private HTML sizeLabel;
148
149         private HTML dateLabel;
150
151         private HTML ownerLabel;
152
153         private HTML pathLabel;
154
155         private HTML searchResults = new HTML("Results for search:");
156
157         /**
158          * Construct the file list widget. This entails setting up the widget
159          * layout, fetching the number of files in the current folder from the
160          * server and filling the local file cache of displayed files with data from
161          * the server, as well.
162          *
163          * @param _images
164          */
165         public SearchResults(final Images _images) {
166                 images = _images;
167                 final GSS app = GSS.get();
168                 table = new FileTable(GSS.VISIBLE_FILE_COUNT + 1, 8) {
169
170                         @Override
171                         public void onBrowserEvent(Event event) {
172                                 if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && DOM.eventGetButton(event) == NativeEvent.BUTTON_RIGHT){
173                                         if (DOM.eventGetCtrlKey(event))
174                                                 clickControl = true;
175                                         else
176                                                 clickControl = false;
177                                         if (DOM.eventGetShiftKey(event)) {
178                                                 clickShift = true;
179                                                 if (selectedRows.size() == 1)
180                                                         firstShift = selectedRows.get(0) - startIndex;
181                                                 //event.preventDefault();
182                                         } else {
183                                                 clickShift = false;
184                                                 firstShift = -1;
185                                                 //event.preventDefault();
186                                         }
187                                         int ri = table.getRowForEvent2(event);
188                                         if(ri != -1)
189                                                 if(!selectedRows.contains(ri-1))
190                                                         onRowClicked(ri, false);
191                                 }
192
193                                 if (files == null || files.size() == 0) {
194                                         if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() == 0) {
195                                                 FileContextMenu fm = new FileContextMenu(images, false, true);
196                                                 fm.onEmptyEvent(event);
197                                         }
198                                         return;
199                                 }
200                                 if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() != 0) {
201                                         FileContextMenu fm = new FileContextMenu(images, false, false);
202                                         fm.onEvent(event);
203                                 } else if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && selectedRows.size() == 0) {
204                                         FileContextMenu fm = new FileContextMenu(images, false, true);
205                                         fm.onEmptyEvent(event);
206                                 } else if (DOM.eventGetType(event) == Event.ONDBLCLICK)
207                                         if (getSelectedFiles().size() == 1) {
208                                                 FileResource file = getSelectedFiles().get(0);
209                                                 String dateString = RestCommand.getDate();
210                                                 String resource = file.getUri().substring(app.getApiPath().length() - 1, file.getUri().length());
211                                                 String sig = app.getCurrentUserResource().getUsername() + " " +
212                                                                 RestCommand.calculateSig("GET", dateString, resource,
213                                                                 RestCommand.base64decode(app.getToken()));
214                                                 Window.open(file.getUri() + "?Authorization=" + URL.encodeComponent(sig) + "&Date=" + URL.encodeComponent(dateString), "_blank", "");
215                                                 event.preventDefault();
216                                                 return;
217                                         }
218                                 if (DOM.eventGetType(event) == Event.ONCLICK) {
219                                         if (DOM.eventGetCtrlKey(event))
220                                                 clickControl = true;
221                                         else
222                                                 clickControl = false;
223                                         if (DOM.eventGetShiftKey(event)) {
224                                                 clickShift = true;
225                                                 if (selectedRows.size() == 1)
226                                                         firstShift = selectedRows.get(0) - startIndex;
227                                                 //event.preventDefault();
228                                         } else {
229                                                 clickShift = false;
230                                                 firstShift = -1;
231                                                 //event.preventDefault();
232                                         }
233                                 }
234                                 super.onBrowserEvent(event);
235                         }
236                 };
237                 prevButton.addClickHandler(this);
238                 nextButton.addClickHandler(this);
239
240                 contextMenu = new DnDSimpleFocusPanel(new HTML(AbstractImagePrototype.create(images.fileContextMenu()).getHTML()));
241                 contextMenu.addClickHandler(new FileContextMenu(images, false, false));
242                 app.getDragController().makeDraggable(contextMenu);
243
244                 // Setup the table.
245                 table.setCellSpacing(0);
246                 table.setCellPadding(2);
247                 table.setWidth("100%");
248
249                 // Hook up events.
250                 table.addClickHandler(new ClickHandler() {
251
252                         @Override
253                         public void onClick(ClickEvent event) {
254                                 Cell cell = table.getCellForEvent(event);
255                                 onRowClicked(cell.getRowIndex(),true);
256                         }
257                 });
258
259                 // Create the 'navigation' bar at the upper-right.
260                 HorizontalPanel innerNavBar = new HorizontalPanel();
261                 innerNavBar.setStyleName("gss-ListNavBar");
262                 innerNavBar.setSpacing(8);
263                 innerNavBar.add(prevButton);
264                 innerNavBar.add(countLabel);
265                 innerNavBar.add(nextButton);
266                 navBar.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
267                 navBar.add(innerNavBar);
268                 navBar.setWidth("100%");
269                 VerticalPanel vp = new VerticalPanel();
270                 vp.add(searchResults);
271                 searchResults.addStyleName("gss-searchLabel");
272                 vp.add(table);
273                 initWidget(vp);
274                 table.setStyleName("gss-List");
275                 initTable();
276                 DeferredCommand.addCommand(new IncrementalCommand() {
277
278                         @Override
279                         public boolean execute() {
280                                 return fetchRootFolder();
281                         }
282                 });
283                 table.sinkEvents(Event.ONCONTEXTMENU);
284                 table.sinkEvents(Event.ONMOUSEUP);
285                 table.sinkEvents(Event.ONMOUSEDOWN);
286                 table.sinkEvents(Event.ONCLICK);
287                 table.sinkEvents(Event.ONKEYDOWN);
288                 table.sinkEvents(Event.ONDBLCLICK);
289                 preventIESelection();
290         }
291
292         @Override
293         public void onClick(ClickEvent event) {
294                 if (event.getSource() == nextButton) {
295                         // Move forward a page.
296                         clearSelectedRows();
297                         startIndex += GSS.VISIBLE_FILE_COUNT;
298                         if (startIndex >= folderFileCount)
299                                 startIndex -= GSS.VISIBLE_FILE_COUNT;
300                         else
301                                 update(false);
302                 } else if (event.getSource() == prevButton) {
303                         clearSelectedRows();
304                         // Move back a page.
305                         startIndex -= GSS.VISIBLE_FILE_COUNT;
306                         if (startIndex < 0)
307                                 startIndex = 0;
308                         else
309                                 update(false);
310                 }
311         }
312
313         /**
314          * Retrieve the root folder for the current user.
315          *
316          * @return true if the retrieval was successful
317          */
318         protected boolean fetchRootFolder() {
319                 UserResource user = GSS.get().getCurrentUserResource();
320                 if (user == null)
321                         return !DONE;
322                 updateFileCache("");
323                 return DONE;
324         }
325
326         public void onRowClicked(int row, boolean toggleSelection) {
327                 // Select the row that was clicked (-1 to account for header row).
328                 if (row > folderFileCount)
329                         return;
330                 if (clickShift) {
331                         GWT.log("ROW is:" + row + " fs:" + firstShift, null);
332                         if (firstShift == -1)
333                                 firstShift = row;
334                         else if (row > firstShift) {
335                                 clearSelectedRows();
336                                 for (int i = firstShift; i < row; i++) {
337                                         selectedRows.add(startIndex + i);
338                                         styleRow(i, true);
339                                 }
340                                 GSS.get().setCurrentSelection(getSelectedFiles());
341                                 //contextMenu.setFiles(getSelectedFiles());
342                                 table.setWidget(row, 0, contextMenu);
343                         } else if (row != -1 && row == firstShift) {
344                                 selectedRows.add(row);
345                                 selectedRows.add(row - 1);
346                                 styleRow(row, true);
347                                 styleRow(row - 1, true);
348                         } else if (row < firstShift) {
349                                 GWT.log("ROW is:" + row + " fs:" + firstShift, null);
350                                 clearSelectedRows();
351
352                                 for (int i = firstShift; i >= row - 1; i--) {
353                                         selectedRows.add(startIndex + i);
354                                         styleRow(i, true);
355                                 }
356                                 GSS.get().setCurrentSelection(getSelectedFiles());
357                                 table.setWidget(row, 0, contextMenu);
358                                 //contextMenu.setFiles(getSelectedFiles());
359                         }
360
361                 } else if (row > 0)
362                         selectRow(row - 1, toggleSelection);
363
364         }
365
366         /**
367          * Initializes the table so that it contains enough rows for a full page of
368          * files.
369          */
370         private void initTable() {
371
372                 nameLabel = new HTML("Name");
373                 nameLabel.addClickHandler(new ClickHandler() {
374                         @Override
375                         public void onClick(ClickEvent event) {
376                                 sortFiles("name");
377                         }
378
379                 });
380                 versionLabel = new HTML("Version");
381                 versionLabel.addClickHandler(new ClickHandler() {
382                         @Override
383                         public void onClick(ClickEvent event) {
384                                 sortFiles("version");
385                         }
386
387                 });
388                 sizeLabel = new HTML("Size");
389                 sizeLabel.addClickHandler(new ClickHandler() {
390                         @Override
391                         public void onClick(ClickEvent event) {
392                                 sortFiles("size");
393                         }
394
395                 });
396                 dateLabel = new HTML("Last modified");
397                 dateLabel.addClickHandler(new ClickHandler() {
398                         @Override
399                         public void onClick(ClickEvent event) {
400                                 sortFiles("date");
401                         }
402
403                 });
404                 ownerLabel = new HTML("Owner");
405                 ownerLabel.addClickHandler(new ClickHandler() {
406                         @Override
407                         public void onClick(ClickEvent event) {
408                                 sortFiles("owner");
409                         }
410
411                 });
412
413                 pathLabel = new HTML("Path");
414                 pathLabel.addClickHandler(new ClickHandler() {
415                         @Override
416                         public void onClick(ClickEvent event) {
417                                 sortFiles("path");
418                         }
419
420                 });
421                 // Create the header row.
422                 table.setText(0, 0, "");
423                 // table.setText(0, 1, "Name");
424                 table.setWidget(0, 1, nameLabel);
425                 table.setWidget(0, 2, ownerLabel);
426                 // table.setText(0, 3, "Version");
427                 table.setWidget(0, 3, pathLabel);
428                 table.setWidget(0, 4, versionLabel);
429                 // table.setText(0, 4, "Size");
430                 table.setWidget(0, 5, sizeLabel);
431                 // table.setText(0, 5, "Last modified");
432                 table.setWidget(0, 6, dateLabel);
433                 table.setWidget(0, 7, navBar);
434                 table.getRowFormatter().setStyleName(0, "gss-ListHeader");
435
436                 // Initialize the rest of the rows.
437                 for (int i = 1; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
438                         table.setText(i, 0, "");
439                         table.setText(i, 1, "");
440                         table.setText(i, 2, "");
441                         table.setText(i, 3, "");
442                         table.setText(i, 4, "");
443                         table.setText(i, 5, "");
444                         table.setText(i, 6, "");
445                         table.getCellFormatter().setWordWrap(i, 0, false);
446                         table.getCellFormatter().setWordWrap(i, 1, false);
447                         table.getCellFormatter().setWordWrap(i, 2, false);
448                         table.getCellFormatter().setWordWrap(i, 3, false);
449                         table.getCellFormatter().setWordWrap(i, 4, false);
450                         table.getCellFormatter().setWordWrap(i, 5, false);
451                         table.getCellFormatter().setWordWrap(i, 6, false);
452                         table.getCellFormatter().setHorizontalAlignment(i, 4, HasHorizontalAlignment.ALIGN_CENTER);
453                 }
454                 prevButton.setVisible(false);
455                 nextButton.setVisible(false);
456         }
457
458         /**
459          * Selects the given row (relative to the current page).
460          *
461          * @param row the row to be selected
462          */
463         private void selectRow(final int row, boolean toggleSelection) {
464                 if (row < folderFileCount) {
465                         if (clickControl)
466                                 if (selectedRows.contains(row) && toggleSelection) {
467                                         int i = selectedRows.indexOf(startIndex + row);
468                                         selectedRows.remove(i);
469                                         styleRow(row, false);
470                                 } else {
471                                         for (int r : selectedRows) {
472                                                 int prow = r - startIndex;
473                                                 table.setWidget(prow + 1, 0, AbstractImagePrototype.create(images.document()).createImage());
474                                         }
475                                         selectedRows.add(startIndex + row);
476                                         styleRow(row, true);
477                                 }
478                         else {
479                                 clearSelectedRows();
480                                 selectedRows.add(startIndex + row);
481                                 styleRow(row, true);
482                         }
483                         if (selectedRows.size() == 1)
484                                 GSS.get().setCurrentSelection(files.get(selectedRows.get(0)));
485                         else
486                                 GSS.get().setCurrentSelection(getSelectedFiles());
487                         //contextMenu.setFiles(getSelectedFiles());
488                         table.setWidget(row + 1, 0, contextMenu);
489                 }
490         }
491
492         public List<FileResource> getSelectedFiles() {
493                 List<FileResource> result = new ArrayList();
494                 for (int i : selectedRows)
495                         result.add(files.get(i));
496                 return result;
497         }
498
499         /**
500          * Make the specified row look like selected or not, according to the
501          * <code>selected</code> flag.
502          *
503          * @param row
504          * @param selected
505          */
506         void styleRow(final int row, final boolean selected) {
507                 if (row != -1 && row >= 0)
508                         if (selected)
509                                 table.getRowFormatter().addStyleName(row + 1, "gss-SelectedRow");
510                         else
511                                 table.getRowFormatter().removeStyleName(row + 1, "gss-SelectedRow");
512         }
513
514         /**
515          * Update the display of the file list.
516          */
517         void update(boolean sort) {
518                 int count = folderFileCount;
519                 int max = startIndex + GSS.VISIBLE_FILE_COUNT;
520                 if (max > count)
521                         max = count;
522                 folderTotalSize = 0;
523
524                 if (sort && files != null && files.size() != 0) {
525                         clearLabels();
526                         clearSelectedRows();
527
528                         Collections.sort(files, new Comparator<FileResource>() {
529
530                                 @Override
531                                 public int compare(FileResource arg0, FileResource arg1) {
532                                         AbstractImagePrototype descPrototype = AbstractImagePrototype.create(images.desc());
533                                         AbstractImagePrototype ascPrototype = AbstractImagePrototype.create(images.asc());
534                                         if (sortingType)
535                                                 if (sortingProperty.equals("version")) {
536                                                         versionLabel.setHTML("Version&nbsp;" + descPrototype.getHTML());
537                                                         return arg0.getVersion().compareTo(arg1.getVersion());
538                                                 } else if (sortingProperty.equals("owner")) {
539                                                         ownerLabel.setHTML("Owner&nbsp;" + descPrototype.getHTML());
540                                                         return arg0.getOwner().compareTo(arg1.getOwner());
541                                                 } else if (sortingProperty.equals("date")) {
542                                                         dateLabel.setHTML("Last modified&nbsp;" + descPrototype.getHTML());
543                                                         return arg0.getModificationDate().compareTo(arg1.getModificationDate());
544                                                 } else if (sortingProperty.equals("size")) {
545                                                         sizeLabel.setHTML("Size&nbsp;" + descPrototype.getHTML());
546                                                         return arg0.getContentLength().compareTo(arg1.getContentLength());
547                                                 } else if (sortingProperty.equals("name")) {
548                                                         nameLabel.setHTML("Name&nbsp;" + descPrototype.getHTML());
549                                                         return arg0.getName().compareTo(arg1.getName());
550                                                 } else if (sortingProperty.equals("path")) {
551                                                         pathLabel.setHTML("Path&nbsp;" + descPrototype.getHTML());
552                                                         return arg0.getUri().compareTo(arg1.getUri());
553                                                 } else {
554                                                         nameLabel.setHTML("Name&nbsp;" + descPrototype.getHTML());
555                                                         return arg0.getName().compareTo(arg1.getName());
556                                                 }
557                                         else if (sortingProperty.equals("version")) {
558                                                 versionLabel.setHTML("Version&nbsp;" + ascPrototype.getHTML());
559                                                 return arg1.getVersion().compareTo(arg0.getVersion());
560                                         } else if (sortingProperty.equals("owner")) {
561                                                 ownerLabel.setHTML("Owner&nbsp;" + ascPrototype.getHTML());
562                                                 return arg1.getOwner().compareTo(arg0.getOwner());
563                                         } else if (sortingProperty.equals("date")) {
564                                                 dateLabel.setHTML("Last modified&nbsp;" + ascPrototype.getHTML());
565                                                 return arg1.getModificationDate().compareTo(arg0.getModificationDate());
566                                         } else if (sortingProperty.equals("size")) {
567                                                 sizeLabel.setHTML("Size&nbsp;" + ascPrototype.getHTML());
568                                                 return arg1.getContentLength().compareTo(arg0.getContentLength());
569                                         } else if (sortingProperty.equals("name")) {
570                                                 nameLabel.setHTML("Name&nbsp;" + ascPrototype.getHTML());
571                                                 return arg1.getName().compareTo(arg0.getName());
572                                         } else if (sortingProperty.equals("path")) {
573                                                 pathLabel.setHTML("Path&nbsp;" + ascPrototype.getHTML());
574                                                 return arg1.getUri().compareTo(arg0.getUri());
575                                         } else {
576                                                 nameLabel.setHTML("Name&nbsp;" + ascPrototype.getHTML());
577                                                 return arg1.getName().compareTo(arg0.getName());
578                                         }
579                                 }
580
581                         });
582
583                 }
584                 // Show the selected files.
585                 int i = 1;
586                 for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
587                         // Don't read past the end.
588                         // if (i > folderFileCount)
589                         // break;
590                         if (startIndex + i > folderFileCount)
591                                 break;
592                         // Add a new row to the table, then set each of its columns to the
593                         // proper values.
594                         table.setWidget(i, 0, AbstractImagePrototype.create(images.document()).createImage());
595                         FileResource fileHeader = files.get(startIndex + i - 1);
596                         table.getRowFormatter().addStyleName(i, "gss-fileRow");
597                         table.setHTML(i, 1, fileHeader.getName());
598                         table.setText(i, 2, fileHeader.getOwner());
599                         table.setText(i, 3, fileHeader.getPath());
600                         table.setText(i, 4, String.valueOf(fileHeader.getVersion()));
601                         table.setText(i, 5, String.valueOf(fileHeader.getFileSizeAsString()));
602                         final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
603                         table.setText(i, 6, formatter.format(fileHeader.getModificationDate()));
604                         folderTotalSize += fileHeader.getContentLength();
605                 }
606
607                 // Clear any remaining slots.
608                 for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
609                         table.setHTML(i, 0, "&nbsp;");
610                         table.setHTML(i, 1, "&nbsp;");
611                         table.setHTML(i, 2, "&nbsp;");
612                         table.setHTML(i, 3, "&nbsp;");
613                         table.setHTML(i, 4, "&nbsp;");
614                         table.setHTML(i, 5, "&nbsp;");
615                         table.setHTML(i, 6, "&nbsp;");
616                         table.setHTML(i, 7, "&nbsp;");
617                 }
618
619                 if (folderFileCount == 0) {
620                         showingStats = "no files";
621                         prevButton.setVisible(false);
622                         nextButton.setVisible(false);
623                 } else if (folderFileCount < GSS.VISIBLE_FILE_COUNT) {
624                         if (folderFileCount == 1)
625                                 showingStats = "1 file";
626                         else
627                                 showingStats = folderFileCount + " files";
628                         showingStats += " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
629                         prevButton.setVisible(false);
630                         nextButton.setVisible(false);
631                 } else {
632                         showingStats = "" + (startIndex + 1) + " - " + max + " of " + count + " files" + " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
633                         prevButton.setVisible(startIndex != 0);
634                         nextButton.setVisible(startIndex + GSS.VISIBLE_FILE_COUNT < count);
635                 }
636                 updateCurrentlyShowingStats();
637         }
638
639         /**
640          *  update status panel with currently showing file stats
641          */
642         public void updateCurrentlyShowingStats() {
643                 GSS.get().getStatusPanel().updateCurrentlyShowing(showingStats);
644         }
645
646         /**
647          * Adjust the height of the table by adding and removing rows as necessary.
648          *
649          * @param newHeight the new height to reach
650          */
651         void resizeTableHeight(final int newHeight) {
652                 GWT.log("Panel: " + newHeight + ", parent: " + table.getParent().getOffsetHeight(), null);
653                 // Fill the rest with empty slots.
654                 if (newHeight > table.getOffsetHeight())
655                         while (newHeight > table.getOffsetHeight()) {
656                                 // table.setHTML(table.getRowCount(), 5, "&nbsp;");
657                                 table.resizeRows(table.getRowCount() + 1);
658                                 GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);
659                         }
660                 else
661                         while (newHeight < table.getOffsetHeight()) {
662                                 // table.setHTML(table.getRowCount(), 5, "&nbsp;");
663                                 table.resizeRows(table.getRowCount() - 1);
664                                 GWT.log("Table: " + table.getOffsetHeight() + ", rows: " + table.getRowCount(), null);
665                         }
666         }
667
668         /**
669          * Update the file cache with data from the server.
670          */
671         public void updateFileCache(String query) {
672                 final GSS app = GSS.get();
673                 clearSelectedRows();
674                 clearLabels();
675                 startIndex = 0;
676                 app.showLoadingIndicator();
677                 if (query == null || query.trim().equals("")) {
678                         searchResults.setHTML("You must specify a query.");
679                         setFiles(new ArrayList());
680                         update(true);
681                         app.hideLoadingIndicator();
682                 } else if (!GSS.isValidResourceName(query)) {
683                         searchResults.setHTML("The query was invalid. Try to use words that appear in the file's name, contents or tags.");
684                         setFiles(new ArrayList());
685                         update(true);
686                         app.hideLoadingIndicator();
687                 } else{
688                         searchResults.setHTML("Search results for " + query);
689
690                         GetCommand<SearchResource> eg = new GetCommand<SearchResource>(SearchResource.class,
691                                                 app.getApiPath() + "search/" + URL.encodeComponent(query), null) {
692
693                                 @Override
694                                 public void onComplete() {
695                                         SearchResource s = getResult();
696                                         setFiles(s.getFiles());
697                                         update(true);
698                                 }
699
700                                 @Override
701                                 public void onError(Throwable t) {
702                                         if(t instanceof RestException)
703                                                 app.displayError("Unable to perform search:"+((RestException)t).getHttpStatusText());
704                                         else
705                                                 app.displayError("System error performing search:"+t.getMessage());
706                                         updateFileCache("");
707                                 }
708
709                         };
710                         DeferredCommand.addCommand(eg);
711                 }
712         }
713
714         /**
715          * Fill the file cache with data.
716          *
717          * @param _files
718          * @param filePaths the files to set
719          */
720         private void setFiles(List<FileResource> _files) {
721                 files = _files;
722                 Collections.sort(files, new Comparator<FileResource>() {
723
724                         @Override
725                         public int compare(FileResource arg0, FileResource arg1) {
726                                 return arg0.getName().compareTo(arg1.getName());
727                         }
728
729                 });
730                 folderFileCount = files.size();
731                 GWT.log("File count:" + folderFileCount, null);
732         }
733
734         private void sortFiles(final String sortProperty) {
735                 if (sortProperty.equals(sortingProperty))
736                         sortingType = !sortingType;
737                 else {
738                         sortingProperty = sortProperty;
739                         sortingType = true;
740                 }
741                 update(true);
742         }
743
744         private void clearLabels() {
745                 nameLabel.setText("Name");
746                 versionLabel.setText("Version");
747                 sizeLabel.setText("Size");
748                 dateLabel.setText("Last modified");
749                 ownerLabel.setText("Owner");
750                 pathLabel.setText("Path");
751         }
752
753         /**
754          * Retrieve the table.
755          *
756          * @return the table
757          */
758         Grid getTable() {
759                 return table;
760         }
761
762         /**
763          * Does the list contains the requested filename
764          *
765          * @param fileName
766          * @return true/false
767          */
768         public boolean contains(String fileName) {
769                 for (int i = 0; i < files.size(); i++)
770                         if (files.get(i).getName().equals(fileName))
771                                 return true;
772                 return false;
773         }
774
775         public void clearSelectedRows() {
776                 for (int r : selectedRows) {
777                         int row = r - startIndex;
778                         styleRow(row, false);
779                         table.setWidget(row + 1, 0, AbstractImagePrototype.create(images.document()).createImage());
780                 }
781                 selectedRows.clear();
782                 Object sel = GSS.get().getCurrentSelection();
783                 if (sel instanceof FileResource || sel instanceof List)
784                         GSS.get().setCurrentSelection(null);
785         }
786
787         public static native void preventIESelection() /*-{
788              $doc.body.onselectstart = function () { return false; };
789          }-*/;
790
791         public static native void enableIESelection() /*-{
792          if ($doc.body.onselectstart != null)
793              $doc.body.onselectstart = null;
794          }-*/;
795
796         public void selectAllRows() {
797                 clearSelectedRows();
798                 int count = folderFileCount;
799                 if (count == 0)
800                         return;
801                 int max = startIndex + GSS.VISIBLE_FILE_COUNT;
802                 if (max > count)
803                         max = count;
804                 int i = 1;
805                 for (; i < GSS.VISIBLE_FILE_COUNT + 1; ++i) {
806                         // Don't read past the end.
807                         // if (i > folderFileCount)
808                         // break;
809                         if (startIndex + i > folderFileCount)
810                                 break;
811                         selectedRows.add(startIndex + i - 1);
812                         styleRow(i - 1, true);
813                 }
814                 GSS.get().setCurrentSelection(getSelectedFiles());
815                 //contextMenu.setFiles(getSelectedFiles());
816                 table.setWidget(i - 1, 0, contextMenu);
817         }
818
819 }