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