update correctly trash node on delete
[pithos] / src / gr / ebs / gss / client / CellTreeView.java
1 /*
2  * Copyright 2011 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.CellTreeViewModel.MyFolderDataProvider;
22 import gr.ebs.gss.client.rest.GetCommand;
23 import gr.ebs.gss.client.rest.RestException;
24 import gr.ebs.gss.client.rest.resource.FolderResource;
25 import gr.ebs.gss.client.rest.resource.MyFolderResource;
26 import gr.ebs.gss.client.rest.resource.OtherUserResource;
27 import gr.ebs.gss.client.rest.resource.OthersFolderResource;
28 import gr.ebs.gss.client.rest.resource.OthersResource;
29 import gr.ebs.gss.client.rest.resource.RestResource;
30 import gr.ebs.gss.client.rest.resource.RestResourceWrapper;
31 import gr.ebs.gss.client.rest.resource.SharedResource;
32 import gr.ebs.gss.client.rest.resource.TrashFolderResource;
33 import gr.ebs.gss.client.rest.resource.TrashResource;
34 import gr.ebs.gss.client.rest.resource.UserResource;
35 import gwtquery.plugins.draggable.client.DragAndDropManager;
36 import gwtquery.plugins.droppable.client.events.DragAndDropContext;
37 import gwtquery.plugins.droppable.client.events.OverDroppableEvent;
38 import gwtquery.plugins.droppable.client.events.OverDroppableEvent.OverDroppableEventHandler;
39 import gwtquery.plugins.droppable.client.gwt.DragAndDropCellTree;
40
41 import java.util.Arrays;
42
43 import com.google.gwt.core.client.GWT;
44 import com.google.gwt.event.logical.shared.AttachEvent;
45 import com.google.gwt.event.logical.shared.OpenEvent;
46 import com.google.gwt.event.logical.shared.OpenHandler;
47 import com.google.gwt.query.client.plugins.GQueryUi;
48 import com.google.gwt.resources.client.ClientBundle;
49 import com.google.gwt.resources.client.ImageResource;
50 import com.google.gwt.resources.client.ImageResource.ImageOptions;
51 import com.google.gwt.user.cellview.client.CellTree;
52 import com.google.gwt.user.cellview.client.TreeNode;
53 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
54 import com.google.gwt.user.client.DeferredCommand;
55 import com.google.gwt.user.client.Event;
56 import com.google.gwt.user.client.IncrementalCommand;
57 import com.google.gwt.user.client.Window;
58 import com.google.gwt.user.client.ui.Composite;
59 import com.google.gwt.user.client.ui.Tree;
60 import com.google.gwt.view.client.ProvidesKey;
61 import com.google.gwt.view.client.SelectionChangeEvent;
62 import com.google.gwt.view.client.SingleSelectionModel;
63 import com.google.gwt.view.client.TreeViewModel;
64 import com.google.gwt.view.client.SelectionChangeEvent.Handler;
65 import com.google.gwt.view.client.TreeViewModel.NodeInfo;
66
67
68 /**
69  * @author kman
70  *
71  */
72 public class CellTreeView extends Composite{
73         public static final boolean DONE = false;
74         Images images;
75         
76         SingleSelectionModel<RestResource> selectionModel = new SingleSelectionModel<RestResource>(new ProvidesKey<RestResource>() {
77
78                 @Override
79                 public Object getKey(RestResource item) {
80                         return item.getClass().getName()+":"+item.getUri();
81                 }});
82         FolderContextMenu menu;
83         
84         
85         MyFolderResource myFolders=null;
86         TrashResource trash = null;
87         SharedResource myshared = null;
88         OthersResource others = null;
89         
90         CellTreeViewModel model;
91         CellTreeViewUtils utils;
92         
93         public interface Images extends ClientBundle,Tree.Resources, FolderContextMenu.Images {
94
95         @Source("gr/ebs/gss/resources/folder_home.png")
96         ImageResource home();
97
98         @Source("gr/ebs/gss/resources/folder_yellow.png")
99         ImageResource folderYellow();
100
101         @Source("gr/ebs/gss/resources/mimetypes/document.png")
102         ImageResource document();
103
104         @Source("gr/ebs/gss/resources/internet.png")
105         ImageResource othersShared();
106
107         @Source("gr/ebs/gss/resources/edit_user.png")
108         ImageResource myShared();
109
110         @Source("gr/ebs/gss/resources/folder_user.png")
111         ImageResource sharedFolder();
112
113         @Source("gr/ebs/gss/resources/trashcan_empty.png")
114         ImageResource trash();
115         }
116         DragAndDropCellTree tree;
117         /*public interface BasicResources extends CellTree.BasicResources{
118                 @ImageOptions(flipRtl = true)
119             @Source("cellTreeLoadingBasic.gif")
120             ImageResource cellTreeLoading();
121                 
122                 @Source({"GssCellTreeBasic.css"})
123             CellTree.Style cellTreeStyle();
124         }*/
125         public interface BasicResources extends CellTree.Resources {
126
127             @ImageOptions(flipRtl = true)
128             @Source("cellTreeClosedItem.gif")
129             ImageResource cellTreeClosedItem();
130
131             @ImageOptions(flipRtl = true)
132             @Source("cellTreeLoadingBasic.gif")
133             ImageResource cellTreeLoading();
134
135             @ImageOptions(flipRtl = true)
136             @Source("cellTreeOpenItem.gif")
137             ImageResource cellTreeOpenItem();
138
139             //@Source({CellTree.Style.DEFAULT_CSS,"GssCellTreeBasic.css"})
140             @Source({"GssCellTreeBasic.css"})
141             CellTree.Style cellTreeStyle();
142           }
143         /**
144          * 
145          */
146         public CellTreeView(final Images _images) {
147                 images = _images;
148                 model = new CellTreeViewModel(images,selectionModel);
149             /*
150              * Create the tree using the model. We use <code>null</code> as the default
151              * value of the root node. The default value will be passed to
152              * CustomTreeModel#getNodeInfo();
153              */
154                 CellTree.Resources res = GWT.create(BasicResources.class);
155             tree = new DragAndDropCellTree(model,null, res){
156                 @Override
157                 public void onBrowserEvent(Event event) {
158                         // TODO Auto-generated method stub
159                         super.onBrowserEvent(event);
160                 }
161             };
162             utils=new CellTreeViewUtils(tree);
163             tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
164             /*tree.addOpenHandler(new OpenHandler<TreeNode>() {
165                         
166                         @Override
167                         public void onOpen(OpenEvent<TreeNode> event) {
168                                 Window.alert("[NODE OPENED]"+event.getTarget());
169                                 
170                         }
171                 });
172             tree.addOverDroppableHandler(new OverDroppableEventHandler() {
173                         
174                         @Override
175                         public void onOverDroppable(OverDroppableEvent event) {
176                                 GWT.log("OVER:"+event);
177                                 
178                         }
179                 });
180             tree.addAttachHandler(new AttachEvent.Handler() {
181                         
182                         @Override
183                         public void onAttachOrDetach(AttachEvent event) {
184                                 GWT.log("ATTACH:"+event.getSource());
185                                 
186                         }
187                 });*/
188             Handler selectionHandler = new SelectionChangeEvent.Handler() { 
189             @Override 
190             public void onSelectionChange(com.google.gwt.view.client.SelectionChangeEvent event) {
191                 NodeInfo<RestResource> nodeInfo = (NodeInfo<RestResource>) getModel().getNodeInfo(selectionModel.getSelectedObject());
192                 
193                 //GWT.log("SLECTED NODE INFO:"+nodeInfo+"   "+tree.getRootTreeNode().getChildValue(1));
194                 //((DefaultNodeInfo<RestResource>)nodeInfo).getValueUpdater().update(selectionModel.getSelectedObject());
195                 //if(nodeInfo.getProvidesKey() instanceof FolderDataProvider)
196                         //((FolderDataProvider)nodeInfo.getProvidesKey()).onRangeChanged(null);
197                 if(nodeInfo==null || nodeInfo.getValueUpdater()==null){}
198                         
199                 else
200                         nodeInfo.getValueUpdater().update(selectionModel.getSelectedObject());
201                 GSS.get().setCurrentSelection(selectionModel.getSelectedObject());
202                 GSS.get().showFileList(true);
203                 //tree.fireEvent(new OpenEvent<RestResource>(selectionModel.getSelectedObject()));
204                 
205             }
206         };
207         //OpenEvent<RestResource>.fire(tree, selectionModel.getSelectedObject());
208         selectionModel.addSelectionChangeHandler(selectionHandler);
209             sinkEvents(Event.ONCONTEXTMENU);
210                 sinkEvents(Event.ONMOUSEUP);
211             initWidget(tree);
212                 
213             DeferredCommand.addCommand(new IncrementalCommand() {
214
215                         @Override
216                         public boolean execute() {
217                                 return fetchRootFolders();
218                         }
219                 });
220         }
221         
222         public void updateNode(RestResource resource){
223                 NodeInfo<RestResource> nodeInfo = (NodeInfo<RestResource>) getModel().getNodeInfo(resource);
224                 
225                 if(nodeInfo!=null){
226                 if(nodeInfo.getValueUpdater()==null){}
227                 else
228                         nodeInfo.getValueUpdater().update(resource);
229         }
230         }
231         
232         public void updateNodeChildren(final RestResource resource){
233                 
234                 if(resource instanceof RestResourceWrapper){
235                         boolean updated=false;
236                         if(((RestResourceWrapper)resource).getResource().getFolders().size()==0){
237                                 if(((RestResourceWrapper)resource).getResource().getParentURI().equals(getMyFolders().getUri())){
238                                         updateNodeChildren(getMyFolders().getUri());
239                                         return;
240                                 }
241                                 if(model.getMymap().get(((RestResourceWrapper)resource).getResource().getParentURI())!=null){
242                                         model.getMymap().get(((RestResourceWrapper)resource).getResource().getParentURI()).refresh(null);
243                                         updated=true;
244                                 }
245                                 if(model.getOthersmap().get(((RestResourceWrapper)resource).getResource().getParentURI())!=null){
246                                         model.getOthersmap().get(((RestResourceWrapper)resource).getResource().getParentURI()).refresh(null);
247                                         updated=true;
248                                 }
249                                 if(model.getSharedmap().get(((RestResourceWrapper)resource).getResource().getParentURI())!=null){
250                                         model.getSharedmap().get(((RestResourceWrapper)resource).getResource().getParentURI()).refresh(null);
251                                         updated=true;
252                                 }
253                                 if(updated){
254                                         if(utils.doesSharedNodeContainsResourceIn1stLevel(resource.getUri())){
255                                                 updateMySharedNode();
256                                         }
257                                         //return;
258                                 }
259                         }
260                 }
261                 
262                 utils.refreshNodeContainingResource(resource);
263                 if(utils.doesSharedNodeContainsResourceIn1stLevel(resource.getUri())){
264                         updateMySharedNode();
265                 }
266                 
267         }
268         public void updateNodeChildrenForRemove(final String resource){
269                 GWT.log("********************************");
270                 GWT.log("[UPDATENODECHILDREN]"+resource);
271                 GWT.log("********************************");
272                 boolean updated=false;
273                 TreeNode node=null;
274                 if(tree.getRootTreeNode().isChildOpen(0)){
275                         node = utils.getNodeContainingResource2(tree.getRootTreeNode().setChildOpen(0,true), resource);
276                 }
277                         GWT.log("CHECK NODE1:"+node+" "+resource);
278                         if(node==null)
279                                 if(tree.getRootTreeNode().isChildOpen(2)){
280                                         GWT.log("CHECK NODE2:"+node);
281                                         node = utils.getNodeContainingResource2(tree.getRootTreeNode().setChildOpen(2,true), resource);
282                                 }
283                         if(node==null)
284                                 if(tree.getRootTreeNode().isChildOpen(3)){
285                                         GWT.log("CHECK NODE3:"+node);
286                                         node = utils.getNodeContainingResource2(tree.getRootTreeNode().setChildOpen(3,true), resource);
287                                 }
288                         
289                         if(node != null && node.getValue() instanceof RestResourceWrapper){
290                                 GWT.log("*********************"+((RestResourceWrapper) node.getValue()).getResource().getFolders().size());
291                                 RestResourceWrapper wrapper  = (RestResourceWrapper) node.getValue();
292                                 if(wrapper.getResource().countNotDeletedSubfolders()==1||wrapper.getResource().countNotDeletedSubfolders()==0)
293                                         updateNodeChildren(((RestResourceWrapper) node.getValue()).getResource().getParentURI());
294                                 else
295                                         updateNodeChildren(((RestResource) node.getValue()).getUri());
296                                 return;
297                                 /*GWT.log("INSIDE:"+node);
298                                 RestResourceWrapper rw = (RestResourceWrapper) node.getValue();
299                                 //if(rw.getResource().getFolders().size()==0){
300                                         if(model.getMymap().get(rw.getResource().getUri())!=null){
301                                                 model.getMymap().get(rw.getResource().getUri()).refresh(null);
302                                                 updated=true;
303                                         }
304                                         if(model.getOthersmap().get(rw.getResource().getUri())!=null){
305                                                 model.getOthersmap().get(rw.getResource().getUri()).refresh(null);
306                                                 updated=true;
307                                         }
308                                         if(model.getSharedmap().get(rw.getResource().getUri())!=null){
309                                                 model.getSharedmap().get(rw.getResource().getUri()).refresh(null);
310                                                 updated=true;
311                                         }
312                                         if(updated){
313                                                 if(doesSharedNodeContainsResourceIn1stLevel(resource)){
314                                                         updateMySharedNode();
315                                                 }
316                                                 return;
317                                         }
318                                 }
319                         //}*/
320                         
321                 }
322                         updateNodeChildren(resource);
323         }
324         public void updateNodeChildren(final String resource){
325                 
326                         
327                 GWT.log("REFRESH THE OTHER WAY");
328                 utils.refreshNodeContainingResource(resource);
329                 if(utils.doesSharedNodeContainsResourceIn1stLevel(resource)){
330                         updateMySharedNode();
331                 }
332         }
333         
334         protected void showPopup(final int x, final int y) {
335                 if (selectionModel.getSelectedObject() == null)
336                         return;
337                 if (menu != null)
338                         menu.hide();
339                 menu = new FolderContextMenu(images);
340                 menu.setPopupPosition(x, y);
341                 menu.show();
342         }
343         private boolean init=false;
344         public boolean fetchRootFolders() {
345                 UserResource userResource = GSS.get().getCurrentUserResource();
346                 if (userResource == null)
347                         return !DONE;
348                 if(!init){
349                         final String path = userResource.getFilesPath();
350                         GetCommand<FolderResource> gf = new GetCommand<FolderResource>(FolderResource.class, path, null) {
351         
352                                 @Override
353                                 public void onComplete() {
354                                         myFolders = new MyFolderResource(getResult());
355                                         //selectionModel.setSelected(myFolders, true);
356                                         //rootNodes.setList(Arrays.asList((RestResource)rootResource));
357                                         //tree.getRootTreeNode().setChildOpen(0, true);
358                                 }
359         
360                                 @Override
361                                 public void onError(Throwable t) {
362                                         GWT.log("Error fetching root folder", t);
363                                         GSS.get().displayError("Unable to fetch root folder");
364                                 }
365         
366                         };
367                         DeferredCommand.addCommand(gf);
368                         DeferredCommand.addCommand(new GetCommand<TrashResource>(TrashResource.class, GSS.get().getCurrentUserResource().getTrashPath(), null) {
369                                 @Override
370                                 public void onComplete() {
371                                         trash = getResult();
372                                 }
373
374                                 @Override
375                                 public void onError(Throwable t) {
376                                         if(t instanceof RestException){
377                                                 int statusCode = ((RestException)t).getHttpStatusCode();
378                                                 // On IE status code 1223 may be returned instead of 204.
379                                                 if(statusCode == 204 || statusCode == 1223){
380                                                         trash = new TrashResource(GSS.get().getCurrentUserResource().getTrashPath());
381                                         }
382                                         else{
383                                                 GWT.log("", t);
384                                                 GSS.get().displayError("Unable to fetch trash folder:"+t.getMessage());
385                                                 trash = new TrashResource(GSS.get().getCurrentUserResource().getTrashPath());
386                                         }
387                                 }
388                         }
389                         });
390                         GetCommand<SharedResource> gs = new GetCommand<SharedResource>(SharedResource.class, userResource.getSharedPath(), null) {
391
392                                 @Override
393                                 public void onComplete() {
394                                         myshared=getResult();
395                                 }
396
397                                 @Override
398                                 public void onError(Throwable t) {
399                                         GWT.log("Error fetching Shared Root folder", t);
400                                         GSS.get().displayError("Unable to fetch Shared Root folder");
401                                 }
402                         };
403                         DeferredCommand.addCommand(gs);
404                         GetCommand<OthersResource> go = new GetCommand<OthersResource>(OthersResource.class,
405                                                 userResource.getOthersPath(), null) {
406
407                                 @Override
408                                 public void onComplete() {
409                                         others = getResult();
410                                         GSS.get().removeGlassPanel();
411                                 }
412
413                                 @Override
414                                 public void onError(Throwable t) {
415                                         GWT.log("Error fetching Others Root folder", t);
416                                         GSS.get().displayError("Unable to fetch Others Root folder");
417                                 }
418                         };
419                         DeferredCommand.addCommand(go);
420                 }
421                 if(myFolders==null||trash==null||myshared==null||others==null)
422                         return !DONE;
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);
426                 return DONE;
427         }
428
429         public Images getImages() {
430                 return images;
431         }
432         
433         
434         public void updateTrashNode(){
435                 DeferredCommand.addCommand(new GetCommand<TrashResource>(TrashResource.class, GSS.get().getCurrentUserResource().getTrashPath(), null) {
436                         @Override
437                         public void onComplete() {
438                                 trash = getResult();
439                                 model.getRootNodes().getList().set(1, trash);
440                                 //model.getRootNodes().refresh();
441                         }
442
443                         @Override
444                         public void onError(Throwable t) {
445                                 if(t instanceof RestException){
446                                         int statusCode = ((RestException)t).getHttpStatusCode();
447                                         // On IE status code 1223 may be returned instead of 204.
448                                         if(statusCode == 204 || statusCode == 1223){
449                                                 trash = new TrashResource(GSS.get().getCurrentUserResource().getTrashPath());
450                                                 model.getRootNodes().getList().set(1, trash);
451                                                 //model.getRootNodes().refresh();
452                                 }
453                                 else{
454                                         GWT.log("", t);
455                                         GSS.get().displayError("Unable to fetch trash folder:"+t.getMessage());
456                                         trash = new TrashResource(GSS.get().getCurrentUserResource().getTrashPath());
457                                         model.getRootNodes().getList().set(1, trash);
458                                         //model.getRootNodes().refresh();
459                                 }
460                         }
461                 }
462                 });
463         }
464         
465         public void updateRootNode(){
466                 final String path = GSS.get().getCurrentUserResource().getFilesPath();
467                 GetCommand<FolderResource> gf = new GetCommand<FolderResource>(FolderResource.class, path, null) {
468
469                         @Override
470                         public void onComplete() {
471                                 myFolders = new MyFolderResource(getResult());
472                                 model.getRootNodes().getList().set(0, myFolders);
473                                 model.getRootNodes().refresh();
474                                 tree.getRootTreeNode().setChildOpen(0, true);
475                                 
476                         }
477
478                         @Override
479                         public void onError(Throwable t) {
480                                 GWT.log("Error fetching root folder", t);
481                                 GSS.get().displayError("Unable to fetch root folder");
482                         }
483
484                 };
485                 DeferredCommand.addCommand(gf);
486         }
487         
488         public void updateMySharedNode(){
489                 GetCommand<SharedResource> gs = new GetCommand<SharedResource>(SharedResource.class, GSS.get().getCurrentUserResource().getSharedPath(), null) {
490
491                         @Override
492                         public void onComplete() {
493                                 myshared=getResult();
494                                 model.getRootNodes().getList().set(2, myshared);
495                         }
496
497                         @Override
498                         public void onError(Throwable t) {
499                                 GWT.log("Error fetching Shared Root folder", t);
500                                 GSS.get().displayError("Unable to fetch Shared Root folder");
501                         }
502                 };
503                 DeferredCommand.addCommand(gs);
504         }
505         
506         public void updateOtherNode(){
507                 GetCommand<OthersResource> go = new GetCommand<OthersResource>(OthersResource.class,
508                                         GSS.get().getCurrentUserResource().getOthersPath(), null) {
509
510                         @Override
511                         public void onComplete() {
512                                 others = getResult();
513                                 model.getRootNodes().getList().set(3, others);
514                         }
515
516                         @Override
517                         public void onError(Throwable t) {
518                                 GWT.log("Error fetching Others Root folder", t);
519                                 GSS.get().displayError("Unable to fetch Others Root folder");
520                         }
521                 };
522                 DeferredCommand.addCommand(go);
523         }
524         
525         
526         public RestResource getSelection(){
527                 return selectionModel.getSelectedObject();
528         }
529         
530         public void clearSelection(){
531                 if(GSS.get().getCurrentSelection().equals(getSelection()))
532                         GSS.get().setCurrentSelection(null);
533                 selectionModel.setSelected(getSelection(), false);
534         }
535         
536         
537         /**
538          * Retrieve the myFolders.
539          *
540          * @return the myFolders
541          */
542         public MyFolderResource getMyFolders() {
543                 return myFolders;
544         }
545         
546         
547         /**
548          * Retrieve the myshared.
549          *
550          * @return the myshared
551          */
552         public SharedResource getMyshared() {
553                 return myshared;
554         }
555         
556         
557         /**
558          * Retrieve the trash.
559          *
560          * @return the trash
561          */
562         public TrashResource getTrash() {
563                 return trash;
564         }
565         
566         
567         /**
568          * Retrieve the others.
569          *
570          * @return the others
571          */
572         public OthersResource getOthers() {
573                 return others;
574         }
575         
576         
577         /**
578          * Retrieve the model.
579          *
580          * @return the model
581          */
582         public TreeViewModel getModel() {
583                 return model;
584         }
585         
586         
587         
588         /**
589          * Retrieve the utils.
590          *
591          * @return the utils
592          */
593         public CellTreeViewUtils getUtils() {
594                 return utils;
595         }
596         
597         public interface RefreshHandler{
598                 void onRefresh();               
599         }
600         
601         
602         public boolean isTrashOrTrashFolderSelected(){
603                 return (getSelection() instanceof TrashResource) || (getSelection() instanceof TrashFolderResource);
604         }
605         
606         public OtherUserResource getOtherUserResourceOfOtherFolder(OthersFolderResource res){
607                 TreeNode n = utils.getNodeContainingResource(tree.getRootTreeNode().setChildOpen(3, true), res);
608                 
609                 if(n!=null){
610                         if(n.getValue() instanceof OtherUserResource)
611                                 return (OtherUserResource) n.getValue();
612                         TreeNode parent = n.getParent();
613                         
614                         while (parent!=null){
615                                 if(parent.getValue() instanceof OtherUserResource)
616                                         return (OtherUserResource) parent.getValue();
617                                 parent = parent.getParent();
618                         }
619                 }
620                 return null;
621         }
622         
623         
624 }