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