2 * Copyright 2011 Electronic Business Systems Ltd.
4 * This file is part of GSS.
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.
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.
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/>.
19 package gr.ebs.gss.client;
21 import static com.google.gwt.query.client.GQuery.$;
22 import gr.ebs.gss.client.CellTreeView.Images;
23 import gr.ebs.gss.client.CellTreeView.RefreshHandler;
24 import gr.ebs.gss.client.rest.GetCommand;
25 import gr.ebs.gss.client.rest.MultipleGetCommand;
26 import gr.ebs.gss.client.rest.RestException;
27 import gr.ebs.gss.client.rest.resource.FileResource;
28 import gr.ebs.gss.client.rest.resource.FolderResource;
29 import gr.ebs.gss.client.rest.resource.MyFolderResource;
30 import gr.ebs.gss.client.rest.resource.OtherUserResource;
31 import gr.ebs.gss.client.rest.resource.OthersFolderResource;
32 import gr.ebs.gss.client.rest.resource.OthersResource;
33 import gr.ebs.gss.client.rest.resource.RestResource;
34 import gr.ebs.gss.client.rest.resource.RestResourceWrapper;
35 import gr.ebs.gss.client.rest.resource.SharedFolderResource;
36 import gr.ebs.gss.client.rest.resource.SharedResource;
37 import gr.ebs.gss.client.rest.resource.TrashFolderResource;
38 import gr.ebs.gss.client.rest.resource.TrashResource;
39 import gwtquery.plugins.draggable.client.DragAndDropManager;
40 import gwtquery.plugins.draggable.client.DraggableOptions;
41 import gwtquery.plugins.draggable.client.DraggableOptions.CursorAt;
42 import gwtquery.plugins.draggable.client.DraggableOptions.DragFunction;
43 import gwtquery.plugins.draggable.client.DraggableOptions.RevertOption;
44 import gwtquery.plugins.draggable.client.events.DragContext;
45 import gwtquery.plugins.droppable.client.DroppableOptions;
46 import gwtquery.plugins.droppable.client.DroppableOptions.DroppableFunction;
47 import gwtquery.plugins.droppable.client.events.DragAndDropContext;
48 import gwtquery.plugins.droppable.client.gwt.DragAndDropNodeInfo;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.HashMap;
53 import java.util.List;
56 import com.google.gwt.cell.client.AbstractCell;
57 import com.google.gwt.cell.client.Cell;
58 import com.google.gwt.cell.client.ValueUpdater;
59 import com.google.gwt.core.client.GWT;
60 import com.google.gwt.dom.client.Style.Cursor;
61 import com.google.gwt.query.client.plugins.GQueryUi;
62 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
63 import com.google.gwt.safehtml.shared.SafeHtml;
64 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
65 import com.google.gwt.user.client.DeferredCommand;
66 import com.google.gwt.user.client.Window;
67 import com.google.gwt.user.client.ui.AbstractImagePrototype;
68 import com.google.gwt.view.client.AsyncDataProvider;
69 import com.google.gwt.view.client.HasData;
70 import com.google.gwt.view.client.ListDataProvider;
71 import com.google.gwt.view.client.ProvidesKey;
72 import com.google.gwt.view.client.SingleSelectionModel;
73 import com.google.gwt.view.client.TreeViewModel;
81 public class CellTreeViewModel implements TreeViewModel{
82 private final ListDataProvider<RestResource> rootNodes = new ListDataProvider<RestResource>();
83 private Map<String,FolderResource> folderCache=new HashMap<String, FolderResource>();
85 SingleSelectionModel<RestResource> selectionModel;
86 Map<String, MyFolderDataProvider> mymap = new HashMap<String, MyFolderDataProvider>();
87 Map<String, MyFolderDataProvider> sharedmap = new HashMap<String, MyFolderDataProvider>();
88 Map<String, MyFolderDataProvider> othersmap = new HashMap<String, MyFolderDataProvider>();
89 static interface Templates extends SafeHtmlTemplates {
90 Templates INSTANCE = GWT.create(Templates.class);
92 @Template(" <div id='dragHelper' class='{0}'></div>")
93 SafeHtml outerHelper(String cssClassName);
96 static void configureDragOperation(DraggableOptions options) {
98 // set a custom element as drag helper. The content of the helper will be
99 // set when the drag will start
100 options.setHelper($(Templates.INSTANCE.outerHelper(
101 "drag").asString()));
102 // opacity of the drag helper
103 options.setOpacity((float) 0.9);
104 // cursor during the drag operation
105 options.setCursor(Cursor.MOVE);
106 // the cell being greater than the helper, force the position of the
107 // helper on the mouse cursor.
108 options.setCursorAt(new CursorAt(10, 10, null, null));
109 // append the helper to the body element
110 options.setAppendTo("body");
111 // set the revert option
112 options.setRevert(RevertOption.ON_INVALID_DROP);
113 // use a Function to fill the content of the helper
114 // we could also add a DragStartEventHandler on the DragAndDropTreeCell and
115 // DragAndDropCellList.
116 options.setOnDragStart(new DragFunction() {
117 public void f(DragContext context) {
118 RestResourceWrapper memberInfo = context.getDraggableData();
119 context.getHelper().setInnerHTML(memberInfo.getName());
128 public CellTreeViewModel(final Images _images,SingleSelectionModel<RestResource> selectionModel ) {
131 this.selectionModel=selectionModel;
134 private final Cell<RestResource> departmentCell = new AbstractCell<RestResource>("contextmenu"){
137 public void render(com.google.gwt.cell.client.Cell.Context arg0, RestResource arg1, SafeHtmlBuilder arg2) {
141 if(arg1 instanceof TrashFolderResource){
142 html = AbstractImagePrototype.create(images.folderYellow()).getHTML();
143 FolderResource res = ((RestResourceWrapper)arg1).getResource();
144 name = res.getName();
145 id = res.getParentName() +"."+name;
147 else if(arg1 instanceof RestResourceWrapper){
148 FolderResource res = ((RestResourceWrapper)arg1).getResource();
150 html = AbstractImagePrototype.create(images.sharedFolder()).getHTML();
151 else if(res.getParentName()==null){
152 html = AbstractImagePrototype.create(images.home()).getHTML();
155 html = AbstractImagePrototype.create(images.folderYellow()).getHTML();
156 name = res.getName();
157 if(res.getParentName() != null){
158 id = res.getParentName()+"."+name;
164 else if(arg1 instanceof TrashResource){
165 html = AbstractImagePrototype.create(images.trash()).getHTML();
170 else if(arg1 instanceof SharedResource){
171 html = AbstractImagePrototype.create(images.myShared()).getHTML();
175 else if(arg1 instanceof OthersResource){
176 html = AbstractImagePrototype.create(images.othersShared()).getHTML();
177 name = "Other's Shared";
180 else if(arg1 instanceof OtherUserResource){
181 html = AbstractImagePrototype.create(images.permUser()).getHTML();
182 name = ((OtherUserResource)arg1).getName();
185 arg2.appendHtmlConstant(html);
186 arg2.appendHtmlConstant("<span id='"+id +"'"+ " class='papala'>");
187 arg2.appendEscaped(name);
188 arg2.appendHtmlConstant("</span>");
191 public void onBrowserEvent(Cell.Context context, com.google.gwt.dom.client.Element parent, RestResource value, com.google.gwt.dom.client.NativeEvent event, com.google.gwt.cell.client.ValueUpdater<RestResource> valueUpdater) {
192 if(event.getType().equals("contextmenu")){
193 selectionModel.setSelected(value, true);
194 GSS.get().getTreeView().showPopup(event.getClientX(), event.getClientY());
202 public <T> NodeInfo<?> getNodeInfo(final T value) {
205 return new DragAndDropNodeInfo<RestResource>(getRootNodes(), departmentCell,
206 selectionModel, null);
208 else if (value instanceof MyFolderResource) {
210 MyFolderDataProvider dataProvider = new MyFolderDataProvider(
211 ((MyFolderResource) value),MyFolderResource.class);
212 DragAndDropNodeInfo<RestResource> n = new DragAndDropNodeInfo<RestResource>(dataProvider, departmentCell,
213 selectionModel, new ResourceValueUpdater());
215 //nodeInfos.put(((MyFolderResource) value).getUri(), n);
216 mymap.put(((MyFolderResource) value).getUri(), dataProvider);
217 DroppableOptions options = n.getDroppableOptions();
218 options.setDroppableHoverClass("droppableHover");
219 // use a DroppableFunction here. We can also add a DropHandler in the tree
221 options.setOnOver(new DroppableFunction() {
224 public void f(final DragAndDropContext context) {
225 if(context.getDroppableData()!=null && context.getDroppableData() instanceof RestResource){
226 GSS.get().getTreeView().getUtils().openNodeContainingResource((RestResource) context.getDroppableData(), new RefreshHandler() {
229 public void onRefresh() {
231 DragAndDropManager.getInstance().initialize(context, GQueryUi.Event.create(com.google.gwt.user.client.Event.getCurrentEvent()));
242 options.setOnDrop(new DroppableFunction() {
244 public void f(DragAndDropContext context) {
246 DnDFolderPopupMenu popup ;
247 if(context.getDraggableData() instanceof FileResource){
248 popup = new DnDFolderPopupMenu(images, ((MyFolderResource) context.getDroppableData()).getResource(), Arrays.asList(context.getDraggableData()));
251 popup = new DnDFolderPopupMenu(images, ((MyFolderResource) context.getDroppableData()).getResource(), context.getDraggableData());
252 int left = context.getDroppable().getAbsoluteLeft() + 40;
253 int top = context.getDroppable().getAbsoluteTop() + 20;
254 popup.setPopupPosition(left, top);
259 // permission cell are not draggable
260 //n.setCellDroppableOnly();
261 configureDragOperation(n.getDraggableOptions());
265 else if (value instanceof SharedResource) {
267 MyFolderDataProvider dataProvider = new MyFolderDataProvider(
268 ((SharedResource) value), SharedFolderResource.class);
269 sharedmap.put(((SharedResource) value).getUri(), dataProvider);
270 return new DragAndDropNodeInfo<RestResource>(dataProvider, departmentCell,
271 selectionModel, new ResourceValueUpdater());
273 else if (value instanceof TrashResource) {
275 ListDataProvider<RestResource> trashProvider = new ListDataProvider<RestResource>();
276 List<RestResource> r = new ArrayList<RestResource>();
277 for(FolderResource f : GSS.get().getTreeView().getTrash().getFolders()){
278 r.add(new TrashFolderResource(f));
280 trashProvider.setList(r);
281 return new DragAndDropNodeInfo<RestResource>(trashProvider, departmentCell,
282 selectionModel, new ResourceValueUpdater());
284 else if (value instanceof OthersResource) {
286 OthersDataProvider dataProvider = new OthersDataProvider(
287 ((OthersResource) value), SharedFolderResource.class);
288 return new DragAndDropNodeInfo<RestResource>(dataProvider, departmentCell,
289 selectionModel, null);
291 else if (value instanceof SharedFolderResource) {
293 MyFolderDataProvider dataProvider = new MyFolderDataProvider(
294 ((SharedFolderResource) value),SharedFolderResource.class);
295 DragAndDropNodeInfo<RestResource> n = new DragAndDropNodeInfo<RestResource>(dataProvider, departmentCell,
296 selectionModel, new ResourceValueUpdater());
297 sharedmap.put(((SharedFolderResource) value).getUri(), dataProvider);
298 DroppableOptions options = n.getDroppableOptions();
299 options.setDroppableHoverClass("droppableHover");
300 // use a DroppableFunction here. We can also add a DropHandler in the tree
302 options.setOnDrop(new DroppableFunction() {
304 public void f(DragAndDropContext context) {
309 // permission cell are not draggable
310 n.setCellDroppableOnly();
313 else if (value instanceof OthersFolderResource) {
315 MyFolderDataProvider dataProvider = new MyFolderDataProvider(
316 ((OthersFolderResource) value),OthersFolderResource.class);
317 DragAndDropNodeInfo<RestResource> n = new DragAndDropNodeInfo<RestResource>(dataProvider, departmentCell,
318 selectionModel, new ResourceValueUpdater());
319 //nodeInfos.put(((OthersFolderResource) value).getUri(), n);
320 othersmap.put(((SharedFolderResource) value).getUri(), dataProvider);
321 DroppableOptions options = n.getDroppableOptions();
322 options.setDroppableHoverClass("droppableHover");
323 // use a DroppableFunction here. We can also add a DropHandler in the tree
325 options.setOnDrop(new DroppableFunction() {
327 public void f(DragAndDropContext context) {
332 // permission cell are not draggable
333 n.setCellDroppableOnly();
336 else if (value instanceof OtherUserResource) {
338 MyFolderDataProvider dataProvider = new MyFolderDataProvider(
339 ((OtherUserResource) value),OthersFolderResource.class);
340 DragAndDropNodeInfo<RestResource> n = new DragAndDropNodeInfo<RestResource>(dataProvider, departmentCell,
341 selectionModel, new ResourceValueUpdater());
342 //nodeInfos.put(((OtherUserResource) value).getUri(), n);
343 DroppableOptions options = n.getDroppableOptions();
344 options.setDroppableHoverClass("droppableHover");
345 // use a DroppableFunction here. We can also add a DropHandler in the tree
347 options.setOnDrop(new DroppableFunction() {
349 public void f(DragAndDropContext context) {
354 // permission cell are not draggable
355 n.setCellDroppableOnly();
358 // TODO Auto-generated method stub
363 public boolean isLeaf(Object value) {
364 if(value instanceof RestResourceWrapper)
365 return ((RestResourceWrapper)value).getResource().getFolders().size()==0;
366 else if(value instanceof TrashResource)
367 return ((TrashResource)value).getFolders().size()==0;
368 else if(value instanceof SharedResource)
369 return ((SharedResource)value).getFolders().size()==0;
370 else if(value instanceof OthersResource)
371 return ((OthersResource)value).getOtherUsers().size()==0;
372 else if(value instanceof OtherUserResource)
373 return ((OtherUserResource)value).getFolders().size()==0;
377 class ResourceValueUpdater implements ValueUpdater<RestResource>{
380 public void update(final RestResource value) {
381 if(value instanceof MyFolderResource){
382 GetCommand<FolderResource> gf = new GetCommand<FolderResource>(FolderResource.class, value.getUri(), null) {
385 public void onComplete() {
386 FolderResource rootResource = getResult();
387 //((MyFolderResource)value).getResource().setFiles(rootResource.getFiles());
388 ((MyFolderResource)value).setResource(rootResource);
389 if(GSS.get().getTreeView().getSelection().getUri().equals(value.getUri()))
390 selectionModel.setSelected(value, true);
391 GSS.get().onResourceUpdate(value);
396 public void onError(Throwable t) {
397 GWT.log("Error fetching root folder", t);
398 GSS.get().displayError("Unable to fetch root folder");
402 DeferredCommand.addCommand(gf);
404 else if(value instanceof TrashResource){
405 DeferredCommand.addCommand(new GetCommand<TrashResource>(TrashResource.class, GSS.get().getCurrentUserResource().getTrashPath(), null) {
407 public void onComplete() {
408 //trash = getResult();
409 for(RestResource r : getRootNodes().getList()){
410 if(r instanceof TrashResource)
411 getRootNodes().getList().set(getRootNodes().getList().indexOf(r),GSS.get().getTreeView().getTrash());
413 GSS.get().getTreeView().updateNodeChildren(GSS.get().getTreeView().getTrash());
417 public void onError(Throwable t) {
418 if(t instanceof RestException){
419 int statusCode = ((RestException)t).getHttpStatusCode();
420 // On IE status code 1223 may be returned instead of 204.
421 if(statusCode == 204 || statusCode == 1223){
422 //trash = new TrashResource(GSS.get().getCurrentUserResource().getTrashPath());
426 GSS.get().displayError("Unable to fetch trash folder:"+t.getMessage());
427 //GSS.get().getTreeView().getTrash() = new TrashResource(GSS.get().getCurrentUserResource().getTrashPath());
433 else if(value instanceof OthersFolderResource){
440 class MyFolderDataProvider extends AsyncDataProvider<RestResource>{
441 private RestResource restResource;
442 private Class resourceClass;
443 public MyFolderDataProvider(RestResource department, Class resourceClass) {
444 super(new ProvidesKey<RestResource>() {
447 public Object getKey(RestResource item) {
448 return item.getUri();
450 this.restResource = department;
451 this.resourceClass=resourceClass;
452 //CellTreeView.this.mymap.put(department.getUri(), MyFolderDataProvider.this);
456 protected void onRangeChanged(final HasData<RestResource> view) {
461 * Retrieve the restResource.
463 * @return the restResource
465 public RestResource getRestResource() {
471 * Modify the restResource.
473 * @param restResource the restResource to set
475 public void setRestResource(RestResource restResource) {
476 this.restResource = restResource;
478 List<RestResource> res =null;
479 public void refresh(final RefreshHandler refresh){
480 FolderResource cache = null;
481 if(restResource instanceof RestResourceWrapper && !((RestResourceWrapper)restResource).getResource().isNeedsExpanding())
482 cache = ((RestResourceWrapper)restResource).getResource();
483 GetCommand<FolderResource> gf = new GetCommand<FolderResource>(FolderResource.class, restResource.getUri(),cache ) {
486 public void onComplete() {
487 if(restResource instanceof RestResourceWrapper){
488 ((RestResourceWrapper)restResource).setResource(getResult());//restResource = getResult();
489 ((RestResourceWrapper)restResource).getResource().setNeedsExpanding(false);
491 if(usedCachedVersion()&&res!=null){
493 updateRowCount(res.size(), true);
494 updateRowData(0,res);
498 String[] folderPaths = null;
499 if(resourceClass.equals(MyFolderResource.class))
500 folderPaths=((MyFolderResource) restResource).getResource().getSubfolderPaths().toArray(new String[] {});
501 else if(resourceClass.equals(SharedFolderResource.class) && restResource instanceof SharedResource)
502 folderPaths=((SharedResource) restResource).getSubfolderPaths().toArray(new String[] {});
503 else if(resourceClass.equals(SharedFolderResource.class)){
504 folderPaths=((SharedFolderResource) restResource).getResource().getSubfolderPaths().toArray(new String[] {});
505 GWT.log("------------>"+folderPaths);
507 else if(resourceClass.equals(TrashFolderResource.class))
508 folderPaths=((TrashFolderResource) restResource).getResource().getSubfolderPaths().toArray(new String[] {});
509 else if(resourceClass.equals(OthersFolderResource.class) && restResource instanceof OtherUserResource)
510 folderPaths=((OtherUserResource) restResource).getSubfolderPaths().toArray(new String[] {});
511 else if(resourceClass.equals(OthersFolderResource.class))
512 folderPaths=((OthersFolderResource) restResource).getResource().getSubfolderPaths().toArray(new String[] {});
513 MultipleGetCommand.Cached[] cached = null;
514 if(restResource instanceof RestResourceWrapper)
515 cached=((RestResourceWrapper)restResource).getResource().getCache();
516 MultipleGetCommand<FolderResource> gf2 = new MultipleGetCommand<FolderResource>(FolderResource.class,
517 folderPaths, cached) {
520 public void onComplete() {
521 res = new ArrayList<RestResource>();
522 for(FolderResource r : getResult()){
526 else if(resourceClass.equals(MyFolderResource.class))
527 res.add(new MyFolderResource(r));
528 else if(resourceClass.equals(SharedFolderResource.class)){
529 res.add(new SharedFolderResource(r));
531 else if(resourceClass.equals(TrashFolderResource.class))
532 res.add(new TrashFolderResource(r));
533 else if(resourceClass.equals(OthersFolderResource.class))
534 res.add(new OthersFolderResource(r));
536 if(restResource instanceof RestResourceWrapper)
537 ((RestResourceWrapper)restResource).getResource().setFolders(getResult());
538 updateRowCount(res.size(), true);
539 updateRowData(0,res);
545 public void onError(Throwable t) {
546 GSS.get().displayError("Unable to fetch subfolders");
547 GWT.log("Unable to fetch subfolders", t);
551 public void onError(String p, Throwable throwable) {
552 GWT.log("Path:"+p, throwable);
556 DeferredCommand.addCommand(gf2);
561 public void onError(Throwable t) {
563 GWT.log("Error fetching root folder", t);
564 GSS.get().displayError("Unable to fetch root folder");
568 DeferredCommand.addCommand(gf);
573 class OthersDataProvider extends AsyncDataProvider<RestResource>{
574 private RestResource restResource;
575 private Class resourceClass;
576 public OthersDataProvider(RestResource department, Class resourceClass) {
577 super(new ProvidesKey<RestResource>() {
580 public Object getKey(RestResource item) {
581 return item.getUri();
583 this.restResource = department;
584 this.resourceClass=resourceClass;
585 //CellTreeView.this.mymap.put(department.getUri(), OthersDataProvider.this);
589 protected void onRangeChanged(final HasData<RestResource> view) {
594 * Retrieve the restResource.
596 * @return the restResource
598 public RestResource getRestResource() {
604 * Modify the restResource.
606 * @param restResource the restResource to set
608 public void setRestResource(RestResource restResource) {
609 this.restResource = restResource;
612 public void refresh(final RefreshHandler refresh){
613 GetCommand<OthersResource> go = new GetCommand<OthersResource>(OthersResource.class,
614 restResource.getUri(), null) {
617 public void onComplete() {
618 final OthersResource others = getResult();
619 MultipleGetCommand<OtherUserResource> gogo = new MultipleGetCommand<OtherUserResource>(OtherUserResource.class,
620 others.getOthers().toArray(new String[] {}), null) {
623 public void onComplete() {
624 List<OtherUserResource> res = getResult();
625 updateRowCount(res.size(), true);
626 List<RestResource> r = new ArrayList<RestResource>();
632 public void onError(Throwable t) {
633 GWT.log("Error fetching Others Root folder", t);
634 GSS.get().displayError("Unable to fetch Others Root folder");
638 public void onError(String p, Throwable throwable) {
639 GWT.log("Path:"+p, throwable);
642 DeferredCommand.addCommand(gogo);
646 public void onError(Throwable t) {
647 GWT.log("Error fetching Others Root folder", t);
648 GSS.get().displayError("Unable to fetch Others Root folder");
651 DeferredCommand.addCommand(go);
658 * Retrieve the rootNodes.
660 * @return the rootNodes
662 public ListDataProvider<RestResource> getRootNodes() {
668 * Retrieve the mymap.
672 public Map<String, MyFolderDataProvider> getMymap() {
678 * Retrieve the sharedmap.
680 * @return the sharedmap
682 public Map<String, MyFolderDataProvider> getSharedmap() {
688 * Retrieve the othersmap.
690 * @return the othersmap
692 public Map<String, MyFolderDataProvider> getOthersmap() {