improved version of bug (almost)fix 371. Abstract methods implemented inside RestReso...
[pithos] / src / gr / ebs / gss / client / GSS.java
index dbbd8a2..0853f28 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
+ * Copyright 2007, 2008, 2009, 2010 Electronic Business Systems Ltd.
  *
  * This file is part of GSS.
  *
@@ -20,6 +20,7 @@ package gr.ebs.gss.client;
 
 import gr.ebs.gss.client.clipboard.Clipboard;
 import gr.ebs.gss.client.dnd.DnDFocusPanel;
+import gr.ebs.gss.client.dnd.DnDSimpleFocusPanel;
 import gr.ebs.gss.client.rest.GetCommand;
 import gr.ebs.gss.client.rest.RestException;
 import gr.ebs.gss.client.rest.resource.FileResource;
@@ -27,8 +28,10 @@ import gr.ebs.gss.client.rest.resource.FolderResource;
 import gr.ebs.gss.client.rest.resource.TrashResource;
 import gr.ebs.gss.client.rest.resource.UserResource;
 
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import com.allen_sauer.gwt.dnd.client.DragContext;
 import com.allen_sauer.gwt.dnd.client.PickupDragController;
@@ -39,15 +42,19 @@ import com.google.gwt.event.logical.shared.ResizeEvent;
 import com.google.gwt.event.logical.shared.ResizeHandler;
 import com.google.gwt.event.logical.shared.SelectionEvent;
 import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.resources.client.ClientBundle;
 import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.Cookies;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.DeferredCommand;
+import com.google.gwt.user.client.History;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.AbsolutePanel;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.user.client.ui.DecoratedTabPanel;
 import com.google.gwt.user.client.ui.DockPanel;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
@@ -60,7 +67,6 @@ import com.google.gwt.user.client.ui.TreeItem;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
 
-
 /**
  * Entry point classes define <code>onModuleLoad()</code>.
  */
