Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I tell a GWT cell widget data has changed via the Event Bus?

Tags:

gwt

event-bus

I have a GWT Cell Tree that I use to display a file structure from a CMS. I am using a AsyncDataProvider that loads data from a custom RPC class I created. I also have a Web Socket system that will broadcast events (File create, renamed, moved, deleted etc) from other clients also working in the system.

What I am trying to wrap my head around is when I recieve one of these events, how I correctly update my Cell Tree?

I suppose this problem would be analogus to having two instances of my Cell Tree on the page, which are presenting the same server-side data and wanting to ensure that when the user updated one, that the other updated as well, via using the EventBus.

I feel this should be pretty simple but I have spent about 6 hours on it now with no headway. My code is included below:

NOTE: I am not using RequestFactory even though it may look like I am it is my custom RPC framework. Also, FileEntity is just a simple representation of a file which has a name accessible by getName().

private void drawTree() {

        // fileService is injected earlier on and is my own custom rpc service
        TreeViewModel model = new CustomTreeModel(new FileDataProvider(fileService));
        CellTree tree = new CellTree(model, "Root");

        tree.setAnimationEnabled(true);

        getView().getWorkspace().add(tree);

    }

    private static class CustomTreeModel implements TreeViewModel {

        // I am trying to use a single AsyncDataProvider so I have a single point of loading data which I can manipulate (Not sure if this is the correct way to go)
        public CustomTreeModel(FileDataProvider dataProvider) {
            this.provider = provider;
        }


        public <T> NodeInfo<?> getNodeInfo(final T value) {

            if (!(value instanceof FileEntity)) {

                                // I already have the root File loaded in my presenter, if we are at the root of the tree, I just add it via a list here
                ListDataProvider<FileEntity> dataProvider = new ListDataProvider<FileEntity>();

                dataProvider.getList().add(TreeWorkspacePresenter.rootFolder);

                return new DefaultNodeInfo<FileEntity>(dataProvider,
                        new FileCell());
            } else {

                                // Otherwise I know that we are loading some tree child data, and I invoke the AsyncProvider to load it from the server
                provider.setFocusFile(value);

                return new DefaultNodeInfo<FileEntity>(provider,
                        new FileCell());
            }
        }

        public boolean isLeaf(Object value) {

            if(value == null || value instanceof Folder)
                return false;
            return true;
        }

    }

    public class FileDataProvider extends AsyncDataProvider<FileEntity> {

        private FileEntity focusFile;
        private FileService service; 

        @Inject
        public FileDataProvider(FileService service){
            this.service = service;
        }

        public void setFocusFile(FileEntity focusFile){
            this.focusFile = focusFile;
        }

        @Override
        protected void onRangeChanged(HasData<FileEntity> display) {


                service.getChildren(((Folder) focusFile),
                        new Reciever<List<FileEntity>>() {

                            @Override
                            public void onSuccess(List<FileEntity> files) {

                                updateRowData(0, files);

                            }

                            @Override
                            public void onFailure(Throwable error) {

                                Window.alert(error.toString());
                            }

                        });

            }
        }



    /**
     * The cell used to render Files.
     */
    public static class FileCell extends AbstractCell<FileEntity> {

        private FileEntity file;

        public FileEntity getFile() {
            return file;

        }

        @Override
        public void render(Context context, FileEntity file, SafeHtmlBuilder sb) {
            if (file != null) {
                this.file = file;
                sb.appendEscaped(file.getName());
            }
        }
    }
like image 962
Casey Jordan Avatar asked Feb 18 '13 03:02

Casey Jordan


1 Answers

Currently there is no direct support for individual tree item refresh even in the latest gwt version.

But there is a workaround for this. Each tree item is associated with an value. Using this value you can get the corresponding tree item.

In your case, i assume, you know which item to update/refresh ie you know which File Entity has changed. Use this file entity to search for the corresponding tree item. Once you get the tree item you just need to expand and collapse or collapse and expand its parent item. This makes parent item to re-render its children. Your changed file entity is one among the children. So it get refreshed.

public void refreshFileEntity(FileEntity fileEntity)
{
       TreeNode fileEntityNode = getFileEntityNode(fileEntity, cellTree.getRootTreeNode() 

       // For expnad and collapse run this for loop

       for ( int i = 0; i < fileEntityNode.getParent().getChildCount(); i++ )
    {
        if ( !fileEntityNode.getParent().isChildLeaf( i ) )
        {
            fileEntityNode.getParent().setChildOpen( i, true );
        }
    }

}

public TreeNode getFileEntityNode(FileEntity fileEntity, TreeNode treeNode)
{
       if(treeNode.getChildren == null)
       {
           return null;
       }
       for(TreeNode node : treeNode.getChildren())
       {
            if(fileEntity.getId().equals( node.getValue.getId() ))
            {
                 return node;
            }
            getEntityNode(fileEntity, node); 
       }
}
like image 50
Adarsha Avatar answered Nov 15 '22 12:11

Adarsha