fix dnd bug, and use filelist.getSelectedFiles() on file drop
[pithos] / src / gr / ebs / gss / client / GSS.java
1 /*
2  * Copyright 2007, 2008, 2009, 2010 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.clipboard.Clipboard;
22 import gr.ebs.gss.client.commands.GetUserCommand;
23 import gr.ebs.gss.client.dnd.DnDFocusPanel;
24 import gr.ebs.gss.client.dnd.DnDSimpleFocusPanel;
25 import gr.ebs.gss.client.rest.GetCommand;
26 import gr.ebs.gss.client.rest.RestException;
27 import gr.ebs.gss.client.rest.resource.FileResource;
28 import gr.ebs.gss.client.rest.resource.FolderResource;
29 import gr.ebs.gss.client.rest.resource.TrashResource;
30 import gr.ebs.gss.client.rest.resource.UserResource;
31
32 import java.util.Arrays;
33 import java.util.Date;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37
38 import com.allen_sauer.gwt.dnd.client.DragContext;
39 import com.allen_sauer.gwt.dnd.client.PickupDragController;
40 import com.allen_sauer.gwt.dnd.client.VetoDragException;
41 import com.google.gwt.core.client.EntryPoint;
42 import com.google.gwt.core.client.GWT;
43 import com.google.gwt.event.logical.shared.ResizeEvent;
44 import com.google.gwt.event.logical.shared.ResizeHandler;
45 import com.google.gwt.event.logical.shared.SelectionEvent;
46 import com.google.gwt.event.logical.shared.SelectionHandler;
47 import com.google.gwt.event.logical.shared.ValueChangeEvent;
48 import com.google.gwt.event.logical.shared.ValueChangeHandler;
49 import com.google.gwt.i18n.client.DateTimeFormat;
50 import com.google.gwt.resources.client.ClientBundle;
51 import com.google.gwt.resources.client.ImageResource;
52 import com.google.gwt.user.client.Command;
53 import com.google.gwt.user.client.Cookies;
54 import com.google.gwt.user.client.DOM;
55 import com.google.gwt.user.client.DeferredCommand;
56 import com.google.gwt.user.client.History;
57 import com.google.gwt.user.client.Window;
58 import com.google.gwt.user.client.ui.AbsolutePanel;
59 import com.google.gwt.user.client.ui.AbstractImagePrototype;
60 import com.google.gwt.user.client.ui.DecoratedTabPanel;
61 import com.google.gwt.user.client.ui.DockPanel;
62 import com.google.gwt.user.client.ui.HTML;
63 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
64 import com.google.gwt.user.client.ui.HasVerticalAlignment;
65 import com.google.gwt.user.client.ui.HorizontalSplitPanel;
66 import com.google.gwt.user.client.ui.Label;
67 import com.google.gwt.user.client.ui.RootPanel;
68 import com.google.gwt.user.client.ui.TabPanel;
69 import com.google.gwt.user.client.ui.TreeItem;
70 import com.google.gwt.user.client.ui.VerticalPanel;
71 import com.google.gwt.user.client.ui.Widget;
72
73 /**
74  * Entry point classes define <code>onModuleLoad()</code>.
75  */
76 public class GSS implements EntryPoint, ResizeHandler {
77
78         /**
79          * A constant that denotes the completion of an IncrementalCommand.
80          */
81         public static final boolean DONE = false;
82
83         public static final int VISIBLE_FILE_COUNT = 100;
84
85         /**
86          * Instantiate an application-level image bundle. This object will provide
87          * programmatic access to all the images needed by widgets.
88          */
89         private static Images images = (Images) GWT.create(Images.class);
90
91         private GlassPanel glassPanel = new GlassPanel();
92
93         /**
94          * An aggregate image bundle that pulls together all the images for this
95          * application into a single bundle.
96          */
97         public interface Images extends ClientBundle, TopPanel.Images, StatusPanel.Images, FileMenu.Images, EditMenu.Images, SettingsMenu.Images, GroupMenu.Images, FilePropertiesDialog.Images, MessagePanel.Images, FileList.Images, SearchResults.Images, Search.Images, Groups.Images, Folders.Images {
98
99                 @Source("gr/ebs/gss/resources/document.png")
100                 ImageResource folders();
101
102                 @Source("gr/ebs/gss/resources/edit_group_22.png")
103                 ImageResource groups();
104
105                 @Source("gr/ebs/gss/resources/search.png")
106                 ImageResource search();
107         }
108
109         /**
110          * The single GSS instance.
111          */
112         private static GSS singleton;
113
114         /**
115          * Gets the singleton GSS instance.
116          *
117          * @return the GSS object
118          */
119         public static GSS get() {
120                 if (GSS.singleton == null)
121                         GSS.singleton = new GSS();
122                 return GSS.singleton;
123         }
124
125         /**
126          * The Application Clipboard implementation;
127          */
128         private Clipboard clipboard = new Clipboard();
129
130         private UserResource currentUserResource;
131
132         /**
133          * The top panel that contains the menu bar.
134          */
135         private TopPanel topPanel;
136
137         /**
138          * The panel that contains the various system messages.
139          */
140         private MessagePanel messagePanel = new MessagePanel(GSS.images);
141
142         /**
143          * The bottom panel that contains the status bar.
144          */
145         private StatusPanel statusPanel = new StatusPanel(GSS.images);
146
147         /**
148          * The top right panel that displays the logged in user details
149          */
150         private UserDetailsPanel userDetailsPanel = new UserDetailsPanel();
151
152         /**
153          * The file list widget.
154          */
155         private FileList fileList;
156
157         /**
158          * The group list widget.
159          */
160         private Groups groups = new Groups(images);
161
162         /**
163          * The search result widget.
164          */
165         private SearchResults searchResults;
166
167         /**
168          * The tab panel that occupies the right side of the screen.
169          */
170         private TabPanel inner = new DecoratedTabPanel();
171
172         /**
173          * The split panel that will contain the left and right panels.
174          */
175         private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
176
177         /**
178          * The horizontal panel that will contain the search and status panels.
179          */
180         private DockPanel searchStatus = new DockPanel();
181
182         /**
183          * The search widget.
184          */
185         private Search search;
186
187         /**
188          * The widget that displays the tree of folders.
189          */
190         private Folders folders = new Folders(images);
191
192         /**
193          * The currently selected item in the application, for use by the Edit menu
194          * commands. Potential types are Folder, File, User and Group.
195          */
196         private Object currentSelection;
197
198         /**
199          * The authentication token of the current user.
200          */
201         private String token;
202
203         /**
204          * The WebDAV password of the current user
205          */
206         private String webDAVPassword;
207
208         private PickupDragController dragController;
209
210         public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
211
212         @Override
213         public void onModuleLoad() {
214                 // Initialize the singleton before calling the constructors of the
215                 // various widgets that might call GSS.get().
216                 singleton = this;
217                 RootPanel.get().add(glassPanel, 0, 0);
218                 parseUserCredentials();
219                 dragController = new PickupDragController(RootPanel.get(), false) {
220
221                         @Override
222                         public void previewDragStart() throws VetoDragException {
223                             super.previewDragStart();
224                             if (context.selectedWidgets.isEmpty())
225                                         throw new VetoDragException();
226
227                             if(context.draggable != null)
228                                         if(context.draggable instanceof DnDFocusPanel){
229                                                 DnDFocusPanel toDrop = (DnDFocusPanel) context.draggable;
230                                                 // prevent drag and drop for trashed files and for
231                                                 // unselected tree items
232                                                 if(toDrop.getFiles() != null && folders.isTrashItem(folders.getCurrent()))
233                                                         throw new VetoDragException();
234                                                 else if(toDrop.getItem() != null && !toDrop.getItem().equals(folders.getCurrent()))
235                                                         throw new VetoDragException();
236                                                 else if(toDrop.getItem() != null && !toDrop.getItem().isDraggable())
237                                                         throw new VetoDragException();
238
239                                         } else if (context.draggable instanceof DnDSimpleFocusPanel) {
240                                         DnDSimpleFocusPanel toDrop = (DnDSimpleFocusPanel) context.draggable;
241                                                 // prevent drag and drop for trashed files and for
242                                                 // unselected tree items
243                                                 if(toDrop.getFiles() != null && folders.isTrashItem(folders.getCurrent()))
244                                                         throw new VetoDragException();
245                                 }
246                           }
247
248                         @Override
249                         protected Widget newDragProxy(DragContext aContext) {
250                                 AbsolutePanel container = new AbsolutePanel();
251                                 HTML html = null;
252                                 DOM.setStyleAttribute(container.getElement(), "overflow", "visible");
253                                 if(aContext.draggable!=null && aContext.draggable.getParent()!= null && aContext.draggable.getParent() instanceof FileTable){
254                                         if(getFileList().getSelectedFiles().size()>1){
255                                                 html=new HTML(getFileList().getSelectedFiles().size()+ " files");
256                                                 container.add(html);
257                                                 return container;
258                                         }
259                                         FileTable proxy;
260                                     proxy = new FileTable(1,8);
261                                     proxy.addStyleName("gss-List");
262                                     FileTable draggableTable = (FileTable) context.draggable.getParent();
263                                     int dragRow = FileTable.getWidgetRow(context.draggable, draggableTable);
264                                     FileTable.copyRow(draggableTable, proxy, dragRow, 0);
265                                     return proxy;
266
267                                 }
268                                 for (Iterator iterator = aContext.selectedWidgets.iterator(); iterator.hasNext();) {
269                                         Widget widget = (Widget) iterator.next();
270                                         if (widget instanceof DnDFocusPanel) {
271                                                 DnDFocusPanel book = (DnDFocusPanel) widget;
272                                                 html = book.cloneHTML();
273                                         } else if (widget instanceof DnDSimpleFocusPanel) {
274                                                 DnDSimpleFocusPanel book = (DnDSimpleFocusPanel) widget;
275                                                 html = book.cloneHTML();
276                                         }
277                                         if(html == null)
278                                                 container.add(new Label("Drag ME"));
279                                         else
280                                                 container.add(html);
281                                         return container;
282                                 }
283                                 return container;
284                         }
285                 };
286                 dragController.setBehaviorDragProxy(true);
287                 dragController.setBehaviorMultipleSelection(false);
288                 topPanel = new TopPanel(GSS.images);
289                 topPanel.setWidth("100%");
290
291                 messagePanel.setWidth("100%");
292                 messagePanel.setVisible(false);
293
294                 search = new Search(images);
295                 searchStatus.add(search, DockPanel.WEST);
296                 searchStatus.add(userDetailsPanel, DockPanel.EAST);
297                 searchStatus.setCellHorizontalAlignment(userDetailsPanel, HasHorizontalAlignment.ALIGN_RIGHT);
298                 searchStatus.setCellVerticalAlignment(search, HasVerticalAlignment.ALIGN_MIDDLE);
299                 searchStatus.setCellVerticalAlignment(userDetailsPanel, HasVerticalAlignment.ALIGN_MIDDLE);
300                 searchStatus.setWidth("100%");
301
302                 fileList = new FileList(images);
303
304                 searchResults = new SearchResults(images);
305
306                 // Inner contains the various lists.
307                 inner.setAnimationEnabled(true);
308                 inner.getTabBar().addStyleName("gss-MainTabBar");
309                 inner.getDeckPanel().addStyleName("gss-MainTabPanelBottom");
310                 inner.add(fileList, createHeaderHTML(AbstractImagePrototype.create(images.folders()), "Files"), true);
311
312                 inner.add(groups, createHeaderHTML(AbstractImagePrototype.create(images.groups()), "Groups"), true);
313                 inner.add(searchResults, createHeaderHTML(AbstractImagePrototype.create(images.search()), "Search Results"), true);
314                 inner.setWidth("100%");
315                 inner.selectTab(0);
316
317                 inner.addSelectionHandler(new SelectionHandler<Integer>() {
318
319                         @Override
320                         public void onSelection(SelectionEvent<Integer> event) {
321                                 int tabIndex = event.getSelectedItem();
322 //                              TreeItem treeItem = GSS.get().getFolders().getCurrent();
323                                 switch (tabIndex) {
324                                         case 0:
325 //                                              Files tab selected
326                                                 fileList.clearSelectedRows();
327                                                 fileList.updateCurrentlyShowingStats();
328                                                 break;
329                                         case 1:
330 //                                              Groups tab selected
331                                                 groups.updateCurrentlyShowingStats();
332                                         updateHistory("Groups");
333                                                 break;
334                                         case 2:
335 //                                              Search tab selected
336                                                 searchResults.clearSelectedRows();
337                                                 searchResults.updateCurrentlyShowingStats();
338                                         updateHistory("Search");
339                                                 break;
340                                 }
341                         }
342                 });
343 //              If the application starts with no history token, redirect to a new "Files" state
344                 String initToken = History.getToken();
345                 if(initToken.length() == 0)
346                         History.newItem("Files");
347 //                 Add history listener to handle any history events
348                 History.addValueChangeHandler(new ValueChangeHandler<String>() {
349                         @Override
350                         public void onValueChange(ValueChangeEvent<String> event) {
351                                 String tokenInput = event.getValue();
352                                 String historyToken = handleSpecialFolderNames(tokenInput);
353                                 try {
354                                         if(historyToken.equals("Search"))
355                                                 inner.selectTab(2);
356                                         else if(historyToken.equals("Groups"))
357                                                 inner.selectTab(1);
358                                         else if(historyToken.equals("Files")|| historyToken.length()==0)
359                                                 inner.selectTab(0);
360                                         else {
361                                                 PopupTree popupTree = GSS.get().getFolders().getPopupTree();
362                                                 TreeItem treeObj = GSS.get().getFolders().getPopupTree().getTreeItem(historyToken);
363                                                 SelectionEvent.fire(popupTree, treeObj);
364                                         }
365                                 } catch (IndexOutOfBoundsException e) {
366                                         inner.selectTab(0);
367                                 }
368                         }
369                 });
370
371                 // Add the left and right panels to the split panel.
372                 splitPanel.setLeftWidget(folders);
373                 splitPanel.setRightWidget(inner);
374                 splitPanel.setSplitPosition("25%");
375                 splitPanel.setSize("100%", "100%");
376                 splitPanel.addStyleName("gss-splitPanel");
377
378                 // Create a dock panel that will contain the menu bar at the top,
379                 // the shortcuts to the left, the status bar at the bottom and the
380                 // right panel taking the rest.
381                 VerticalPanel outer = new VerticalPanel();
382                 outer.add(topPanel);
383                 outer.add(searchStatus);
384                 outer.add(messagePanel);
385                 outer.add(splitPanel);
386                 outer.add(statusPanel);
387                 outer.setWidth("100%");
388                 outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
389
390                 outer.setSpacing(4);
391
392                 // Hook the window resize event, so that we can adjust the UI.
393                 Window.addResizeHandler(this);
394                 // Clear out the window's built-in margin, because we want to take
395                 // advantage of the entire client area.
396                 Window.setMargin("0px");
397                 // Finally, add the outer panel to the RootPanel, so that it will be
398                 // displayed.
399                 RootPanel.get().add(outer);
400                 // Call the window resized handler to get the initial sizes setup. Doing
401                 // this in a deferred command causes it to occur after all widgets'
402                 // sizes have been computed by the browser.
403                 DeferredCommand.addCommand(new Command() {
404
405                         @Override
406                         public void execute() {
407                                 onWindowResized(Window.getClientHeight());
408                         }
409                 });
410         }
411
412         /**
413          * Fetches the User object for the specified username.
414          *
415          * @param username the username of the user
416          */
417         private void fetchUser(final String username) {
418                 String path = getApiPath() + username + "/";
419                 GetCommand<UserResource> getUserCommand = new GetCommand<UserResource>(UserResource.class, username, path, null) {
420
421                         @Override
422                         public void onComplete() {
423                                 currentUserResource = getResult();
424                                 final String announcement = currentUserResource.getAnnouncement();
425                                 if (announcement != null)
426                                         DeferredCommand.addCommand(new Command() {
427
428                                                 @Override
429                                                 public void execute() {
430                                                         displayInformation(announcement);
431                                                 }
432                                         });
433                         }
434
435                         @Override
436                         public void onError(Throwable t) {
437                                 GWT.log("Fetching user error", t);
438                                 if (t instanceof RestException)
439                                         GSS.get().displayError("No user found:" + ((RestException) t).getHttpStatusText());
440                                 else
441                                         GSS.get().displayError("System error fetching user data:" + t.getMessage());
442                                 authenticateUser();
443                         }
444                 };
445                 DeferredCommand.addCommand(getUserCommand);
446         }
447
448         /**
449          * Parse and store the user credentials to the appropriate fields.
450          */
451         private void parseUserCredentials() {
452                 Configuration conf = (Configuration) GWT.create(Configuration.class);
453                 String cookie = conf.authCookie();
454                 String auth = Cookies.getCookie(cookie);
455                 if (auth == null) {
456                         authenticateUser();
457                         // Redundant, but silences warnings about possible auth NPE, below.
458                         return;
459                 }
460                 int sepIndex = auth.indexOf(conf.cookieSeparator());
461                 if (sepIndex == -1)
462                         authenticateUser();
463                 token = auth.substring(sepIndex + 1);
464                 final String username = auth.substring(0, sepIndex);
465                 if (username == null)
466                         authenticateUser();
467
468                 refreshWebDAVPassword();
469
470                 DeferredCommand.addCommand(new Command() {
471
472                         @Override
473                         public void execute() {
474                                 fetchUser(username);
475                         }
476                 });
477         }
478
479         /**
480          * Redirect the user to the login page for authentication.
481          */
482         protected void authenticateUser() {
483                 Configuration conf = (Configuration) GWT.create(Configuration.class);
484                 Window.Location.assign(conf.loginUrl() + "?next=" + GWT.getModuleBaseURL());
485         }
486
487         /**
488          * Clear the cookie and redirect the user to the logout page.
489          */
490         void logout() {
491                 Configuration conf = (Configuration) GWT.create(Configuration.class);
492                 String cookie = conf.authCookie();
493                 String domain = Window.Location.getHostName();
494                 String path = Window.Location.getPath();
495                 Cookies.setCookie(cookie, "", null, domain, path, false);
496                 Window.Location.assign(conf.logoutUrl());
497         }
498
499         /**
500          * Creates an HTML fragment that places an image & caption together, for use
501          * in a group header.
502          *
503          * @param imageProto an image prototype for an image
504          * @param caption the group caption
505          * @return the header HTML fragment
506          */
507         private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
508                 String captionHTML = "<table class='caption' cellpadding='0' " + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML() + "</td><td class='rcaption'><b style='white-space:nowrap'>&nbsp;" + caption + "</b></td></tr></table>";
509                 return captionHTML;
510         }
511
512         private void onWindowResized(int height) {
513                 // Adjust the split panel to take up the available room in the window.
514                 int newHeight = height - splitPanel.getAbsoluteTop() - 44;
515                 if (newHeight < 1)
516                         newHeight = 1;
517                 splitPanel.setHeight("" + newHeight);
518         }
519
520         @Override
521         public void onResize(ResizeEvent event) {
522                 int height = event.getHeight();
523                 onWindowResized(height);
524         }
525
526         public boolean isFileListShowing() {
527                 int tab = inner.getTabBar().getSelectedTab();
528                 if (tab == 0)
529                         return true;
530                 return false;
531         }
532
533         public boolean isSearchResultsShowing() {
534                 int tab = inner.getTabBar().getSelectedTab();
535                 if (tab == 2)
536                         return true;
537                 return false;
538         }
539
540         /**
541          * Make the user list visible.
542          */
543         public void showUserList() {
544                 inner.selectTab(1);
545         }
546
547         /**
548          * Make the file list visible.
549          */
550         public void showFileList() {
551                 fileList.updateFileCache(false, true /*clear selection*/);
552                 inner.selectTab(0);
553         }
554
555         /**
556          * Make the file list visible.
557          *
558          * @param update
559          */
560         public void showFileList(boolean update) {
561                 TreeItem currentFolder = getFolders().getCurrent();
562                 if (currentFolder != null) {
563                         List<FileResource> files = null;
564                         Object cachedObject = currentFolder.getUserObject();
565                         if (cachedObject instanceof FolderResource) {
566                                 FolderResource folder = (FolderResource) cachedObject;
567                                 files = folder.getFiles();
568                         } else if (cachedObject instanceof TrashResource) {
569                                 TrashResource folder = (TrashResource) cachedObject;
570                                 files = folder.getFiles();
571                         }
572                         if (files != null)
573                                 getFileList().setFiles(files);
574                 }
575                 fileList.updateFileCache(update, true /*clear selection*/);
576                 inner.selectTab(0);
577         }
578
579         /**
580          * Make the search results visible.
581          *
582          * @param query the search query string
583          */
584         public void showSearchResults(String query) {
585                 searchResults.updateFileCache(query);
586                 searchResults.updateCurrentlyShowingStats();
587                 inner.selectTab(2);
588         }
589
590         /**
591          * Display the 'loading' indicator.
592          */
593         public void showLoadingIndicator() {
594                 topPanel.getLoading().setVisible(true);
595         }
596
597         /**
598          * Hide the 'loading' indicator.
599          */
600         public void hideLoadingIndicator() {
601                 topPanel.getLoading().setVisible(false);
602         }
603
604         /**
605          * A native JavaScript method to reach out to the browser's window and
606          * invoke its resizeTo() method.
607          *
608          * @param x the new width
609          * @param y the new height
610          */
611         public static native void resizeTo(int x, int y) /*-{
612                 $wnd.resizeTo(x,y);
613         }-*/;
614
615         /**
616          * A helper method that returns true if the user's list is currently visible
617          * and false if it is hidden.
618          *
619          * @return true if the user list is visible
620          */
621         public boolean isUserListVisible() {
622                 return inner.getTabBar().getSelectedTab() == 1;
623         }
624
625         /**
626          * Display an error message.
627          *
628          * @param msg the message to display
629          */
630         public void displayError(String msg) {
631                 messagePanel.displayError(msg);
632         }
633
634         /**
635          * Display a warning message.
636          *
637          * @param msg the message to display
638          */
639         public void displayWarning(String msg) {
640                 messagePanel.displayWarning(msg);
641         }
642
643         /**
644          * Display an informational message.
645          *
646          * @param msg the message to display
647          */
648         public void displayInformation(String msg) {
649                 messagePanel.displayInformation(msg);
650         }
651
652         /**
653          * Retrieve the folders.
654          *
655          * @return the folders
656          */
657         public Folders getFolders() {
658                 return folders;
659         }
660
661         /**
662          * Retrieve the search.
663          *
664          * @return the search
665          */
666         Search getSearch() {
667                 return search;
668         }
669
670         /**
671          * Retrieve the currentSelection.
672          *
673          * @return the currentSelection
674          */
675         public Object getCurrentSelection() {
676                 return currentSelection;
677         }
678
679         /**
680          * Modify the currentSelection.
681          *
682          * @param newCurrentSelection the currentSelection to set
683          */
684         public void setCurrentSelection(Object newCurrentSelection) {
685                 currentSelection = newCurrentSelection;
686         }
687
688         /**
689          * Retrieve the groups.
690          *
691          * @return the groups
692          */
693         public Groups getGroups() {
694                 return groups;
695         }
696
697         /**
698          * Retrieve the fileList.
699          *
700          * @return the fileList
701          */
702         public FileList getFileList() {
703                 return fileList;
704         }
705
706         public SearchResults getSearchResults() {
707                 return searchResults;
708         }
709
710         /**
711          * Retrieve the topPanel.
712          *
713          * @return the topPanel
714          */
715         TopPanel getTopPanel() {
716                 return topPanel;
717         }
718
719         /**
720          * Retrieve the clipboard.
721          *
722          * @return the clipboard
723          */
724         public Clipboard getClipboard() {
725                 return clipboard;
726         }
727
728         public StatusPanel getStatusPanel() {
729                 return statusPanel;
730         }
731
732         /**
733          * Retrieve the userDetailsPanel.
734          *
735          * @return the userDetailsPanel
736          */
737         public UserDetailsPanel getUserDetailsPanel() {
738                 return userDetailsPanel;
739         }
740
741         /**
742          * Retrieve the dragController.
743          *
744          * @return the dragController
745          */
746         public PickupDragController getDragController() {
747                 return dragController;
748         }
749
750         public String getToken() {
751                 return token;
752         }
753
754         public String getWebDAVPassword() {
755                 return webDAVPassword;
756         }
757
758         public void removeGlassPanel() {
759                 glassPanel.removeFromParent();
760         }
761
762         /**
763          * Retrieve the currentUserResource.
764          *
765          * @return the currentUserResource
766          */
767         public UserResource getCurrentUserResource() {
768                 return currentUserResource;
769         }
770
771         /**
772          * Modify the currentUserResource.
773          *
774          * @param newUser the new currentUserResource
775          */
776         public void setCurrentUserResource(UserResource newUser) {
777                 currentUserResource = newUser;
778         }
779
780         public static native void preventIESelection() /*-{
781                 $doc.body.onselectstart = function () { return false; };
782         }-*/;
783
784         public static native void enableIESelection() /*-{
785                 if ($doc.body.onselectstart != null)
786                 $doc.body.onselectstart = null;
787         }-*/;
788
789         /**
790          * @return the absolute path of the API root URL
791          */
792         public String getApiPath() {
793                 Configuration conf = (Configuration) GWT.create(Configuration.class);
794                 return GWT.getModuleBaseURL() + conf.apiPath();
795         }
796
797         public void refreshWebDAVPassword() {
798                 Configuration conf = (Configuration) GWT.create(Configuration.class);
799                 String domain = Window.Location.getHostName();
800                 String path = Window.Location.getPath();
801                 String cookie = conf.webdavCookie();
802                 webDAVPassword = Cookies.getCookie(cookie);
803                 Cookies.setCookie(cookie, "", null, domain, path, false);
804         }
805
806         /**
807          * Convert server date to local time according to browser timezone
808          * and format it according to localized pattern.
809          * Time is always formatted to 24hr format.
810          * NB: This assumes that server runs in UTC timezone. Otherwise
811          * we would need to adjust for server time offset as well.
812          *
813          * @param date
814          * @return String
815          */
816         public static String formatLocalDateTime(Date date) {
817                 Date convertedDate = new Date(date.getTime() - date.getTimezoneOffset());
818                 final DateTimeFormat dateFormatter = DateTimeFormat.getShortDateFormat();
819                 final DateTimeFormat timeFormatter = DateTimeFormat.getFormat("HH:mm");
820                 String datePart = dateFormatter.format(convertedDate);
821                 String timePart = timeFormatter.format(convertedDate);
822                 return datePart + " " + timePart;
823         }
824         
825         /**
826          * History support for folder navigation
827          * adds a new browser history entry
828          *
829          * @param key
830          */
831         public void updateHistory(String key){
832 //              Replace any whitespace of the initial string to "+"
833 //              String result = key.replaceAll("\\s","+");
834 //              Add a new browser history entry.
835 //              History.newItem(result);
836                 History.newItem(key);
837         }
838
839         /**
840          * This method examines the token input and add a "/" at the end in case it's omitted.
841          * This happens only in Files/trash/, Files/shared/, Files/others.
842          *
843          * @param tokenInput
844          * @return the formated token with a "/" at the end or the same tokenInput parameter
845          */
846
847         private String handleSpecialFolderNames(String tokenInput){
848                 List<String> pathsToCheck = Arrays.asList("Files/trash", "Files/shared", "Files/others");
849                 if(pathsToCheck.contains(tokenInput))
850                         return tokenInput + "/";
851                 return tokenInput;
852
853         }
854
855         /**
856          * Reject illegal resource names, like '.' or '..' or slashes '/'.
857          */
858         static boolean isValidResourceName(String name) {
859                 if (".".equals(name) || "..".equals(name) || name.contains("/"))
860                         return false;
861                 return true;
862         }
863
864         public void putUserToMap(String _userName, String _userFullName){
865                 userFullNameMap.put(_userName, _userFullName);
866         }
867
868         public String findUserFullName(String _userName){
869                 return userFullNameMap.get(_userName);
870         }
871
872         public String getUserFullName(String _userName) {
873                 if (GSS.get().findUserFullName(_userName) == null)
874                         //if there is no userFullName found then the map fills with the given _userName,
875                         //so userFullName = _userName
876                         GSS.get().putUserToMap(_userName, _userName);
877                 else if(GSS.get().findUserFullName(_userName).indexOf('@') != -1){
878                         //if the userFullName = _userName the GetUserCommand updates the userFullName in the map
879                         GetUserCommand guc = new GetUserCommand(_userName);
880                         guc.execute();
881                 }
882                 return GSS.get().findUserFullName(_userName);
883         }
884 }