X-Git-Url: https://code.grnet.gr/git/pithos/blobdiff_plain/c917374b6a55c738a2bc874369e215892f059e6c..ce98bfc619a13df1884b185f3c9eb066f7738c8f:/src/gr/ebs/gss/client/GSS.java diff --git a/src/gr/ebs/gss/client/GSS.java b/src/gr/ebs/gss/client/GSS.java index a8fceb3..af95cac 100644 --- a/src/gr/ebs/gss/client/GSS.java +++ b/src/gr/ebs/gss/client/GSS.java @@ -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,6 +28,7 @@ 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.Arrays; import java.util.Iterator; import java.util.List; @@ -35,14 +37,23 @@ import com.allen_sauer.gwt.dnd.client.PickupDragController; import com.allen_sauer.gwt.dnd.client.VetoDragException; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; +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.WindowResizeListener; 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; @@ -50,18 +61,15 @@ import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalSplitPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.SourcesTabEvents; -import com.google.gwt.user.client.ui.TabListener; import com.google.gwt.user.client.ui.TabPanel; 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 onModuleLoad(). */ -public class GSS implements EntryPoint, WindowResizeListener { +public class GSS implements EntryPoint, ResizeHandler { /** * A constant that denotes the completion of an IncrementalCommand. @@ -75,22 +83,23 @@ public class GSS implements EntryPoint, WindowResizeListener { * 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 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 { - @Resource("gr/ebs/gss/resources/document.png") - AbstractImagePrototype folders(); + @Source("gr/ebs/gss/resources/document.png") + ImageResource folders(); - @Resource("gr/ebs/gss/resources/edit_group_22.png") - AbstractImagePrototype groups(); + @Source("gr/ebs/gss/resources/edit_group_22.png") + ImageResource groups(); - @Resource("gr/ebs/gss/resources/search.png") - AbstractImagePrototype search(); + @Source("gr/ebs/gss/resources/search.png") + ImageResource search(); } /** @@ -144,7 +153,7 @@ public class GSS implements EntryPoint, WindowResizeListener { /** * The group list widget. */ - private Groups groups = new Groups(images); + private Groups groups = new Groups(images); /** * The search result widget. @@ -152,15 +161,9 @@ public class GSS implements EntryPoint, WindowResizeListener { 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. @@ -200,6 +203,7 @@ public class GSS implements EntryPoint, WindowResizeListener { private PickupDragController dragController; + @Override public void onModuleLoad() { // Initialize the singleton before calling the constructors of the // various widgets that might call GSS.get(). @@ -210,32 +214,46 @@ public class GSS implements EntryPoint, WindowResizeListener { @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); @@ -264,40 +282,76 @@ public class GSS implements EntryPoint, WindowResizeListener { searchResults = new SearchResults(images); // Inner contains the various lists. - inner.getTabBar().setStyleName("gss-TabBar"); - inner.setStyleName("gss-TabPanel"); - inner.add(fileList, createHeaderHTML(images.folders(), "Files"), true); + 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(images.groups(), "Groups"), true); - inner.add(searchResults, createHeaderHTML(images.search(), "Search Results"), true); + inner.add(groups, createHeaderHTML(AbstractImagePrototype.create(images.groups()), "Groups"), true); + inner.add(searchResults, createHeaderHTML(AbstractImagePrototype.create(images.search()), "Search Results"), true); inner.setWidth("100%"); inner.selectTab(0); - inner.addTabListener(new TabListener() { - public void onTabSelected(SourcesTabEvents sender, int tabIndex) { - switch (tabIndex) { - case 0: - fileList.updateCurrentlyShowingStats(); - break; - case 1: - groups.updateCurrentlyShowingStats(); - break; - case 2: - searchResults.updateCurrentlyShowingStats(); - break; - } - } + inner.addSelectionHandler(new SelectionHandler() { - public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) { - return true; + @Override + public void onSelection(SelectionEvent event) { + int tabIndex = event.getSelectedItem(); +// TreeItem treeItem = GSS.get().getFolders().getCurrent(); + switch (tabIndex) { + case 0: +// Files tab selected + fileList.clearSelectedRows(); + fileList.updateCurrentlyShowingStats(); + break; + case 1: +// Groups tab selected + groups.updateCurrentlyShowingStats(); + updateHistory("Groups"); + break; + case 2: +// Search tab selected + searchResults.clearSelectedRows(); + searchResults.updateCurrentlyShowingStats(); + updateHistory("Search"); + 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() { + @Override + public void onValueChange(ValueChangeEvent event) { + String tokenInput = event.getValue(); + String historyToken = handleSpecialFolderNames(tokenInput); + 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 { + PopupTree popupTree = GSS.get().getFolders().getPopupTree(); + TreeItem treeObj = GSS.get().getFolders().getPopupTree().getTreeItem(historyToken); + SelectionEvent.fire(popupTree, treeObj); + } + } 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 @@ -313,25 +367,22 @@ public class GSS implements EntryPoint, WindowResizeListener { outer.setSpacing(4); - loading = new LoadingIndicator(); - // Hook the window resize event, so that we can adjust the UI. - Window.addWindowResizeListener(this); - + 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() { + + @Override public void execute() { - onWindowResized(Window.getClientWidth(), Window.getClientHeight()); + onWindowResized(Window.getClientHeight()); } }); } @@ -343,7 +394,7 @@ public class GSS implements EntryPoint, WindowResizeListener { */ private void fetchUser(final String username) { String path = getApiPath() + username + "/"; - GetCommand getUserCommand = new GetCommand(UserResource.class, username, path){ + GetCommand getUserCommand = new GetCommand(UserResource.class, username, path, null) { @Override public void onComplete() { @@ -351,6 +402,8 @@ public class GSS implements EntryPoint, WindowResizeListener { final String announcement = currentUserResource.getAnnouncement(); if (announcement != null) DeferredCommand.addCommand(new Command() { + + @Override public void execute() { displayInformation(announcement); } @@ -360,10 +413,10 @@ public class GSS implements EntryPoint, WindowResizeListener { @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(); } }; @@ -377,9 +430,6 @@ public class GSS implements EntryPoint, WindowResizeListener { 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. @@ -388,7 +438,7 @@ public class GSS implements EntryPoint, WindowResizeListener { 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(); @@ -396,6 +446,8 @@ public class GSS implements EntryPoint, WindowResizeListener { refreshWebDAVPassword(); DeferredCommand.addCommand(new Command() { + + @Override public void execute() { fetchUser(username); } @@ -411,10 +463,14 @@ public class GSS implements EntryPoint, WindowResizeListener { } /** - * 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()); } @@ -427,19 +483,11 @@ public class GSS implements EntryPoint, WindowResizeListener { * @return the header HTML fragment */ private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) { - String captionHTML = "" + "
" + imageProto.getHTML() + - " " + - caption + "
"; + String captionHTML = "" + "
" + imageProto.getHTML() + " " + caption + "
"; return captionHTML; } - /* - * (non-Javadoc) - * - * @see com.google.gwt.user.client.WindowResizeListener#onWindowResized(int,int) - */ - public void onWindowResized(int width, int height) { + private void onWindowResized(int height) { // Adjust the split panel to take up the available room in the window. int newHeight = height - splitPanel.getAbsoluteTop() - 44; if (newHeight < 1) @@ -447,15 +495,23 @@ public class GSS implements EntryPoint, WindowResizeListener { splitPanel.setHeight("" + newHeight); } - public boolean isFileListShowing(){ + @Override + public void onResize(ResizeEvent event) { + int height = event.getHeight(); + onWindowResized(height); + } + + 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; } @@ -476,6 +532,7 @@ public class GSS implements EntryPoint, WindowResizeListener { /** * Make the file list visible. + * * @param update */ public void showFileList(boolean update) { @@ -499,6 +556,7 @@ public class GSS implements EntryPoint, WindowResizeListener { /** * Make the search results visible. + * * @param query the search query string */ public void showSearchResults(String query) { @@ -511,14 +569,14 @@ public class GSS implements EntryPoint, WindowResizeListener { * 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); } /** @@ -529,7 +587,7 @@ public class GSS implements EntryPoint, WindowResizeListener { * @param y the new height */ public static native void resizeTo(int x, int y) /*-{ - $wnd.resizeTo(x,y); + $wnd.resizeTo(x,y); }-*/; /** @@ -623,7 +681,7 @@ public class GSS implements EntryPoint, WindowResizeListener { return fileList; } - public SearchResults getSearchResults(){ + public SearchResults getSearchResults() { return searchResults; } @@ -645,12 +703,10 @@ public class GSS implements EntryPoint, WindowResizeListener { return clipboard; } - - public StatusPanel getStatusPanel(){ + public StatusPanel getStatusPanel() { return statusPanel; } - /** * Retrieve the userDetailsPanel. * @@ -669,7 +725,7 @@ public class GSS implements EntryPoint, WindowResizeListener { return dragController; } - public String getToken(){ + public String getToken() { return token; } @@ -677,7 +733,7 @@ public class GSS implements EntryPoint, WindowResizeListener { return webDAVPassword; } - public void removeGlassPanel(){ + public void removeGlassPanel() { glassPanel.removeFromParent(); } @@ -700,12 +756,12 @@ public class GSS implements EntryPoint, WindowResizeListener { } 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; }-*/; /** @@ -725,4 +781,44 @@ public class GSS implements EntryPoint, WindowResizeListener { Cookies.setCookie(cookie, "", null, domain, path, false); } + /** + * History support for folder navigation + * adds a new browser history entry + * + * @param key + */ + public void updateHistory(String key){ +// Replace any whitespace of the initial string to "+" +// String result = key.replaceAll("\\s","+"); +// Add a new browser history entry. +// History.newItem(result); + History.newItem(key); + } + + /** + * This method examines the token input and add a "/" at the end in case it's omitted. + * This happens only in Files/trash/, Files/shared/, Files/others. + * + * @param tokenInput + * @return the formated token with a "/" at the end or the same tokenInput parameter + */ + + private String handleSpecialFolderNames(String tokenInput){ + List pathsToCheck = Arrays.asList("Files/trash", "Files/shared", "Files/others"); + if(pathsToCheck.contains(tokenInput)) + return tokenInput + "/"; + return tokenInput; + + } + + /** + * Reject illegal resource names, like '.' or '..'. + */ + static boolean isValidResourceName(String name) { + if (".".equals(name) || "..".equals(name)) + return false; + return true; + } + + }