@@ -71,20 +77,21 @@ public class GSS implements EntryPoint, ResizeHandler {
         */
        public static final boolean DONE = false;
 
-       public static final int VISIBLE_FILE_COUNT = 200;
+       public static final int VISIBLE_FILE_COUNT = 100;
 
        /**
         * Instantiate an application-level image bundle. This object will provide
         * programmatic access to all the images needed by widgets.
         */
        private static Images images = (Images) GWT.create(Images.class);
+
        private GlassPanel glassPanel = new GlassPanel();
 
        /**
         * An aggregate image bundle that pulls together all the images for this
         * application into a single bundle.
         */
-       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 {
+       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 {
 
                @Source("gr/ebs/gss/resources/document.png")
                ImageResource folders();
@@ -147,7 +154,7 @@ public class GSS implements EntryPoint, ResizeHandler {
        /**
         * The group list widget.
         */
-       private Groups groups  = new Groups(images);
+       private Groups groups = new Groups(images);
 
        /**
         * The search result widget.
@@ -155,15 +162,9 @@ public class GSS implements EntryPoint, ResizeHandler {
        private SearchResults searchResults;
 
        /**
-        * A widget that displays a message indicating that communication with the
-        * server is underway.
-        */
-       private LoadingIndicator loading;
-
-       /**
         * The tab panel that occupies the right side of the screen.
         */
-       private TabPanel inner = new TabPanel();
+       private TabPanel inner = new DecoratedTabPanel();
 
        /**
         * The split panel that will contain the left and right panels.
@@ -197,6 +198,12 @@ public class GSS implements EntryPoint, ResizeHandler {
        private String token;
 
        /**
+        * A map that stores a set of String URI and the corresponding object
+        * in order history functionality to be implemented.
+        */
+       private Map<String, Object> map = new HashMap<String, Object>();
+
+       /**
         * The WebDAV password of the current user
         */
        private String webDAVPassword;
@@ -213,32 +220,46 @@ public class GSS implements EntryPoint, ResizeHandler {
 
                        @Override
                        public void previewDragStart() throws VetoDragException {
-                           super.previewDragStart();
-                           if (context.selectedWidgets.isEmpty())
+                               super.previewDragStart();
+                               if (context.selectedWidgets.isEmpty())
                                        throw new VetoDragException();
 
-                           if(context.draggable != null){
-                                       DnDFocusPanel toDrop = (DnDFocusPanel) context.draggable;
-                                       //prevent drag and drop for trashed files and for unselected tree items
-                                       if(toDrop.getFiles() != null && folders.isTrashItem(folders.getCurrent()))
-                                               throw new VetoDragException();
-                                       else if(toDrop.getItem() != null && !toDrop.getItem().equals(folders.getCurrent()))
-                                               throw new VetoDragException();
-                                       else if(toDrop.getItem() != null && !toDrop.getItem().isDraggable())
-                                               throw new VetoDragException();
-
-                           }
-                         }
+                               if (context.draggable != null)
+                                       if (context.draggable instanceof DnDFocusPanel) {
+                                               DnDFocusPanel toDrop = (DnDFocusPanel) context.draggable;
+                                               // prevent drag and drop for trashed files and for
+                                               // unselected tree items
+                                               if (toDrop.getFiles() != null && folders.isTrashItem(folders.getCurrent()))
+                                                       throw new VetoDragException();
+                                               else if (toDrop.getItem() != null && !toDrop.getItem().equals(folders.getCurrent()))
+                                                       throw new VetoDragException();
+                                               else if (toDrop.getItem() != null && !toDrop.getItem().isDraggable())
+                                                       throw new VetoDragException();
+
+                                       } else if (context.draggable instanceof DnDSimpleFocusPanel) {
+                                               DnDSimpleFocusPanel toDrop = (DnDSimpleFocusPanel) context.draggable;
+                                               // prevent drag and drop for trashed files and for
+                                               // unselected tree items
+                                               if (toDrop.getFiles() != null && folders.isTrashItem(folders.getCurrent()))
+                                                       throw new VetoDragException();
+                                       }
+                       }
 
                        @Override
                        protected Widget newDragProxy(DragContext aContext) {
                                AbsolutePanel container = new AbsolutePanel();
                                DOM.setStyleAttribute(container.getElement(), "overflow", "visible");
                                for (Iterator iterator = aContext.selectedWidgets.iterator(); iterator.hasNext();) {
+                                       HTML html = null;
                                        Widget widget = (Widget) iterator.next();
-                                       DnDFocusPanel book = (DnDFocusPanel) widget;
-                                       HTML html = book.cloneHTML();
-                                       if(html == null)
+                                       if (widget instanceof DnDFocusPanel) {
+                                               DnDFocusPanel book = (DnDFocusPanel) widget;
+                                               html = book.cloneHTML();
+                                       } else if (widget instanceof DnDSimpleFocusPanel) {
+                                               DnDSimpleFocusPanel book = (DnDSimpleFocusPanel) widget;
+                                               html = book.cloneHTML();
+                                       }
+                                       if (html == null)
                                                container.add(new Label("Drag ME"));
                                        else
                                                container.add(html);
@@ -267,8 +288,9 @@ public class GSS implements EntryPoint, ResizeHandler {
                searchResults = new SearchResults(images);
 
                // Inner contains the various lists.
-               inner.getTabBar().setStyleName("gss-TabBar");
-               inner.setStyleName("gss-TabPanel");
+               inner.setAnimationEnabled(true);
+               inner.getTabBar().addStyleName("gss-MainTabBar");
+               inner.getDeckPanel().addStyleName("gss-MainTabPanelBottom");
                inner.add(fileList, createHeaderHTML(AbstractImagePrototype.create(images.folders()), "Files"), true);
 
                inner.add(groups, createHeaderHTML(AbstractImagePrototype.create(images.groups()), "Groups"), true);
@@ -280,29 +302,58 @@ public class GSS implements EntryPoint, ResizeHandler {
 
                        @Override
                        public void onSelection(SelectionEvent<Integer> event) {
-                               int tabIndex= event.getSelectedItem();
+                               int tabIndex = event.getSelectedItem();
+                               TreeItem treeItem = GSS.get().getFolders().getCurrent();
                                switch (tabIndex) {
-                               case 0:
-                                       fileList.clearSelectedRows();
-                                       fileList.updateCurrentlyShowingStats();
-                                       break;
-                               case 1:
-                                       groups.updateCurrentlyShowingStats();
-                                       break;
-                               case 2:
-                                       searchResults.clearSelectedRows();
-                                       searchResults.updateCurrentlyShowingStats();
-                                       break;
-                       }
+                                       case 0:
+//                                             Files tab selected
+                                               fileList.clearSelectedRows();
+                                               fileList.updateCurrentlyShowingStats();
+                                               break;
+                                       case 1:
+//                                             Groups tab selected
+                                               groups.updateCurrentlyShowingStats();
+                                       updateHistory("Groups", treeItem);
+                                               break;
+                                       case 2:
+//                                             Search tab selected
+                                               searchResults.clearSelectedRows();
+                                               searchResults.updateCurrentlyShowingStats();
+                                       updateHistory("Search", treeItem);
+                                               break;
+                               }
                        }
                });
-
+//             If the application starts with no history token, redirect to a new "Files" state
+               String initToken = History.getToken();
+               if(initToken.length() == 0)
+                       History.newItem("Files");
+
+//                Add history listener to handle any history events
+                  History.addValueChangeHandler(new ValueChangeHandler<String>() {
+                             public void onValueChange(ValueChangeEvent<String> event) {
+                               String historyToken = event.getValue();
+                               try {
+                                       if(historyToken.equals("Search"))
+                                               inner.selectTab(2);
+                                       else if(historyToken.equals("Groups"))
+                                               inner.selectTab(1);
+                                       else if(historyToken.equals("Files")|| historyToken.length()==0)
+                                               inner.selectTab(0);
+                                               else
+                                                       SelectionEvent.fire(GSS.get().getFolders().getPopupTree(), (TreeItem) getHistoryItem(historyToken));
+                                       } catch (IndexOutOfBoundsException e) {
+                                               inner.selectTab(0);
+                                               }
+                                       }
+                             });
 
                // Add the left and right panels to the split panel.
                splitPanel.setLeftWidget(folders);
                splitPanel.setRightWidget(inner);
                splitPanel.setSplitPosition("25%");
                splitPanel.setSize("100%", "100%");
+               splitPanel.addStyleName("gss-splitPanel");
 
                // Create a dock panel that will contain the menu bar at the top,
                // the shortcuts to the left, the status bar at the bottom and the
@@ -318,25 +369,21 @@ public class GSS implements EntryPoint, ResizeHandler {
 
                outer.setSpacing(4);
 
-               loading = new LoadingIndicator();
-
                // Hook the window resize event, so that we can adjust the UI.
                Window.addResizeHandler(this);
-
                // Clear out the window's built-in margin, because we want to take
                // advantage of the entire client area.
                Window.setMargin("0px");
-
                // Finally, add the outer panel to the RootPanel, so that it will be
                // displayed.
                RootPanel.get().add(outer);
-
                // Call the window resized handler to get the initial sizes setup. Doing
                // this in a deferred command causes it to occur after all widgets'
                // sizes have been computed by the browser.
                DeferredCommand.addCommand(new Command() {
+
                        public void execute() {
-                               onWindowResized(Window.getClientWidth());
+                               onWindowResized(Window.getClientHeight());
                        }
                });
        }
@@ -348,7 +395,7 @@ public class GSS implements EntryPoint, ResizeHandler {
         */
        private void fetchUser(final String username) {
                String path = getApiPath() + username + "/";
-               GetCommand<UserResource> getUserCommand = new GetCommand<UserResource>(UserResource.class, username, path){
+               GetCommand<UserResource> getUserCommand = new GetCommand<UserResource>(UserResource.class, username, path, null) {
 
                        @Override
                        public void onComplete() {
@@ -356,6 +403,7 @@ public class GSS implements EntryPoint, ResizeHandler {
                                final String announcement = currentUserResource.getAnnouncement();
                                if (announcement != null)
                                        DeferredCommand.addCommand(new Command() {
+
                                                public void execute() {
                                                        displayInformation(announcement);
                                                }
@@ -365,10 +413,10 @@ public class GSS implements EntryPoint, ResizeHandler {
                        @Override
                        public void onError(Throwable t) {
                                GWT.log("Fetching user error", t);
-                               if(t instanceof RestException)
-                                       GSS.get().displayError("No user found:"+((RestException)t).getHttpStatusText());
+                               if (t instanceof RestException)
+                                       GSS.get().displayError("No user found:" + ((RestException) t).getHttpStatusText());
                                else
-                                       GSS.get().displayError("System error fetching user data:"+t.getMessage());
+                                       GSS.get().displayError("System error fetching user data:" + t.getMessage());
                                authenticateUser();
                        }
                };
@@ -382,9 +430,6 @@ public class GSS implements EntryPoint, ResizeHandler {
                Configuration conf = (Configuration) GWT.create(Configuration.class);
                String cookie = conf.authCookie();
                String auth = Cookies.getCookie(cookie);
-               String domain = Window.Location.getHostName();
-               String path = Window.Location.getPath();
-               Cookies.setCookie(cookie, "", null, domain, path, false);
                if (auth == null) {
                        authenticateUser();
                        // Redundant, but silences warnings about possible auth NPE, below.
@@ -393,7 +438,7 @@ public class GSS implements EntryPoint, ResizeHandler {
                int sepIndex = auth.indexOf(conf.cookieSeparator());
                if (sepIndex == -1)
                        authenticateUser();
-               token = auth.substring(sepIndex + 1, auth.length());
+               token = auth.substring(sepIndex + 1);
                final String username = auth.substring(0, sepIndex);
                if (username == null)
                        authenticateUser();
@@ -401,6 +446,7 @@ public class GSS implements EntryPoint, ResizeHandler {
                refreshWebDAVPassword();
 
                DeferredCommand.addCommand(new Command() {
+
                        public void execute() {
                                fetchUser(username);
                        }
@@ -416,10 +462,14 @@ public class GSS implements EntryPoint, ResizeHandler {
        }
 
        /**
-        * Redirect the user to the logout page.
+        * Clear the cookie and redirect the user to the logout page.
         */
        void logout() {
                Configuration conf = (Configuration) GWT.create(Configuration.class);
+               String cookie = conf.authCookie();
+               String domain = Window.Location.getHostName();
+               String path = Window.Location.getPath();
+               Cookies.setCookie(cookie, "", null, domain, path, false);
                Window.Location.assign(conf.logoutUrl());
        }
 
@@ -432,14 +482,10 @@ public class GSS implements EntryPoint, ResizeHandler {
         * @return the header HTML fragment
         */
        private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
-               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>";
+               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>";
                return captionHTML;
        }
 
-
        private void onWindowResized(int height) {
                // Adjust the split panel to take up the available room in the window.
                int newHeight = height - splitPanel.getAbsoluteTop() - 44;
@@ -450,19 +496,21 @@ public class GSS implements EntryPoint, ResizeHandler {
 
        @Override
        public void onResize(ResizeEvent event) {
-               int width=event.getWidth();
-               onWindowResized(width);
+               int height = event.getHeight();
+               onWindowResized(height);
        }
 
-       public boolean isFileListShowing(){
+       public boolean isFileListShowing() {
                int tab = inner.getTabBar().getSelectedTab();
-               if(tab == 0) return true;
+               if (tab == 0)
+                       return true;
                return false;
        }
 
-       public boolean isSearchResultsShowing(){
+       public boolean isSearchResultsShowing() {
                int tab = inner.getTabBar().getSelectedTab();
-               if(tab == 2) return true;
+               if (tab == 2)
+                       return true;
                return false;
        }
 
@@ -483,6 +531,7 @@ public class GSS implements EntryPoint, ResizeHandler {
 
        /**
         * Make the file list visible.
+        *
         * @param update
         */
        public void showFileList(boolean update) {
@@ -506,6 +555,7 @@ public class GSS implements EntryPoint, ResizeHandler {
 
        /**
         * Make the search results visible.
+        *
         * @param query the search query string
         */
        public void showSearchResults(String query) {
@@ -518,14 +568,14 @@ public class GSS implements EntryPoint, ResizeHandler {
         * Display the 'loading' indicator.
         */
        public void showLoadingIndicator() {
-               loading.center();
+               topPanel.getLoading().setVisible(true);
        }
 
        /**
         * Hide the 'loading' indicator.
         */
        public void hideLoadingIndicator() {
-               loading.hide();
+               topPanel.getLoading().setVisible(false);
        }
 
        /**
@@ -536,7 +586,7 @@ public class GSS implements EntryPoint, ResizeHandler {
         * @param y the new height
         */
        public static native void resizeTo(int x, int y) /*-{
-        $wnd.resizeTo(x,y);
+               $wnd.resizeTo(x,y);
        }-*/;
 
        /**
@@ -630,7 +680,7 @@ public class GSS implements EntryPoint, ResizeHandler {
                return fileList;
        }
 
-       public SearchResults getSearchResults(){
+       public SearchResults getSearchResults() {
                return searchResults;
        }
 
@@ -652,12 +702,10 @@ public class GSS implements EntryPoint, ResizeHandler {
                return clipboard;
        }
 
-
-       public StatusPanel getStatusPanel(){
+       public StatusPanel getStatusPanel() {
                return statusPanel;
        }
 
-
        /**
         * Retrieve the userDetailsPanel.
         *
@@ -676,7 +724,7 @@ public class GSS implements EntryPoint, ResizeHandler {
                return dragController;
        }
 
-       public String getToken(){
+       public String getToken() {
                return token;
        }
 
@@ -684,7 +732,7 @@ public class GSS implements EntryPoint, ResizeHandler {
                return webDAVPassword;
        }
 
-       public void removeGlassPanel(){
+       public void removeGlassPanel() {
                glassPanel.removeFromParent();
        }
 
@@ -707,12 +755,12 @@ public class GSS implements EntryPoint, ResizeHandler {
        }
 
        public static native void preventIESelection() /*-{
-       $doc.body.onselectstart = function () { return false; };
+               $doc.body.onselectstart = function () { return false; };
        }-*/;
 
        public static native void enableIESelection() /*-{
                if ($doc.body.onselectstart != null)
-                       $doc.body.onselectstart = null;
+               $doc.body.onselectstart = null;
        }-*/;
 
        /**
@@ -731,7 +779,27 @@ public class GSS implements EntryPoint, ResizeHandler {
                webDAVPassword = Cookies.getCookie(cookie);
                Cookies.setCookie(cookie, "", null, domain, path, false);
        }
+       /**
+        * @param key
+        * @return Object of the corresponding String URI which is stored in the history map
+        */
+       public Object getHistoryItem(String key){
+               return map.get(key);
+       }
 
-
-
+       /**
+        * Replaces any whitespace in the given string to "+"
+        * Sets a pair of key - object in the History (using a map)
+        * and adds a new browser history entry
+        * @param key
+        * @param obj
+        */
+       public void updateHistory(String key, Object obj){
+//             Replace any whitespace of the initial string to "+"
+               String result = key.replaceAll("\\s","+");
+//             Add a new pair key - object in the History map.
+               map.put(result, obj);
+//             Add a new browser history entry.
+               History.newItem(result);
+       }
 }