Programmatically refresh a Gwt CellTree

Fabio B. picture Fabio B. · Aug 30, 2011 · Viewed 7.6k times · Source

I want to fire the "open root node" event on my current working CellTree, which now has the following behaviour:

@Override
    public <T> NodeInfo<?> getNodeInfo(final T value) {
        return new DefaultNodeInfo<Categoria>(
                (value instanceof Categoria) ? 
                        createBranchDataProvider((Categoria)value) :
                        rootDataProvider, 
                new CategoriaCell()
        );
    }

private AsyncDataProvider<Categoria> createRootDataProvider() {
        AsyncDataProvider<Categoria> dataProvider = new AsyncDataProvider<Categoria>() {
            @Override
            protected void onRangeChanged(HasData<Categoria> display) {
                AsyncCallback<Categoria[]> cb = new AsyncCallback<Categoria[]>() {
                    @Override
                    public void onSuccess(Categoria[] result) {
                        updateRowCount(result.length, true);
                        updateRowData(0, Arrays.asList(result));
                    }
                    @Override
                    public void onFailure(Throwable caught) {
                        Window.alert(caught.toString());
                    }
                };  
                rpcService.getCategorie(cb);
            }
        };
        return dataProvider;
    }

How can I fire that "onRangeChanged" event, to refresh my level-1 nodes?

What is my convenience method missing?

private void updateTree() {     
        TreeNode rootTreeNode = cellTree.getRootTreeNode();
        for (int i = 0; i < rootTreeNode.getChildCount(); i++) {
            rootTreeNode.setChildOpen(i, false);
        }
        // HOW TO REFRESH LEVEL-1 NODES?
    }

Answer

MatejC picture MatejC · Nov 11, 2011

Working example. Add reference to DataProvider (and parent Node) (MyMenuItem and MyCell with DataProvider in my code). After adding element refresh parent.

public class MyMenuItem {
    private String name;
    private String action; //some data
    private int level; //if needed
    private ArrayList<MyMenuItem> list; //nodes childrens
    private MyMenuItem parent; //track internal parent
    private MyCell cell; //for refresh - reference to visual component

    public void setCell(MyCell cell) {
        this.cell = cell;
    }
    public void refresh() {
      if(parent!=null) {
          parent.refresh();
      }
      if (cell!=null) {
          cell.refresh(); //refresh tree
      }
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAction() {
        return action;
    }
    public void setAction(String action) {
        this.action = action;
    }
    public MyMenuItem(String name, String action) {
        super();
        parent = null;
        level = 0;
        this.name = name;
        this.action = action;
        list = new ArrayList<MyMenuItem>();
    }
    public MyMenuItem(String name) {
        this(name, "");
    }
    public void addSubMenu(MyMenuItem m) {
        m.level = this.level+1;
        m.parent = this;
        list.add(m);
    }

    public boolean hasChildrens() {
        return list.size()>0;
    }
    public int getLevel() {
        return level;
    }
    public void setLevel(int level) {
        this.level = level;
    }
    public ArrayList<MyMenuItem> getList() {
        return list;
    }
    public MyMenuItem getParent() {
        return parent;
    }
}

public class MyTreeModel implements TreeViewModel {
    private MyMenuItem officialRoot; //default not dynamic
    private MyMenuItem studentRoot; //default not dynamic
    private MyMenuItem testRoot; //default not dynamic
    private MyMenuItem root;

    public MyMenuItem getRoot() { // to set CellTree root
        return root;
    }

    public MyTreeModel() {
        root = new MyMenuItem("root");
        // Default items
        officialRoot = new MyMenuItem("Official"); //some basic static data
        studentRoot = new MyMenuItem("Student");
        testRoot = new MyMenuItem("Test");
        root.addSubMenu(officialRoot);
        root.addSubMenu(studentRoot);
        root.addSubMenu(testRoot);
    }

    //example of add add logic
    private void addNew(MyMenuItem myparent, String name, String uid) {
        myparent.addSubMenu(new MyMenuItem(name, uid)); 
        myparent.refresh(); //HERE refresh tree
    }   

    @Override
    public <T> NodeInfo<?> getNodeInfo(T value) {
        ListDataProvider<MyMenuItem> dataProvider;
        MyMenuItem myValue = null;
        if (value == null) { // root is not set
            dataProvider = new ListDataProvider<MyMenuItem>(root.getList());
        } else {
            myValue = (MyMenuItem) value;
            dataProvider = new ListDataProvider<MyMenuItem>(myValue.getList());
        }
        MyCell cell = new MyCell(dataProvider); //HERE Add reference
        if (myValue != null)
            myValue.setCell(cell);
        return new DefaultNodeInfo<MyMenuItem>(dataProvider, cell);
    }

    @Override
    public boolean isLeaf(Object value) {
        if (value instanceof MyMenuItem) {
            MyMenuItem t = (MyMenuItem) value;
            if (!t.hasChildrens())
                return true;
            return false;
        }
        return false; 
    }

}

public class MyCell extends AbstractCell<MyMenuItem> {
        ListDataProvider<MyMenuItem> dataProvider; //for refresh
        public MyCell(ListDataProvider<MyMenuItem> dataProvider) {
          super("keydown","dblclick");
          this.dataProvider = dataProvider;
        }
        public void refresh() {
            dataProvider.refresh(); 
        }
        @Override
        public void onBrowserEvent(Context context, Element parent, MyMenuItem value,
            NativeEvent event, ValueUpdater<MyMenuItem> valueUpdater) {
          if (value == null) {
            return;
          }
          super.onBrowserEvent(context, parent, value, event, valueUpdater);
          if ("click".equals(event.getType())) {
            this.onEnterKeyDown(context, parent, value, event, valueUpdater);
          }
          if ("dblclick".equals(event.getType())) {
              this.onEnterKeyDown(context, parent, value, event, valueUpdater);
            }
        }

        @Override
        public void render(Context context, MyMenuItem value, SafeHtmlBuilder sb) {
          if (value == null) {
            return;
          }
          sb.appendEscaped(value.getName());
          //add HERE for better formating
        }


        @Override
        protected void onEnterKeyDown(Context context, Element parent,
                MyMenuItem value, NativeEvent event, ValueUpdater<MyMenuItem> valueUpdater) {
          Window.alert("You clicked "+event.getType()+" " + value.getName());
        }


}

in module add

 treeModel = new MyTreeModel();
 tree = new CellTree(treeModel,treeModel.getRoot());