Hi Janak Sorry that I was not clear enough! I will try again ;)
I have a panel with an ULCTableTree inside. The number of nodes shown by the tree might be quite big. It is absolute ok that ULC does a lazy loading and also the big tree is shown fast enough! To open the nodes of the tree we have added KeyStrokes such as '*', '-' and '+'. With '*' the tree should open all ist nodes. And that takes very very long. The problem is not that it takes very long, but that the user does not get any feedback. In fact it seams to go very long because we first did not realise that ULC is loading data... I'm sure that it is ok for our users to see the data is loading as it is done in Eclipse when you open a large tree with '*'. And anybody can understand that it takes some time to open a large tree. My problem is now that the tree is opened on the server side in 100ms and then I see nothing... I would like to open node by node and then force the loading of every node. This may as well block any user operation. Another way would be to load all nodes in a background operation as in the eager loading example. In both situations once the operation is startet the loading of the nodes should load all nodes, because the user should not be bothered a second time with the loading problem. Did I destroy any clearness now? Hope not :) Thanks for any tips! Regards Alex -----Ursprüngliche Nachricht----- Von: Janak Mulani [mailto:[EMAIL PROTECTED] Gesendet: Montag, 2. Oktober 2006 18:08 An: Stucki Alexander, Bedag Cc: [email protected] Betreff: RE: [ULC-developer] Full expand a large tree -> EagerLoading for TableTree? Hi Alex, >I try to open a large TableTree (Root with 100 nodes and every node has >6 levels of subnodes) and this takes very very long! ULCTableTree will upload only those nodes that are visible. Moreover it will not upload child nodes unless they become visible when their parent node is expanded. Therefore not all 100 nodes will be uploaded (unless ofcourse they are all visible). So your initial data loading should be fast. >The problem is that the ULC must load all data at once and this takes >very long even when the nodes hold only Strings. As I said ULC loads data in a lazy manner and does not load all the data. Or is it that you want to force loading of all data? If that is the case then you can use: tableTree.putClientProperty("disableLazyLoading", Boolean.TRUE); I am sorry that I do not understand your problem. You are saying that ULC is loading all the data which is taking a long time and that you tried to find a solution to this problem. However, as I have described above ULC loads data in a lazy manner and therefore it should not take long. Could you please answer the following: 1. please explain your problem again? 2. Do you in fact want to upload all the data? 3. How have you deployed your application on the client? 4. Is the application slow while loading the data only or for all user interaction in general. 5. What happens if you reduce the number of nodes? Do they load faster? Thanks and regards, Janak -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Behalf Of Stucki Alexander, Bedag Sent: Friday, September 29, 2006 2:54 PM To: [EMAIL PROTECTED] Subject: [ULC-developer] Full expand a large tree -> EagerLoading for TableTree? Hi All, I try to open a large TableTree (Root with 100 nodes and every node has 6 levels of subnodes) and this takes very very long! The problem is that the ULC must load all data at once and this takes very long even when the nodes hold only Strings. I tried loading the data in several ways A) expand the nodes at client side B) add a RoundTripListener and open the nodes one by one C) adapt the EagerLoadingSample of ULCTable. The problems... A) here I could not load the data from UI side. Only the first subnodes are shown. B) This works so far but the roundtrip ends befor all nodes are loaded. If you scroll the scrollbar, suddenly the nodes are loading again, what is a strange behaviour for the user. C) As in A) I do not know how to get the data uploaded. The old way with handleRequest() is deprecated and I could even not adapt it for the TabelTree because the descriptions seam to be wrong which I deliver to the request. It would be nice to open the nodes on the UI side so the user gets a feedback that the tree is opening. On the other hand it would be nice to load the nodes in the background. In both ways I must force to upload a node. How can I do this? Thanks a lot!! Regards Alex Below my experiments ;) import java.util.ArrayList; import java.util.List; import com.ulcjava.base.application.AbstractAction; import com.ulcjava.base.application.AbstractApplication; import com.ulcjava.base.application.ApplicationContext; import com.ulcjava.base.application.ULCBorderLayoutPane; import com.ulcjava.base.application.ULCBoxLayoutPane; import com.ulcjava.base.application.ULCButton; import com.ulcjava.base.application.ULCComponent; import com.ulcjava.base.application.ULCFrame; import com.ulcjava.base.application.ULCScrollPane; import com.ulcjava.base.application.ULCTableTree; import com.ulcjava.base.application.event.ActionEvent; import com.ulcjava.base.application.event.IRoundTripListener; import com.ulcjava.base.application.event.RoundTripEvent; import com.ulcjava.base.application.tabletree.AbstractTableTreeModel; import com.ulcjava.base.application.tabletree.DefaultTableTreeModel; import com.ulcjava.base.application.tabletree.IMutableTableTreeNode; import com.ulcjava.base.application.tabletree.ITableTreeNode; import com.ulcjava.base.application.tree.TreePath; import com.ulcjava.base.application.util.BorderedComponentUtilities; import com.ulcjava.base.application.util.Dimension; import com.ulcjava.base.client.UITableTree; import com.ulcjava.base.development.DevelopmentRunner; public class MyExpandNodeTableTree extends AbstractApplication { private static final int NUM_OF_SUBCHILDS = 30;//100; private static final int NUM_OF_SUBSUB_LEVELS = 6; public static void main(String args[]) { DevelopmentRunner.setApplicationClass(MyExpandNodeTableTree.class); DevelopmentRunner.run(); } public void start() { ApplicationContext.addRoundTripListener(new EagerLoadingTableTreeHandler()); //MyTable //add 100 childs to root MyTableTreeNode root = new MyTableTreeNode("ROOT", null); for(int i = 0; i< NUM_OF_SUBCHILDS; i++){ MyTableTreeNode subchild = new MyTableTreeNode("subChild_"+i, ""+i); root.insert(subchild, i); } //add subchilds 6 level deep for(int j = 0; j < root.getChildCount(); j++){ addNewChild((IMutableTableTreeNode)root.getChildAt(j),0); } DefaultTableTreeModel tableTreeModel = new DefaultTableTreeModel(root, new String[]{"name", "date"}); MyULCTableTree tableTree = new MyULCTableTree(tableTreeModel); ULCScrollPane tableTreePane = new ULCScrollPane(tableTree); ULCComponent borderedTableTree = BorderedComponentUtilities.createBorderedComponent(tableTreePane, "tableTree"); ULCBoxLayoutPane buttonPane = ULCBoxLayoutPane.createVerticalBox(); buttonPane.add(new ULCButton(tableTree.getExpandOnServerAction()), -1, ULCBoxLayoutPane.CENTER_ALIGNMENT); buttonPane.add(new ULCButton(tableTree.getExpandOnClientAction()), -1, ULCBoxLayoutPane.CENTER_ALIGNMENT); buttonPane.add(new ULCButton(tableTree.getExpandInMultipleRoundTripsAction()), -1, ULCBoxLayoutPane.CENTER_ALIGNMENT); buttonPane.add(new ULCButton(tableTree.getCollapseAllAction()), -1, ULCBoxLayoutPane.CENTER_ALIGNMENT); ULCComponent borderedButtonPane = BorderedComponentUtilities.createBorderedComponent(buttonPane, "buttonPane"); //add all to the root pane ULCBorderLayoutPane rootBox = new ULCBorderLayoutPane(); rootBox.setPreferredSize(new Dimension(500,900)); rootBox.add(borderedTableTree, ULCBorderLayoutPane.CENTER); rootBox.add(borderedButtonPane, ULCBorderLayoutPane.SOUTH); ULCFrame frame = new ULCFrame("My ExpandTreeNode Sample"); frame.setDefaultCloseOperation(ULCFrame.TERMINATE_ON_CLOSE); frame.add(rootBox); frame.setVisible(true); } private void addNewChild(IMutableTableTreeNode node, int level){ if(level > NUM_OF_SUBSUB_LEVELS){ return; } int newLevel = level+1; IMutableTableTreeNode child = new MyTableTreeNode("subSubChild_"+newLevel, ""+newLevel); addNewChild(child,newLevel); node.insert(child,0); } public static class MyULCTableTree extends ULCTableTree { //first version private AbstractAction expandOnServerAction = new AbstractAction("expandOnServerAction") { public void actionPerformed(ActionEvent arg0) { fullExpandSelectedObject(); } }; //second version private AbstractAction expandOnClientAction = new AbstractAction("expandOnClientAction") { public void actionPerformed(ActionEvent arg0) { MyULCTableTree.this.callFullExpandMethodOnClient(); } }; //third version private AbstractAction expandInMultipleRoundTripsAction = new AbstractAction("expandInMultipleRoundTripsAction") { public void actionPerformed(ActionEvent arg0) { fullExpandInMultipleServerRoundTrips(); } }; //collapseAll private AbstractAction collapseAllAction = new AbstractAction("collapseAllAction") { public void actionPerformed(ActionEvent arg0) { collapseAll(); } }; public MyULCTableTree(AbstractTableTreeModel model) { super(model); } public void fullExpandInMultipleServerRoundTrips(){ ApplicationContext.addRoundTripListener(new MyTableTreeNodeOpener()); } private class MyTableTreeNodeOpener implements IRoundTripListener { private int row = 0; private static final int NUM_OF_ROWS_TO_OPEN = 10; public void roundTripDidStart(RoundTripEvent event) { /* noop */ } public void roundTripWillEnd(RoundTripEvent event) { if(null == MyULCTableTree.this.getSelectedPath()){ System.out.println("Please select a node!!!"); return; } Object node = MyULCTableTree.this.getSelectedPath().getLastPathComponent(); int rowCounter = 0; while (row < MyULCTableTree.this.getRowCount() && rowCounter < NUM_OF_ROWS_TO_OPEN) { // System.out.println("MyULCTableTree.this.getRowCount() = '"+ MyULCTableTree.this.getRowCount() + "'"); // System.out.println("rowCounter = '"+ rowCounter + "'"); // System.out.println("row = '"+ row + "'"); // System.out.println("MyULCTableTree.this.isExpanded("+row+") = '"+ MyULCTableTree.this.isExpanded(row) + "'"); System.out.println("expanding row = '"+ row + "'"); if(!MyULCTableTree.this.isExpanded(row)){ MyULCTableTree.this.expandRow(row); rowCounter++; } else { //go on } row++; } if(0 == rowCounter){ System.out.println("rowCounter is zero -> removing RoundTripLilstener"); ApplicationContext.removeRoundTripListener(this); } } } public void callFullExpandMethodOnClient(){ invokeUI("fullExpandSelectedObject"); } /** * Der selektierte Node und alle seine Kinder werden geöffnet. */ public void fullExpandSelectedObject() { if(null == getSelectedPath()){ System.out.println("Please select a node!!!"); return; } long begin = System.currentTimeMillis(); // ClientContext.setEventDeliveryMode(this, // UlcEventCategories.TREE_EXPANSION_EVENT_CATEGORY, // ClientContext.ASYNCHRONOUS_MODE); //ClientContext.DEFERRED_MODE); IMutableTableTreeNode node = (IMutableTableTreeNode)getSelectedPath().getLastPathComponent(); if (!node.isLeaf()){ fullExpand(node); } // ClientContext.setEventDeliveryMode(this, // UlcEventCategories.TREE_EXPANSION_EVENT_CATEGORY, // ClientContext.SYNCHRONOUS_MODE); long end = System.currentTimeMillis(); System.out.println("server.fullExpandSelectedObject() took '"+(end-begin)+"ms'"); } private void fullExpand(IMutableTableTreeNode parentNode) { try { int nok = this.getModel().getChildCount(parentNode); for(int i=0; i<nok; i++) { IMutableTableTreeNode kidNode = (IMutableTableTreeNode) this.getModel().getChild(parentNode, i); TreePath tp = this.getTreePath(kidNode); expandPath(tp); fullExpand(kidNode); } } catch (IllegalStateException e) { throw new RuntimeException(e); } } private TreePath getTreePath(Object instance) { if (instance==null) throw new IllegalStateException("Der Tree ist leer."); List treePathObjects = getTreePath0((IMutableTableTreeNode)this.getModel().getRoot(), instance); if (treePathObjects==null) throw new IllegalStateException("Die Instanz "+instance+" kommt im TableTreeModel nicht vor."); Object[] treePathArray = treePathObjects.toArray(); return new TreePath(treePathArray); } private List getTreePath0(IMutableTableTreeNode node, Object instance) { if (instance.equals(node)) { List treePathObjects = new ArrayList(); treePathObjects.add(0, node); return treePathObjects; } else { for (int i = 0; i < node.getChildCount(); i++) { List treePathObjects = getTreePath0((IMutableTableTreeNode)node.getChildAt(i), instance); if (treePathObjects!=null) { treePathObjects.add(0,node); return treePathObjects; } } return null; } } private void collapseAll(){ int row = 1; //the root node keeps open... while (row < this.getRowCount()) { this.collapseRow(row); row++; } } protected String typeString() { return MyUITableTree.class.getName(); } public AbstractAction getExpandInMultipleRoundTripsAction() { return expandInMultipleRoundTripsAction; } public AbstractAction getExpandOnClientAction() { return expandOnClientAction; } public AbstractAction getExpandOnServerAction() { return expandOnServerAction; } public AbstractAction getCollapseAllAction() { return collapseAllAction; } } public static class MyUITableTree extends UITableTree { //to open the nodes on the UI side is not usefull because not the //data of the invisible nodes must first uploaded. /** * Der selektierte Node und alle seine Kinder werden geöffnet. */ public void fullExpandSelectedObject() { long begin = System.currentTimeMillis(); if(null == this.getBasicTableTree().getSelectedPath()){ System.out.println("Please select a node!!!"); return; } Object node = this.getBasicTableTree().getSelectedPath().getLastPathComponent(); fullExpand(node); long end = System.currentTimeMillis(); System.out.println("client.fullExpandSelectedObject() took '"+(end-begin)+"ms'"); } private void fullExpand(Object parentNode) { try { int childCount = this.getBasicTableTree().getModel().getChildCount(parentNode); for(int i=0; i<childCount; i++) { Object kidNode = this.getBasicTableTree().getModel().getChild(parentNode, i); javax.swing.tree.TreePath tp = this.getTreePath(kidNode); this.getBasicTableTree().expandPath(tp); fullExpand(kidNode); } } catch (IllegalStateException e) { throw new RuntimeException(e); } } private javax.swing.tree.TreePath getTreePath(Object instance) throws IllegalStateException { if (instance==null) throw new IllegalStateException("Der Tree ist leer."); List treePathObjects = getTreePath0(this.getBasicTableTree().getModel().getRoot(), instance); if (treePathObjects==null) throw new IllegalStateException("Die Instanz "+instance+" kommt im TableTreeModel nicht vor."); Object[] treePathArray = treePathObjects.toArray(); return new javax.swing.tree.TreePath(treePathArray); } private List getTreePath0(Object node, Object instance) { if (instance.equals(node)) { List treePathObjects = new ArrayList(); treePathObjects.add(0,node); return treePathObjects; } else { for (int i = 0; i < this.getBasicTableTree().getModel().getChildCount(node); i++) { List treePathObjects = getTreePath0(this.getBasicTableTree().getModel().getChild(node,i), instance); if (treePathObjects!=null) { treePathObjects.add(0,node); return treePathObjects; } } return null; } } } public class MyTableTreeNode implements IMutableTableTreeNode { private IMutableTableTreeNode parent = null; private ArrayList children = new ArrayList(); private int COLUMN_NAME = 0; private int COLUMN_DATE = 1; private String name = null; private String date = null; public MyTableTreeNode(String name, String rechtsgrund){ this.name = name; this.date = rechtsgrund; } public void setValueAt(Object arg0, int arg1) { throw new UnsupportedOperationException(this.getClass().getName()); } public void insert(IMutableTableTreeNode arg0, int arg1) { children.add(arg1,arg0); } public void remove(int arg0) { throw new UnsupportedOperationException(this.getClass().getName()); } public void setParent(IMutableTableTreeNode arg0) { this.parent = arg0; } public boolean isCellEditable(int arg0) { return false; } public ITableTreeNode getChildAt(int arg0) { return (ITableTreeNode)children.get(arg0); } public int getChildCount() { return children.size(); } public ITableTreeNode getParent() { return this.parent; } public int getIndex(ITableTreeNode arg0) { return children.indexOf(arg0); } public Object getValueAt(int arg0) { if(arg0 == COLUMN_NAME){ return name; } else if(arg0 == COLUMN_DATE){ return date; } else { throw new UnsupportedOperationException(this.getClass().getName()); } } public boolean isLeaf() { return children.size()==0; } } } import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.WeakHashMap; import com.ulcjava.base.application.ULCComponent; import com.ulcjava.base.application.ULCContainer; import com.ulcjava.base.application.ULCFrame; import com.ulcjava.base.application.ULCRootPane; import com.ulcjava.base.application.ULCScrollPane; import com.ulcjava.base.application.ULCTableTree; import com.ulcjava.base.application.ULCWindow; import com.ulcjava.base.application.event.IRoundTripListener; import com.ulcjava.base.application.event.ITableTreeModelListener; import com.ulcjava.base.application.event.RoundTripEvent; import com.ulcjava.base.application.event.TableTreeModelEvent; import com.ulcjava.base.application.tabletree.ITableTreeModel; import com.ulcjava.base.application.tree.TreePath; import com.ulcjava.base.server.ULCTableTreeModelAdapter; import com.ulcjava.base.shared.internal.Anything; public class EagerLoadingTableTreeHandler implements IRoundTripListener, ITableTreeModelListener { private transient WeakHashMap fEagerTables; private transient WeakHashMap fEagerTableModels; public EagerLoadingTableTreeHandler() { fEagerTables = new WeakHashMap(); fEagerTableModels = new WeakHashMap(); } public void roundTripDidStart(RoundTripEvent event) { /* noop */ } public void roundTripWillEnd(RoundTripEvent event) { System.out.println(this.getClass().getName() + ".roundTripWillEnd()"); visit(new EagerAddVisitor()); } private void visit(IComponentVisitor visitor) { List rootPanes = new ArrayList(); rootPanes.addAll(Arrays.asList(ULCFrame.getFrames())); for (int i = 0; i < rootPanes.size(); i++) { ULCWindow window = (ULCWindow)rootPanes.get(i); rootPanes.addAll(Arrays.asList(window.getOwnedWindows())); } // we don't always have the applet pane // -> do the applet pane case with help of reflection! try { Class appletPaneClass = Class.forName("com.ulcjava.environment.applet.application.ULCAppletPane"); Method getInstanceMethod = appletPaneClass.getMethod("getInstance", new Class[0]); rootPanes.add(getInstanceMethod.invoke(null, new Object[0])); } catch (Exception ignored) { /* noop */ } for (Iterator i = rootPanes.iterator(); i.hasNext();) { visit((ULCRootPane)i.next(), visitor); } } private void visit(ULCComponent component, IComponentVisitor visitor) { visitor.visit(component); if (component instanceof ULCContainer) { ULCContainer container = (ULCContainer)component; ULCComponent[] components = container.getComponents(); for (int i = 0; i < components.length; i++) { visit(components[i], visitor); } } } private static int getFirstRow(ULCTableTree tableTree) { if (tableTree.getParent() instanceof ULCScrollPane) { ULCScrollPane scrollPane = (ULCScrollPane)tableTree.getParent(); double verticalPosition = scrollPane.getVerticalScrollBar().getPosition(); int firstVisibleRow = (int)(tableTree.getRowCount() * verticalPosition) - 50; return Math.max(0, firstVisibleRow); } else { return 0; } } private static int getLastRow(ULCTableTree tableTree) { if (tableTree.getParent() instanceof ULCScrollPane) { ULCScrollPane scrollPane = (ULCScrollPane)tableTree.getParent(); double verticalPosition = scrollPane.getVerticalScrollBar().getPosition(); int firstVisibleRow = (int)(tableTree.getRowCount() * verticalPosition) - 50; int lastVisibleRow = firstVisibleRow + 3 * 50; return Math.min(lastVisibleRow, tableTree.getRowCount() - 1); } else { return tableTree.getRowCount() - 1; } } private static void eagerSetData(ULCTableTreeModelAdapter modelAdapter, TreePath firstRow, TreePath lastRow, int[] columns) { int[] firstDescription = modelAdapter.getDescriptionForPath(firstRow); int[] lastDescription = modelAdapter.getDescriptionForPath(lastRow); Anything args = new Anything(); args.put("descriptions", new int[][]{firstDescription, lastDescription}); args.put("columns", columns); System.out.println(EagerLoadingTableTreeHandler.class + ".eagerSetData() requestData : args = '"+ args.toString() + "'"); modelAdapter.handleRequest("requestData", args); } private static void eagerSetCellRendererComponents(ULCTableTree tableTree, int firstRow, int lastRow, int[] columns) { Anything args = new Anything(); args.put("descriptions", new int[]{firstRow, lastRow}); args.put("columns", columns); tableTree.handleRequest("requestCellRendererComponents", args); } private static void eagerSetCellEditorComponents(ULCTableTree tableTree, int firstRow, int lastRow, int[] columns) { Anything args = new Anything(); args.put("descriptions", new int[]{firstRow, lastRow}); args.put("columns", columns); tableTree.handleRequest("requestCellEditorComponents", args); } private static void eagerSetHeaderRendererComponents(ULCTableTree tableTree, int[] columns) { Anything args = new Anything(); args.put("columns", columns); tableTree.handleRequest("requestHeaderRendererComponents", args); } private static int[] getAllColumns(ULCTableTree tableTree) { int[] result = new int[tableTree.getColumnCount()]; for (int i = 0; i < result.length; i++) { result[i] = tableTree.convertColumnIndexToModel(i); } return result; } // private static int[] getRendererColumns(ULCTableTree tableTree) { // int[] tmpResult = new int[tableTree.getColumnCount()]; // int tmpCount = 0; // for (int i = 0; i < tableTree.getColumnCount(); i++) { // if (tableTree.getColumnModel().getColumn(i).getCellRenderer() != null || tableTree.getDefaultRenderer(tableTree.getColumnClass(i)) != null) // { // tmpResult[tmpCount] = i; // tmpCount++; // } // } // // int[] result = new int[tmpCount]; // System.arraycopy(tmpResult, 0, result, 0, result.length); // return result; // } // private static int[] getEditorColumns(ULCTableTree tableTree) { // int[] tmpResult = new int[tableTree.getColumnCount()]; // int tmpCount = 0; // for (int i = 0; i < tableTree.getColumnCount(); i++) { // if (tableTree.getColumnModel().getColumn(i).getCellEditor() != null || tableTree.getDefaultEditor(tableTree.getColumnClass(i)) != null) // { // tmpResult[tmpCount] = i; // tmpCount++; // } // } // // int[] result = new int[tmpCount]; // System.arraycopy(tmpResult, 0, result, 0, result.length); // return result; // } // private static int[] getHeaderColumns(ULCTableTree tableTree) { // int[] tmpResult = new int[tableTree.getColumnCount()]; // int tmpCount = 0; // for (int i = 0; i < tableTree.getColumnCount(); i++) { // if (tableTree.getColumnModel().getColumn(i).getHeaderRenderer() != null || tableTree.getTableHeader() != null && tableTree.getTableHeader().getDefaultRenderer() != null) // { // tmpResult[tmpCount] = i; // tmpCount++; // } // } // // int[] result = new int[tmpCount]; // System.arraycopy(tmpResult, 0, result, 0, result.length); // return result; // } private static interface IComponentVisitor { public void visit(ULCComponent component); } private class EagerAddVisitor implements IComponentVisitor { public void visit(ULCComponent component) { if (component instanceof ULCTableTree) { ULCTableTree tableTree = (ULCTableTree)component; if (!fEagerTables.containsKey(tableTree)) { fEagerTables.put(tableTree, null); int firstRow = getFirstRow(tableTree); int lastRow = getLastRow(tableTree); // eagerSetCellRendererComponents(tableTree, firstRow, lastRow, getRendererColumns(tableTree)); // eagerSetCellEditorComponents(tableTree, firstRow, lastRow, getEditorColumns(tableTree)); // eagerSetHeaderRendererComponents(tableTree, getHeaderColumns(tableTree)); } if (!fEagerTableModels.containsKey(tableTree.getModel())) { fEagerTableModels.put(tableTree.getModel(), null); tableTree.getModel().addTableTreeModelListener(EagerLoad ingTableTreeHandler.this); TreePath firstRow = tableTree.getPathForRow(getFirstRow(tableTree)); TreePath lastRow = tableTree.getPathForRow(getLastRow(tableTree)); eagerSetData(ULCTableTreeModelAdapter.getInstance(tableT ree.getModel()), firstRow, lastRow, getAllColumns(tableTree)); } } } } private class EagerRemoveVisitor implements IComponentVisitor { private ITableTreeModel fModel; public EagerRemoveVisitor(ITableTreeModel model) { fModel = model; } public void visit(ULCComponent component) { if (component instanceof ULCTableTree) { ULCTableTree tableTree = (ULCTableTree)component; if (tableTree.getModel() == fModel) { fEagerTables.remove(tableTree); fEagerTableModels.remove(fModel); fModel.removeTableTreeModelListener(EagerLoadingTableTre eHandler.this); } } } } public void tableTreeChanged(TableTreeModelEvent event) { // trick: remove both, the source tableTree(s) and it's model from the eager lists // -> tableTree and tableTree model is again eagerly loaded! visit(new EagerRemoveVisitor((ITableTreeModel)event.getSource())); } public void tableTreeStructureChanged(TableTreeModelEvent arg0) { tableTreeChanged(arg0); } public void tableTreeNodeStructureChanged(TableTreeModelEvent arg0) { tableTreeChanged(arg0); } public void tableTreeNodesInserted(TableTreeModelEvent arg0) { tableTreeChanged(arg0); } public void tableTreeNodesRemoved(TableTreeModelEvent arg0) { tableTreeChanged(arg0); } public void tableTreeNodesChanged(TableTreeModelEvent arg0) { tableTreeChanged(arg0); } } Alex Stucki Bedag Informatik AG Software-Entwicklung Gutenbergstrasse 1 3011 Bern Telefon: +41 (0)31 633 21 21 (direkt 633 25 35) E-Mail: mailto:[EMAIL PROTECTED] www.bedag.ch _______________________________________________ ULC-developer mailing list [email protected] http://lists.canoo.com/mailman/listinfo/ulc-developer
