2013-02-18 9 views
6

Ich habe eine GWT Cell Tree, die ich verwenden, um eine Dateistruktur von einem CMS anzuzeigen. Ich verwende eine , die Daten aus einer benutzerdefinierten RPC-Klasse, die ich erstellt habe, lädt. Ich habe auch ein Web Socket-System, das Ereignisse (Datei erstellen, umbenennen, verschieben, löschen usw.) von anderen Clients, die ebenfalls im System arbeiten, überträgt.Wie kann ich einem GWT-Zellen-Widget mitteilen, dass sich Daten über den Event-Bus geändert haben?

Was ich versuche, meinen Kopf zu wickeln ist, wenn ich eines dieser Ereignisse erhalte, wie ich meinen Zellenbaum richtig aktualisiere?

Ich nehme an, dieses Problem wäre analog zu zwei Instanzen meiner Cell Tree auf der Seite, die die gleichen serverseitigen Daten präsentieren und sicherstellen möchten, dass, wenn der Benutzer aktualisiert, dass der andere auch aktualisiert wird, über die EventBus.

Ich denke, das sollte ziemlich einfach sein, aber ich habe jetzt etwa 6 Stunden darauf ohne Fortschritt verbracht. Mein Code ist unten enthalten:

HINWEIS: Ich verwende keine RequestFactory, obwohl es aussehen mag, als ob ich es ist mein eigenes RPC-Framework. Außerdem ist FileEntity nur eine einfache Darstellung einer Datei mit einem Namen, auf den durch getName() zugegriffen werden kann.

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()); 
      } 
     } 
    } 

Antwort

2

Derzeit gibt es keine direkte Unterstützung für die Aktualisierung einzelner Baumelemente, auch nicht in der neuesten gwt-Version.

Aber es gibt einen Workaround dafür. Jedes Baumelement ist mit einem Wert verknüpft. Mit diesem Wert erhalten Sie den entsprechenden Baumeintrag.

In Ihrem Fall nehme ich an, Sie wissen, welches Element zu aktualisieren/aktualisieren, dh Sie wissen, welche Datei Entität geändert hat. Verwenden Sie diese Dateientität, um nach dem entsprechenden Baumelement zu suchen. Sobald Sie das Baumelement erhalten haben, müssen Sie nur das übergeordnete Element erweitern und reduzieren oder reduzieren und erweitern. Dadurch werden die untergeordneten Elemente erneut gerendert. Ihre geänderte Dateieinheit gehört zu den Kindern. So wird es erfrischt.

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); 
     } 
} 
+0

Nicht genau das, was ich gesucht habe, aber das funktioniert. Was halten Sie davon, einen Index FileEntity-> TreeNode zu pflegen, um die Suchzeiten zu verbessern? Vielen Dank! –

+0

Ja ist es immer eine bessere Indizierung zu verwenden ... – Adarsha

0

Sie können den Datenprovider verwenden, um den Zellbaum zu aktualisieren. Sie können die komplette Zelle Baum aktualisieren mit:

provider.setList(pList); 
provider.refresh(); 

Wenn Sie nur eine spezielle Zelle aktualisieren möchten Sie die listwrapper vom Dataprovider erhalten und setzen nur ein Element.

provider.getList().set(12, element); 
+0

Dies muss mit einem AsyncDataProvider arbeiten, wo neue Daten vom Server kommen. Ich denke nicht, dass dieser Ansatz funktioniert ... –