2011-08-30 10 views
6

Quiero desencadenar el evento "nodo raíz abierta" en mi CellTree de trabajo actual, que ahora tiene el siguiente comportamiento:Programatically actualizar una Gwt CellTree

@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; 
    } 

¿Cómo puedo disparar que "onRangeChanged" evento, a actualizar mis nodos de nivel 1?

¿Cuál es mi método de conveniencia que falta?

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? 
    } 

Respuesta

2

Los nodos de nivel 1 (supongo que la media por debajo del nodo raíz) no puede ser refrescado la forma en que lo está haciendo.

Debe almacenar la instancia de su dataProvider para los nodos de nivel 1 en algún lugar. Más tarde, cuando actualiza su lista, debe actualizar su dataProvider almacenado para sus nodos de nivel 1.
Los nodos por debajo del nivel 1 se pueden actualizar de la manera en que lo hace. Porque tan pronto como cierre los nodos de nivel 1 (eso es lo que está haciendo en el método updateTree) y la próxima vez que lo abra se llamará getNodeInfo y las subcategorías actualizadas se recuperarán y se mostrarán en el CellTree.

ACTUALIZACIÓN

para actualizar la CellWidgets que se adjunta a AsyncDataProvider que probablemente tendrá que extender el AsyncDataProvider y, o bien extraer la llamada RPC a un método getData() que se llama en el onRangeChanged() método o crear una interface with a refresh method e implementarlo en su AsyncDataProvider personalizado que llama al método protegido onRangeChanged().

+0

<< Más tarde, al actualizar su lista tiene que actualizar su almacenado dataProvider para sus nodos de nivel-1. >> Bueno!^___^pero ... ¿CÓMO?!? -.- 'Quiero decir, el único método disponible en el proveedor es updateRowData(), ¿tengo que duplicar el código rpc presente en onRangeChanged(), o simplemente puedo activar el evento "range changed" de alguna manera? gracias –

+0

ver mi respuesta actualizada –

4

Ejemplo de trabajo. Agregue referencia a DataProvider (y nodo principal) (MyMenuItem y MyCell con DataProvider en mi código). Después de agregar el elemento 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()); 
     } 


} 

en el módulo añadir

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