2 * Copyright 2011 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and
31 * documentation are those of the authors and should not be
32 * interpreted as representing official policies, either expressed
33 * or implied, of GRNET S.A.
35 package gr.grnet.pithos.web.client;
37 import gr.grnet.pithos.web.client.CellTreeViewModel.ClearSelection;
38 import gr.grnet.pithos.web.client.rest.GetCommand;
39 import gr.grnet.pithos.web.client.rest.RestException;
40 import gr.grnet.pithos.web.client.rest.resource.FolderResource;
41 import gr.grnet.pithos.web.client.rest.resource.MyFolderResource;
42 import gr.grnet.pithos.web.client.rest.resource.OtherUserResource;
43 import gr.grnet.pithos.web.client.rest.resource.OthersFolderResource;
44 import gr.grnet.pithos.web.client.rest.resource.OthersResource;
45 import gr.grnet.pithos.web.client.rest.resource.RestResource;
46 import gr.grnet.pithos.web.client.rest.resource.RestResourceWrapper;
47 import gr.grnet.pithos.web.client.rest.resource.SharedResource;
48 import gr.grnet.pithos.web.client.rest.resource.TrashFolderResource;
49 import gr.grnet.pithos.web.client.rest.resource.TrashResource;
50 import gr.grnet.pithos.web.client.rest.resource.UserResource;
51 import gwtquery.plugins.droppable.client.gwt.DragAndDropCellTree;
53 import java.util.Arrays;
55 import com.google.gwt.core.client.GWT;
56 import com.google.gwt.resources.client.ClientBundle;
57 import com.google.gwt.resources.client.ImageResource;
58 import com.google.gwt.resources.client.ImageResource.ImageOptions;
59 import com.google.gwt.user.cellview.client.CellTree;
60 import com.google.gwt.user.cellview.client.TreeNode;
61 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
62 import com.google.gwt.user.client.DeferredCommand;
63 import com.google.gwt.user.client.Event;
64 import com.google.gwt.user.client.IncrementalCommand;
65 import com.google.gwt.user.client.ui.Composite;
66 import com.google.gwt.user.client.ui.Tree;
67 import com.google.gwt.view.client.ProvidesKey;
68 import com.google.gwt.view.client.SelectionChangeEvent;
69 import com.google.gwt.view.client.SingleSelectionModel;
70 import com.google.gwt.view.client.TreeViewModel;
71 import com.google.gwt.view.client.SelectionChangeEvent.Handler;
72 import com.google.gwt.view.client.TreeViewModel.NodeInfo;
75 public class CellTreeView extends Composite{
76 public static final boolean DONE = false;
80 SingleSelectionModel<RestResource> selectionModel = new SingleSelectionModel<RestResource>(new ProvidesKey<RestResource>() {
83 public Object getKey(RestResource item) {
84 return item.getClass().getName()+":"+item.getUri();
86 FolderContextMenu menu;
89 MyFolderResource myFolders=null;
90 TrashResource trash = null;
91 SharedResource myshared = null;
92 OthersResource others = null;
94 CellTreeViewModel model;
95 CellTreeViewUtils utils;
97 public interface Images extends ClientBundle,Tree.Resources, FolderContextMenu.Images {
99 @Source("gr/grnet/pithos/resources/folder_home.png")
100 ImageResource home();
102 @Source("gr/grnet/pithos/resources/folder_yellow.png")
103 ImageResource folderYellow();
105 @Source("gr/grnet/pithos/resources/mimetypes/document.png")
106 ImageResource document();
108 @Source("gr/grnet/pithos/resources/internet.png")
109 ImageResource othersShared();
111 @Source("gr/grnet/pithos/resources/edit_user.png")
112 ImageResource myShared();
114 @Source("gr/grnet/pithos/resources/folder_user.png")
115 ImageResource sharedFolder();
117 @Source("gr/grnet/pithos/resources/trashcan_empty.png")
118 ImageResource trash();
120 DragAndDropCellTree tree;
121 /*public interface BasicResources extends CellTree.BasicResources{
122 @ImageOptions(flipRtl = true)
123 @Source("cellTreeLoadingBasic.gif")
124 ImageResource cellTreeLoading();
126 @Source({"GssCellTreeBasic.css"})
127 CellTree.Style cellTreeStyle();
129 public interface BasicResources extends CellTree.Resources {
131 @ImageOptions(flipRtl = true)
132 @Source("cellTreeClosedItem.gif")
133 ImageResource cellTreeClosedItem();
135 @ImageOptions(flipRtl = true)
136 @Source("cellTreeLoadingBasic.gif")
137 ImageResource cellTreeLoading();
139 @ImageOptions(flipRtl = true)
140 @Source("cellTreeOpenItem.gif")
141 ImageResource cellTreeOpenItem();
143 //@Source({CellTree.Style.DEFAULT_CSS,"GssCellTreeBasic.css"})
144 @Source({"GssCellTreeBasic.css"})
145 CellTree.Style cellTreeStyle();
150 public CellTreeView(Pithos _app, final Images _images) {
153 model = new CellTreeViewModel(app, images,selectionModel);
155 * Create the tree using the model. We use <code>null</code> as the default
156 * value of the root node. The default value will be passed to
157 * CustomTreeModel#getNodeInfo();
159 CellTree.Resources res = GWT.create(BasicResources.class);
160 tree = new DragAndDropCellTree(model,null, res){
162 public void onBrowserEvent(Event event) {
163 // TODO Auto-generated method stub
164 super.onBrowserEvent(event);
167 utils=new CellTreeViewUtils(tree);
168 tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
169 /*tree.addOpenHandler(new OpenHandler<TreeNode>() {
172 public void onOpen(OpenEvent<TreeNode> event) {
173 Window.alert("[NODE OPENED]"+event.getTarget());
177 tree.addOverDroppableHandler(new OverDroppableEventHandler() {
180 public void onOverDroppable(OverDroppableEvent event) {
181 GWT.log("OVER:"+event);
185 tree.addAttachHandler(new AttachEvent.Handler() {
188 public void onAttachOrDetach(AttachEvent event) {
189 GWT.log("ATTACH:"+event.getSource());
193 Handler selectionHandler = new SelectionChangeEvent.Handler() {
195 public void onSelectionChange(com.google.gwt.view.client.SelectionChangeEvent event) {
196 NodeInfo<RestResource> nodeInfo = (NodeInfo<RestResource>) getModel().getNodeInfo(selectionModel.getSelectedObject());
197 if(nodeInfo==null || nodeInfo.getValueUpdater()==null){
198 app.showFileList(getSelection());
201 nodeInfo.getValueUpdater().update(selectionModel.getSelectedObject());
202 app.setCurrentSelection(selectionModel.getSelectedObject());
207 selectionModel.addSelectionChangeHandler(selectionHandler);
208 sinkEvents(Event.ONCONTEXTMENU);
209 sinkEvents(Event.ONMOUSEUP);
211 FolderResource loadingResource = new FolderResource("loading");
212 loadingResource.setName("Loading....");
213 loadingResource.setShared(false);
214 RestResourceWrapper loading = new RestResourceWrapper(loadingResource);
215 model.getRootNodes().setList(Arrays.asList((RestResource)loading));
217 DeferredCommand.addCommand(new IncrementalCommand() {
220 public boolean execute() {
221 return fetchRootFolders();
226 public void updateNode(RestResource resource){
227 NodeInfo<RestResource> nodeInfo = (NodeInfo<RestResource>) getModel().getNodeInfo(resource);
230 if(nodeInfo.getValueUpdater()==null){}
232 nodeInfo.getValueUpdater().update(resource);
236 public void updateNodeChildren(final RestResource resource){
238 if(resource instanceof RestResourceWrapper){
239 boolean updated=false;
240 if(((RestResourceWrapper)resource).getResource().getFolders().size()==0){
241 if(((RestResourceWrapper)resource).getResource().getParentURI().equals(getMyFolders().getUri())){
242 updateNodeChildren(getMyFolders().getUri());
245 if(model.getMymap().get(((RestResourceWrapper)resource).getResource().getParentURI())!=null){
246 model.getMymap().get(((RestResourceWrapper)resource).getResource().getParentURI()).refresh(null);
249 if(model.getOthersmap().get(((RestResourceWrapper)resource).getResource().getParentURI())!=null){
250 model.getOthersmap().get(((RestResourceWrapper)resource).getResource().getParentURI()).refresh(null);
253 if(model.getSharedmap().get(((RestResourceWrapper)resource).getResource().getParentURI())!=null){
254 model.getSharedmap().get(((RestResourceWrapper)resource).getResource().getParentURI()).refresh(null);
258 if(utils.doesSharedNodeContainsResourceIn1stLevel(resource.getUri())){
259 updateMySharedNode();
261 else if(tree.getRootTreeNode().isChildOpen(2)){
262 utils.refreshNodeContainingResource(tree.getRootTreeNode().setChildOpen(2,true),resource.getUri());
269 utils.refreshNodeContainingResource(resource);
270 if(utils.doesSharedNodeContainsResourceIn1stLevel(resource.getUri())){
271 updateMySharedNode();
273 else if(tree.getRootTreeNode().isChildOpen(2)){
274 GWT.log("REFRESH THE OTHER WAY 2:"+resource);
275 utils.refreshNodeContainingResource(tree.getRootTreeNode().setChildOpen(2,true),resource.getUri());
279 public void updateNodeChildrenForRemove(final String resource){
280 GWT.log("********************************");
281 GWT.log("[UPDATENODECHILDREN]"+resource);
282 GWT.log("********************************");
283 boolean updated=false;
285 TreeNode sharedNode=null;
286 if(tree.getRootTreeNode().isChildOpen(0)){
287 node = utils.getNodeContainingResource2(tree.getRootTreeNode().setChildOpen(0,true), resource);
289 GWT.log("CHECK NODE1:"+node+" "+resource);
291 if(tree.getRootTreeNode().isChildOpen(2)){
292 GWT.log("CHECK NODE2:"+node);
294 node = utils.getNodeContainingResource2(tree.getRootTreeNode().setChildOpen(2,true), resource);
298 if(tree.getRootTreeNode().isChildOpen(3)){
299 GWT.log("CHECK NODE3:"+node);
300 node = utils.getNodeContainingResource2(tree.getRootTreeNode().setChildOpen(3,true), resource);
302 if(node != null && node.getValue() instanceof RestResourceWrapper){
303 GWT.log("*********************"+((RestResourceWrapper) node.getValue()).getResource().getFolders().size());
304 RestResourceWrapper wrapper = (RestResourceWrapper) node.getValue();
305 if(wrapper.getResource().countNotDeletedSubfolders()==1||wrapper.getResource().countNotDeletedSubfolders()==0){
306 updateNodeChildren(((RestResourceWrapper) node.getValue()).getResource().getParentURI());
307 if(((RestResourceWrapper) node.getValue()).getResource().getParentURI().equals(myFolders.getUri())){
308 if(utils.doesSharedNodeContainsResourceIn1stLevel(resource)||utils.doesSharedNodeContainsResourceIn2ndLevel(resource)){
309 updateMySharedNode();
315 updateNodeChildren(((RestResource) node.getValue()).getUri());
318 updateNodeChildren(resource);
320 public void updateNodeChildren(final String resource){
323 GWT.log("REFRESH THE OTHER WAY");
324 utils.refreshNodeContainingResource(resource);
325 if(utils.doesSharedNodeContainsResourceIn1stLevel(resource)||utils.doesSharedNodeContainsResourceIn2ndLevel(resource)){
326 GWT.log("REFRESH THE OTHER WAY 1:"+resource);
327 updateMySharedNode();
329 else if(tree.getRootTreeNode().isChildOpen(2)){
330 GWT.log("REFRESH THE OTHER WAY 2:"+resource);
331 utils.refreshNodeContainingResource(tree.getRootTreeNode().setChildOpen(2,true),resource);
335 protected void showPopup(final int x, final int y) {
336 if (selectionModel.getSelectedObject() == null)
340 // menu = new FolderContextMenu(images);
341 // menu.setPopupPosition(x, y);
344 private boolean init=false;
345 public boolean fetchRootFolders() {
346 UserResource userResource = app.getCurrentUserResource();
347 if (userResource == null)
350 final String path = userResource.getFilesPath();
351 GetCommand<FolderResource> gf = new GetCommand<FolderResource>(app, FolderResource.class, path, null) {
354 public void onComplete() {
355 myFolders = new MyFolderResource(getResult());
356 //selectionModel.setSelected(myFolders, true);
357 //rootNodes.setList(Arrays.asList((RestResource)rootResource));
358 //tree.getRootTreeNode().setChildOpen(0, true);
362 public void onError(Throwable t) {
363 GWT.log("Error fetching root folder", t);
364 app.displayError("Unable to fetch root folder");
368 DeferredCommand.addCommand(gf);
369 DeferredCommand.addCommand(new GetCommand<TrashResource>(app, TrashResource.class, app.getCurrentUserResource().getTrashPath(), null) {
371 public void onComplete() {
376 public void onError(Throwable t) {
377 if(t instanceof RestException){
378 int statusCode = ((RestException)t).getHttpStatusCode();
379 // On IE status code 1223 may be returned instead of 204.
380 if(statusCode == 204 || statusCode == 1223){
381 trash = new TrashResource(app.getCurrentUserResource().getTrashPath());
385 app.displayError("Unable to fetch trash folder:"+t.getMessage());
386 trash = new TrashResource(app.getCurrentUserResource().getTrashPath());
391 GetCommand<SharedResource> gs = new GetCommand<SharedResource>(app, SharedResource.class, userResource.getSharedPath(), null) {
394 public void onComplete() {
395 myshared=getResult();
399 public void onError(Throwable t) {
400 GWT.log("Error fetching Shared Root folder", t);
401 app.displayError("Unable to fetch Shared Root folder");
404 DeferredCommand.addCommand(gs);
405 GetCommand<OthersResource> go = new GetCommand<OthersResource>(app, OthersResource.class,
406 userResource.getOthersPath(), null) {
409 public void onComplete() {
410 others = getResult();
414 public void onError(Throwable t) {
415 GWT.log("Error fetching Others Root folder", t);
416 app.displayError("Unable to fetch Others Root folder");
419 DeferredCommand.addCommand(go);
421 if(myFolders==null||trash==null||myshared==null||others==null)
423 model.getRootNodes().setList(Arrays.asList((RestResource)myFolders,(RestResource)trash,(RestResource)myshared,(RestResource)others));
424 tree.getRootTreeNode().setChildOpen(0, true);
425 selectionModel.setSelected(myFolders, true);
429 public Images getImages() {
434 public void updateTrashNode(){
435 DeferredCommand.addCommand(new GetCommand<TrashResource>(app, TrashResource.class, app.getCurrentUserResource().getTrashPath(), null) {
437 public void onComplete() {
439 boolean trashIsOpen = tree.getRootTreeNode().isChildOpen(1);
440 model.getRootNodes().getList().set(1, trash);
441 model.getRootNodes().refresh();
442 tree.getRootTreeNode().setChildOpen(1, true);
446 public void onError(Throwable t) {
447 if(t instanceof RestException){
448 int statusCode = ((RestException)t).getHttpStatusCode();
449 // On IE status code 1223 may be returned instead of 204.
450 if(statusCode == 204 || statusCode == 1223){
451 trash = new TrashResource(app.getCurrentUserResource().getTrashPath());
452 model.getRootNodes().getList().set(1, trash);
453 //model.getRootNodes().refresh();
457 app.displayError("Unable to fetch trash folder:"+t.getMessage());
458 trash = new TrashResource(app.getCurrentUserResource().getTrashPath());
459 model.getRootNodes().getList().set(1, trash);
460 //model.getRootNodes().refresh();
467 public void updateRootNode(){
468 final String path = app.getCurrentUserResource().getFilesPath();
469 GetCommand<FolderResource> gf = new GetCommand<FolderResource>(app, FolderResource.class, path, null) {
472 public void onComplete() {
473 myFolders = new MyFolderResource(getResult());
474 model.getRootNodes().getList().set(0, myFolders);
475 model.getRootNodes().refresh();
476 tree.getRootTreeNode().setChildOpen(0, true);
481 public void onError(Throwable t) {
482 GWT.log("Error fetching root folder", t);
483 app.displayError("Unable to fetch root folder");
487 DeferredCommand.addCommand(gf);
490 public void updateMySharedNode(){
491 GetCommand<SharedResource> gs = new GetCommand<SharedResource>(app, SharedResource.class, app.getCurrentUserResource().getSharedPath(), null) {
494 public void onComplete() {
495 myshared=getResult();
496 model.getRootNodes().getList().set(2, myshared);
500 public void onError(Throwable t) {
501 GWT.log("Error fetching Shared Root folder", t);
502 app.displayError("Unable to fetch Shared Root folder");
505 DeferredCommand.addCommand(gs);
508 public void updateOtherNode(){
509 GetCommand<OthersResource> go = new GetCommand<OthersResource>(app, OthersResource.class,
510 app.getCurrentUserResource().getOthersPath(), null) {
513 public void onComplete() {
514 others = getResult();
515 model.getRootNodes().getList().set(3, others);
519 public void onError(Throwable t) {
520 GWT.log("Error fetching Others Root folder", t);
521 app.displayError("Unable to fetch Others Root folder");
524 DeferredCommand.addCommand(go);
528 public RestResource getSelection(){
529 return selectionModel.getSelectedObject();
532 public void clearSelection(){
533 if(app.getCurrentSelection().equals(getSelection()))
534 app.setCurrentSelection(null);
535 selectionModel.setSelected(getSelection(), false);
540 * Retrieve the myFolders.
542 * @return the myFolders
544 public MyFolderResource getMyFolders() {
550 * Retrieve the myshared.
552 * @return the myshared
554 public SharedResource getMyshared() {
560 * Retrieve the trash.
564 public TrashResource getTrash() {
570 * Retrieve the others.
574 public OthersResource getOthers() {
580 * Retrieve the model.
584 public TreeViewModel getModel() {
591 * Retrieve the utils.
595 public CellTreeViewUtils getUtils() {
599 public interface RefreshHandler{
604 public boolean isTrashOrTrashFolderSelected(){
605 return (getSelection() instanceof TrashResource) || (getSelection() instanceof TrashFolderResource);
608 public OtherUserResource getOtherUserResourceOfOtherFolder(OthersFolderResource res){
609 TreeNode n = utils.getNodeContainingResource(tree.getRootTreeNode().setChildOpen(3, true), res);
612 if(n.getValue() instanceof OtherUserResource)
613 return (OtherUserResource) n.getValue();
614 TreeNode parent = n.getParent();
616 while (parent!=null){
617 if(parent.getValue() instanceof OtherUserResource)
618 return (OtherUserResource) parent.getValue();
619 parent = parent.getParent();
625 public void refreshCurrentNode(boolean clearSelection){
626 NodeInfo<RestResource> nodeInfo = (NodeInfo<RestResource>) getModel().getNodeInfo(selectionModel.getSelectedObject());
627 if(nodeInfo==null || nodeInfo.getValueUpdater()==null){
628 app.showFileList(getSelection(),clearSelection);
632 ((ClearSelection)nodeInfo.getValueUpdater()).setClearSelection(clearSelection);
633 nodeInfo.getValueUpdater().update(selectionModel.getSelectedObject());