Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Riena » How to get a lazy loading tree in Riena?
How to get a lazy loading tree in Riena? [message #726763] Mon, 19 September 2011 13:17 Go to next message
Tihomir Todorov is currently offline Tihomir TodorovFriend
Messages: 6
Registered: September 2011
Junior Member
Hey,

i try to create a lazy loading tree.
So that, wenn i click on a plus symbol of the node with children,
the node should be expanded and during this the children of the node should be created.
Something like lazy loading in SWT.

For this purpose, i use the method called expandedChanged(ISubModuleNode source) of the class SubModuleNodeListener.

The source code shows below, on how i do it this.

The result is fine!
The Problem ist, that i get everytime the Exception "org.eclipse.swt.SWTException: Widget is disposed",
wenn i click on the plus symbol.

I think must not be so. Wenn i use activated(...) instead of expandedChanged(...) all work fine.

So the questions are:

How can i get lasy loiding tree in Riena?
Is my way wrong or right? Wenn i do something wrong, what is this and on how it should be?
Does has the method "expandedChanged(ISubModuleNode source)" a bug?


// ------------------
// Source code:
//-------------------
MyApp extends SWTApplication {

  // ...

  @Override
  protected IApplicationNode createModel() {
    IApplicationNode appNode = super.createModel();

    createDummyTree(appNode);

    return appNode;
  }

  // ------------------------------------------------------------------- Start -
//@formatter:off
  /**
   * root
   *   |-node_1
   *       |-node_11
   *       |-node_12
   *           |-node_121
   *           |-node_122
   *       |-node_13
   *   |-node_2
   * 
   * @param module a {@link IModuleNode}
   */
  private void createDummyTree(IApplicationNode appNode) {

    ISubApplicationNode subApp = new SubApplicationNode(new NavigationNodeId("id_subapp_1"), "SubApp_1");
    WorkareaManager.getInstance().registerDefinition(subApp, "1.perspective", false);
    appNode.addChild(subApp);

    IModuleGroupNode moduleGroup = new ModuleGroupNode(new NavigationNodeId("id_subapp_1_modulegroup"));
    subApp.addChild(moduleGroup);

    IModuleNode module = new ModuleNode(new NavigationNodeId("id_module_1"), "Module_1");
    module.setClosable(false);
    moduleGroup.addChild(module);

    StammTreeNode2 root = createStammTreeNode2(Integer.valueOf(0), "root", null, null, null, null);

    StammTreeNode2 node_1 = createStammTreeNode2(Integer.valueOf(1), "node_1", null, null, Long.valueOf(7000058), null);
    StammTreeNode2 node_2 = createStammTreeNode2(Integer.valueOf(2), "node_2", null, null, null, null);
    root.addChild(node_1); root.addChild(node_2);

    StammTreeNode2 node_11 = createStammTreeNode2(Integer.valueOf(11), "node_11", null, null, null, null);
    StammTreeNode2 node_12 = createStammTreeNode2(Integer.valueOf(12), "node_12", null, null, null, null);
    StammTreeNode2 node_13 = createStammTreeNode2(Integer.valueOf(13), "node_13", null, null, null, null);
    node_1.addChild(node_11); node_1.addChild(node_12); node_1.addChild(node_13);

    StammTreeNode2 node_121 = createStammTreeNode2(Integer.valueOf(121), "node_121", null, null, null, null);
    StammTreeNode2 node_122 = createStammTreeNode2(Integer.valueOf(122), "node_122", null, null, null, null);
    node_12.addChild(node_121); node_12.addChild(node_122);
    
 
    for (StammTreeNode2 treeNode : root.getChildren()) {
      ISubModuleNode newSubModule = new SubModuleNode(new NavigationNodeId(String.valueOf(treeNode.getId())), treeNode.getLabel());
      WorkareaManager.getInstance().registerDefinition(newSubModule, GenericWorkframeSubModuleController.class, GenericWorkframeSubModuleView.ID);
      module.addChild(newSubModule);

      // Attach the treeNode to the newSubModule so it can be accessed when the subModule is expanded.
      newSubModule.setContext("StammTreeNode", treeNode);

      // Add a dummy sub-module to the sub-module that has children to make it expandable.
      if (treeNode.getChildren().size() != 0) {
        newSubModule.addChild(new SubModuleNode());
      }

      newSubModule.addListener(new ExpandedListener());
    }
  }
//@formatter:on

  private StammTreeNode2 createStammTreeNode2(Integer id, String label, String tooltip, Integer parentId, Long classId, Integer sorter) {
    StammTreeNode2 node = new StammTreeNode2();

    node.setId(id);
    node.setLabel(label);
    node.setTooltip(tooltip);
    node.setParentId(parentId);
    node.setClassId(classId);
    node.setSorter(sorter);

    return node;
  }

  private class StammTreeNode2 extends StammTreeNode {

    private List<StammTreeNode2> children;

    public StammTreeNode2() {
      children = new ArrayList<StammTreeNode2>();
    }

    public List<StammTreeNode2> getChildren() {
      return children;
    }

    public void addChild(StammTreeNode2 node) {
      children.add(node);
    }

  }
  
  private class ExpandedListener extends SubModuleNodeListener {
    
    @Override
    public void expandedChanged(ISubModuleNode source) {

      if (source.isExpanded()) {
        System.out.println("expanded");
        try {
          // Iterate over the node's children.
          for (ISubModuleNode node : source.getChildren()) {
            // The sub-module already has a data object attached to it.
            // This is only the case when the sub-module has previously been expanded.
            if (node.getContext("StammTreeNode") != null) {
              return;
            }

            // The item is a dummy item. Remove it.
            // source.removeChild(node);
            node.dispose();
          }

        } catch (ConcurrentModificationException e) {
          // e.printStackTrace();
        }

        List<StammTreeNode2> treeNodes = ((StammTreeNode2) source.getContext("StammTreeNode")).getChildren();

        if (treeNodes.size() == 0) {
          return;
        }
        
          for (StammTreeNode2 treeNode : treeNodes) {

            ISubModuleNode newSubModule = new SubModuleNode(new NavigationNodeId(String.valueOf(treeNode.getId())), treeNode.getLabel());
            WorkareaManager.getInstance().registerDefinition(newSubModule, GenericWorkframeSubModuleController.class, GenericWorkframeSubModuleView.ID);
            source.addChild(newSubModule);

            // Attach the treeNode to the newSubModule so it can be accessed when the subModule is expanded.
            newSubModule.setContext("StammTreeNode", treeNode);
         
            // Add a dummy sub-module to the sub-module that has children to make it expandable.
            if (treeNode.getChildren().size() != 0) {
              newSubModule.addChild(new SubModuleNode());
            }


            newSubModule.addListener(this);
          }
      } else { // end isExpanded()
        System.out.println("collapsed");
      }
    }
  }

  // --------------------------------------------------------------------- End -



// ------------------
// Exception:
//-------------------
org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:4282)
at org.eclipse.swt.SWT.error(SWT.java:4197)
at org.eclipse.swt.SWT.error(SWT.java:4168)
at org.eclipse.swt.widgets.Widget.error(Widget.java:468)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:340)
at org.eclipse.swt.widgets.TreeItem.getItems(TreeItem.java:785)
at org.eclipse.jface.viewers.TreeViewer.getChildren(TreeViewer.java:168)
at org.eclipse.jface.viewers.AbstractTreeViewer.createChildren(AbstractTreeViewer.java:774)
at org.eclipse.jface.viewers.TreeViewer.createChildren(TreeViewer.java:644)
at org.eclipse.jface.viewers.AbstractTreeViewer.createChildren(AbstractTreeViewer.java:753)
at org.eclipse.jface.viewers.AbstractTreeViewer.handleTreeExpand(AbstractTreeViewer.java:1485)
at org.eclipse.jface.viewers.TreeViewer.handleTreeExpand(TreeViewer.java:952)
at org.eclipse.riena.internal.ui.ridgets.swt.TreeRidget$SharedControlTreeViewer.handleTreeExpand(TreeRidget.java:940)
at org.eclipse.jface.viewers.AbstractTreeViewer$4.treeExpanded(AbstractTreeViewer.java:1496)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:132)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1062)
at org.eclipse.swt.widgets.Tree.wmNotifyChild(Tree.java:7538)
at org.eclipse.swt.widgets.Control.wmNotify(Control.java:5534)
at org.eclipse.swt.widgets.Composite.wmNotify(Composite.java:1896)
at org.eclipse.swt.widgets.Control.WM_NOTIFY(Control.java:5086)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4584)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
at org.eclipse.swt.internal.win32.OS.CallWindowProcW(Native Method)
at org.eclipse.swt.internal.win32.OS.CallWindowProc(OS.java:2424)
at org.eclipse.swt.widgets.Tree.callWindowProc(Tree.java:1533)
at org.eclipse.swt.widgets.Tree.WM_LBUTTONDOWN(Tree.java:6411)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4564)
at org.eclipse.swt.widgets.Tree.windowProc(Tree.java:5937)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4985)
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2530)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3752)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2696)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2660)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.riena.navigation.ui.swt.application.SwtApplication.createView(SwtApplication.java:72)
at org.eclipse.riena.navigation.ui.application.AbstractApplication.start(AbstractApplication.java:79)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
Re: How to get a lazy loading tree in Riena? [message #726809 is a reply to message #726763] Mon, 19 September 2011 15:41 Go to previous messageGo to next message
Thorsten Schenkel is currently offline Thorsten SchenkelFriend
Messages: 15
Registered: July 2009
Junior Member
I can reproduce your problem. (With a simpler example)
I copied some parts of your code. At first a ConcurrentModificationException was fired in the method expandedChanged of the class ExpandedListener. I avoid this problem with a break statement after "node.dispose()".
After that "fix" I still get the "Widget is disposed"-Exception. But I don't find a quick solution. Please open a Riena bug for this problem.
Re: How to get a lazy loading tree in Riena? [message #727035 is a reply to message #726763] Tue, 20 September 2011 09:08 Go to previous message
Tihomir Todorov is currently offline Tihomir TodorovFriend
Messages: 6
Registered: September 2011
Junior Member
Hallo Thorsten,

thanks for your quick reply.
About the break statement, i know this Smile. But i think, it is not the right solution, just a momentan workaround Wink.
After the call "node.disposed();" or "source.removeChild(node);", Riena uses intern a object called java.util.LinkedList!
The problem appears because of "LinkedList"!

We remove a node (obj. of LinkkedList) in the for loop. So we change the size of "LinkedList".
But a LinkedList thinks, that it has a old size. And the class LinkedList does not care what would happen,
when we create one such case.

Riena needs may be a better algorithm about this, what would happen after the call "node.disposed();".

So i am trying to find a workaround now about "Widget is disposed".
I tryed also with try...catch but i can't catch the Exception. Have you an idea? How?

From the stack trace i can see, that Riena use intern a JFace TreeViewer.
Is it possible to get this object or a ITreeRidget of the navigation model?
Something like this:
(new SubModuleNode()).getNavigationNodeController().getTypecastedAdapter(TreeViewer.class);
or something else?

I open today a Riena bug too under the number: Bug 358193 (bugs.eclipse.org/bugs/show_bug.cgi?id=358193)
There i reproduced the problem with a simpler example.

Greeting,
Tihomir
Previous Topic:How to do a multifield validiation in Riena
Next Topic:Riena-App requires more than 3 minutes, if it's closed.
Goto Forum:
  


Current Time: Fri Dec 19 13:00:51 GMT 2014

Powered by FUDForum. Page generated in 0.01833 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software